CUBRID Engine  latest
execute_schema.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_schema.c
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdarg.h>
28 #include <ctype.h>
29 #include <assert.h>
30 
31 #include "authenticate.h"
32 #include "error_manager.h"
33 #include "parser.h"
34 #include "parser_message.h"
35 #include "db.h"
36 #include "dbi.h"
37 #include "semantic_check.h"
38 #include "execute_schema.h"
39 #include "execute_statement.h"
40 #include "schema_manager.h"
41 #include "transaction_cl.h"
42 #include "system_parameter.h"
43 #if defined(WINDOWS)
44 #include "misc_string.h"
45 #endif /* WINDOWS */
46 #include "semantic_check.h"
47 #include "xasl_generation.h"
48 #include "memory_alloc.h"
49 #include "transform.h"
50 #include "set_object.h"
51 #include "object_accessor.h"
52 #include "object_primitive.h"
53 #include "object_representation.h"
54 #include "memory_hash.h"
55 #include "locator_cl.h"
56 #include "network_interface_cl.h"
57 #include "view_transform.h"
58 #include "xasl_to_stream.h"
59 #include "parser_support.h"
60 #include "dbtype.h"
61 
62 #if defined (SUPPRESS_STRLEN_WARNING)
63 #define strlen(s1) ((int) strlen(s1))
64 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
65 
66 #define UNIQUE_SAVEPOINT_ADD_ATTR_MTHD "aDDaTTRmTHD"
67 #define UNIQUE_SAVEPOINT_CREATE_ENTITY "cREATEeNTITY"
68 #define UNIQUE_SAVEPOINT_DROP_ENTITY "dROPeNTITY"
69 #define UNIQUE_SAVEPOINT_REPLACE_VIEW "rEPlACE"
70 #define UNIQUE_SAVEPOINT_RENAME "rENAME"
71 #define UNIQUE_SAVEPOINT_MULTIPLE_ALTER "mULTIPLEaLTER"
72 #define UNIQUE_SAVEPOINT_TRUNCATE "tRUnCATE"
73 #define UNIQUE_SAVEPOINT_CHANGE_ATTR "cHANGEaTTR"
74 #define UNIQUE_SAVEPOINT_ALTER_INDEX "aLTERiNDEX"
75 #define UNIQUE_SAVEPOINT_CHANGE_DEF_COLL "cHANGEdEFAULTcOLL"
76 #define UNIQUE_SAVEPOINT_CHANGE_TBL_COMMENT "cHANGEtBLcOMMENT"
77 #define UNIQUE_SAVEPOINT_CHANGE_COLUMN_COMMENT "cHANGEcOLUMNcOMMENT"
78 #define UNIQUE_SAVEPOINT_CREATE_USER_ENTITY "cREATEuSEReNTITY"
79 #define UNIQUE_SAVEPOINT_DROP_USER_ENTITY "dROPuSEReNTITY"
80 #define UNIQUE_SAVEPOINT_ALTER_USER_ENTITY "aLTERuSEReNTITY"
81 #define UNIQUE_SAVEPOINT_GRANT_USER "gRANTuSER"
82 #define UNIQUE_SAVEPOINT_REVOKE_USER "rEVOKEuSER"
83 
84 #define QUERY_MAX_SIZE 1024 * 1024
85 #define MAX_FILTER_PREDICATE_STRING_LENGTH 255
86 
87 typedef enum
88 {
90 } DO_INDEX;
91 
92 typedef enum
93 {
97  SM_ATTR_CHG_BEST_EFFORT = 3 /* same as SM_ATTR_CHG_WITH_ROW_UPDATE, but there is a significant chance that the
98  * operation will fail */
100 
101 /* The ATT_CHG_XXX enum bit flags describe the status of an attribute specific
102  * property (sm_attr_properties_chg). Each property is initialized with
103  * 'ATT_CHG_PROPERTY_NOT_CHECKED' value, and keeps it until is marked as
104  * checked (by setting to zero) and then set corresponding bits.
105  * '_OLD' and '_NEW' flags track simple presence of property in the attribute
106  * existing schema and new definition, while the upper values flags are set
107  * upon more cross-checkings. Some flags applies only to certain properties
108  * (like '.._TYPE_..' for domain of attribute)
109  * !! Values in enum should be kept in this order as some internal checks
110  * rely on the order !!*/
111 enum
112 {
113  /* property present in existing schema */
115  /* property present in new attribute definition */
117  /* present in OLD , lost in NEW */
119  /* not present in OLD , gained in NEW */
121  /* property is not changed (not present in both current schema or new defition or present in both but not affected in
122  * any way) */
124  /* property is changed (i.e.: both present in old an new , but different) */
126  /* type : precision increase : varchar(2) -> varchar (10) */
128  /* type : for COLLECTION or OBJECT (Class) type : the new SET is more general (the new OBJECT is a super-class) */
130  /* type : upgrade : int -> bigint */
132  /* type : changed, but needs checking if new domain supports all existing values , i.e : int -> char(3) */
134  /* type : pseudo-upgrade : datetime -> time: this is succesful as a cast, but may fail due to unique constraint */
136  /* type : not supported with existing configuration */
138  /* type : upgrade : not supported */
140  /* property was not checked needs to be the highest value in enum */
142 };
143 
144 /* Enum to access array from 'sm_attr_properties_chg' struct
145  */
146 enum
147 {
148  P_NAME = 0, /* name of attribute */
149  P_NOT_NULL, /* constraint NOT NULL */
150  P_DEFAULT_VALUE, /* DEFAULT VALUE of attribute */
151  P_ON_UPDATE_EXPR, /* ON UPADTE default of attribute */
152  P_CONSTR_CHECK, /* constraint CHECK */
153  P_DEFFERABLE, /* DEFFERABLE */
154  P_ORDER, /* ORDERING definition */
155  P_AUTO_INCR, /* has AUTO INCREMENT */
156  P_CONSTR_FK, /* constraint FOREIGN KEY */
157  P_S_CONSTR_PK, /* constraint PRIMARY KEY only on one single column : the checked attribute */
158  P_M_CONSTR_PK, /* constraint PRIMARY KEY on more columns, including checked attribute */
159  P_S_CONSTR_UNI, /* constraint UNIQUE only on one single column : the checked attribute */
160  P_M_CONSTR_UNI, /* constraint UNIQUE on more columns, including checked attribute */
161  P_CONSTR_NON_UNI, /* has a non-unique index defined on it, should apply only for existing schema (as you
162  * cannot add a non-index with ALTER CHANGE) */
163  P_PREFIX_INDEX, /* has a prefix index defined on it, should apply only for existing schema (as you
164  * cannot add a prefix index with ALTER CHANGE) */
165  P_TYPE, /* type (domain) change */
166  P_IS_PARTITION_COL, /* class has partitions */
167  P_COMMENT, /* has comment */
169 };
170 
171 /* sm_attr_properties_chg :
172  * structure used for checking existing attribute definition (from schema)
173  * and new attribute definition
174  * Array is accessed using enum values define above.
175  */
178 {
179  int p[NUM_ATT_CHG_PROP]; /* 'change' property */
182  int att_id;
183  SM_NAME_SPACE name_space; /* class, shared or normal attribute */
184  SM_NAME_SPACE new_name_space; /* class, shared or normal attribute */
185  bool class_has_subclass; /* if class is part of a hierarchy and if it has subclasses */
186 };
187 
188 /* sm_partition_alter_info :
189  * helper object for altering partitioning
190  */
193 {
194  MOP root_op; /* MOP of the root class */
195  DB_CTMPL *root_tmpl; /* template of the root class */
196  char keycol[DB_MAX_IDENTIFIER_LENGTH]; /* partition key column */
197  char **promoted_names; /* promoted partition names */
198  int promoted_count; /* number of promoted partition */
199 };
200 
201 /* part_class_info :
202  * structure used for creating partitions for a class
203  */
206 {
207  char *pname; /* partition name */
208  DB_CTMPL *temp; /* partition class template for */
209  DB_OBJECT *obj; /* partition class obj */
211 };
212 
213 /* db_value_slist :
214  * partition range definition list
215  */
218 {
220  SM_PARTITION *partition; /* partition info */
221  MOP class_obj; /* class object */
222  DB_VALUE *min; /* min range for partition */
223  DB_VALUE *max; /* max range for partition */
224 };
225 
226 static int drop_class_name (const char *name, bool is_cascade_constraints);
227 
229 static int do_alter_clause_rename_entity (PARSER_CONTEXT * const parser, PT_NODE * const alter);
230 static int do_alter_clause_add_index (PARSER_CONTEXT * const parser, PT_NODE * const alter);
231 static int do_alter_clause_drop_index (PARSER_CONTEXT * const parser, PT_NODE * const alter);
232 static int do_alter_change_auto_increment (PARSER_CONTEXT * const parser, PT_NODE * const alter);
233 
234 static int do_rename_internal (const char *const old_name, const char *const new_name);
235 static DB_CONSTRAINT_TYPE get_reverse_unique_index_type (const bool is_reverse, const bool is_unique);
236 static int create_or_drop_index_helper (PARSER_CONTEXT * parser, const char *const constraint_name,
237  const bool is_reverse, const bool is_unique, PT_NODE * spec,
238  PT_NODE * column_names, PT_NODE * column_prefix_length,
239  PT_NODE * filter_predicate, int func_index_pos, int func_index_args_count,
240  PT_NODE * function_expr, PT_NODE * comment, DB_OBJECT * const obj,
241  SM_INDEX_STATUS index_status, DO_INDEX do_index);
242 static int update_locksets_for_multiple_rename (const char *class_name, int *num_mops, MOP * mop_set, int *num_names,
243  char **name_set, bool error_on_misssing_class);
244 static int acquire_locks_for_multiple_rename (const PT_NODE * statement);
245 
246 static int validate_attribute_domain (PARSER_CONTEXT * parser, PT_NODE * attribute, const bool check_zero_precision);
248 static int add_foreign_key (DB_CTMPL * ctemplate, const PT_NODE * cnstr, const char **att_names);
249 
250 static int add_union_query (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * query);
251 static int add_query_to_virtual_class (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * queries);
252 static int do_copy_indexes (PARSER_CONTEXT * parser, MOP classmop, SM_CLASS * src_class);
253 
254 static int do_recreate_renamed_class_indexes (const PARSER_CONTEXT * parser, const char *const old_class_name,
255  const char *const class_name);
256 
257 static int do_alter_clause_change_attribute (PARSER_CONTEXT * const parser, PT_NODE * const alter);
258 
259 static int do_alter_change_owner (PARSER_CONTEXT * const parser, PT_NODE * const alter);
260 
261 static int do_alter_change_default_cs_coll (PARSER_CONTEXT * const parser, PT_NODE * const alter);
262 
263 static int do_alter_change_tbl_comment (PARSER_CONTEXT * const parser, PT_NODE * const alter);
264 static int do_alter_change_col_comment (PARSER_CONTEXT * const parser, PT_NODE * const alter);
265 
266 static int do_change_att_schema_only (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attribute,
267  PT_NODE * old_name_node, PT_NODE * constraints, SM_ATTR_PROP_CHG * attr_chg_prop,
268  SM_ATTR_CHG_SOL * change_mode);
269 
270 static int build_attr_change_map (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attr_def,
271  PT_NODE * attr_old_name, PT_NODE * constraints,
272  SM_ATTR_PROP_CHG * attr_chg_properties);
273 
274 static int build_att_type_change_map (TP_DOMAIN * curr_domain, TP_DOMAIN * req_domain,
275  SM_ATTR_PROP_CHG * attr_chg_properties);
276 static int build_att_coll_change_map (TP_DOMAIN * curr_domain, TP_DOMAIN * req_domain,
277  SM_ATTR_PROP_CHG * attr_chg_properties);
278 
279 static int check_att_chg_allowed (const char *att_name, const PT_TYPE_ENUM t, const SM_ATTR_PROP_CHG * attr_chg_prop,
280  SM_ATTR_CHG_SOL chg_how, bool log_error_allowed, bool * new_attempt);
281 
282 static bool is_att_property_structure_checked (const SM_ATTR_PROP_CHG * attr_chg_properties);
283 
284 static bool is_att_change_needed (const SM_ATTR_PROP_CHG * attr_chg_properties);
285 
286 static void reset_att_property_structure (SM_ATTR_PROP_CHG * attr_chg_properties);
287 
288 static bool is_att_prop_set (const int prop, const int value);
289 
290 static int get_att_order_from_def (PT_NODE * attribute, bool * ord_first, const char **ord_after_name);
291 
292 static int check_default_on_update_clause (PARSER_CONTEXT * parser, PT_NODE * attribute);
293 
295  const char *classname);
296 
298 
300 
302  int attr_count, MOP class_mop);
303 
304 static bool is_attribute_primary_key (const char *class_name, const char *attr_name);
305 
306 static const char *get_hard_default_for_type (PT_TYPE_ENUM type);
307 
308 static int do_run_upgrade_instances_domain (PARSER_CONTEXT * parser, OID * p_class_oid, int att_id);
309 
310 static int do_drop_att_constraints (MOP class_mop, SM_CONSTRAINT_INFO * constr_info_list);
311 
312 static int do_recreate_att_constraints (MOP class_mop, SM_CONSTRAINT_INFO * constr_info_list);
313 
314 static int check_change_attribute (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attribute,
315  PT_NODE * old_name_node, PT_NODE ** pointer_constraints,
316  SM_ATTR_PROP_CHG * attr_chg_prop, SM_ATTR_CHG_SOL * change_mode);
317 
318 static int check_change_class_collation (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_ALTER_INFO * alter,
319  bool * need_update, int *collation_id);
320 
321 static int sort_constr_info_list (SM_CONSTRAINT_INFO ** source);
322 static int save_constraint_info_from_pt_node (SM_CONSTRAINT_INFO ** save_info, const PT_NODE * const pt_constr);
323 
324 static int do_run_update_query_for_class (char *query, MOP class_mop, int *row_count);
326  DO_INDEX do_index);
327 
329 static int do_create_partition_constraint (PT_NODE * alter, SM_CLASS * root_class, SM_CLASS_CONSTRAINT * constraint,
330  SM_PARTITION_ALTER_INFO * pinfo);
341 static int do_promote_partition_by_name (const char *class_name, const char *part_num, char **partition_name);
342 static int do_promote_partition (SM_CLASS * class_);
343 #if defined (ENABLE_UNUSED_FUNCTION)
344 static int do_analyze_partition (PARSER_CONTEXT * parser, PT_NODE * alter, SM_PARTITION_ALTER_INFO * pinfo);
345 #endif
346 static int do_redistribute_partitions_data (const char *class_name, const char *keyname, char **promoted,
347  int promoted_count, PT_ALTER_CODE alter_op, bool should_update,
348  bool should_insert);
350 static PT_NODE *replace_names_alter_chg_attr (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg,
351  int *continue_walk);
352 static PT_NODE *pt_replace_names_index_expr (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg,
353  int *continue_walk);
354 static int adjust_partition_range (DB_OBJLIST * objs);
355 static int adjust_partition_size (MOP class_, DB_CTMPL * tmpl);
356 
357 static const char *get_attr_name (PT_NODE * attribute);
358 static int do_add_attribute (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * atts, PT_NODE * constraints,
359  bool error_on_not_normal);
361 static DB_QUERY_TYPE *query_get_column_with_name (DB_QUERY_TYPE * query_columns, const char *name);
362 static PT_NODE *get_attribute_with_name (PT_NODE * atts, const char *name);
363 static PT_NODE *create_select_to_insert_into (PARSER_CONTEXT * parser, const char *class_name, PT_NODE * create_select,
364  PT_CREATE_SELECT_ACTION create_select_action,
365  DB_QUERY_TYPE * query_columns);
366 static int execute_create_select_query (PARSER_CONTEXT * parser, const char *const class_name, PT_NODE * create_select,
367  PT_CREATE_SELECT_ACTION create_select_action, DB_QUERY_TYPE * query_columns,
368  PT_NODE * flagged_statement);
369 
370 static int do_find_auto_increment_serial (MOP * auto_increment_obj, const char *class_name, const char *attr_name);
371 static int do_check_fk_constraints_internal (DB_CTMPL * ctemplate, PT_NODE * constraints, bool is_partitioned);
372 
373 static int get_index_type_qualifiers (MOP obj, bool * is_reverse, bool * is_unique, const char *index_name);
375  char *class_name, char *partition_name, DB_VALUE * minval);
376 static int do_save_all_indexes (MOP classmop, SM_CONSTRAINT_INFO ** saved_index_info_listpp);
377 static int do_drop_saved_indexes (MOP classmop, SM_CONSTRAINT_INFO * index_save_info);
378 static int do_recreate_saved_indexes (MOP classmop, SM_CONSTRAINT_INFO * index_save_info);
379 
380 static int do_alter_index_status (PARSER_CONTEXT * parser, const PT_NODE * statement);
381 
383 
384 /*
385  * Function Group :
386  * DO functions for alter statement
387  *
388  */
389 
390 /*
391  * do_alter_one_clause_with_template() - Executes the operations required by a
392  * single ALTER clause.
393  * return: Error code
394  * parser(in): Parser context
395  * alter(in/out): Parse tree of a single clause of an ALTER statement. Not
396  * all possible clauses are handled by this function; see the
397  * note below and the do_alter() function.
398  *
399  * Note: This function handles clauses that require class template operations.
400  * It always calls dbt_edit_class(). Other ALTER clauses might have
401  * dedicated processing functions. See do_alter() for details.
402  */
403 static int
405 {
406  const char *entity_name, *new_query;
407  const char *attr_name, *mthd_name, *mthd_file, *attr_mthd_name;
408  const char *new_name, *old_name, *domain;
409  DB_CTMPL *ctemplate = NULL;
410  DB_OBJECT *vclass, *sup_class;
411  int error = NO_ERROR;
412  DB_ATTRIBUTE *found_attr, *def_attr;
413  DB_METHOD *found_mthd;
414  TP_DOMAIN *def_domain;
415  DB_VALUE src_val, dest_val;
416  DB_TYPE db_desired_type;
417  int query_no, class_attr;
418  PT_NODE *vlist, *p, *n, *d;
419  PT_NODE *node, *nodelist;
420  PT_NODE *data_type, *data_default, *path;
421  PT_NODE *slist;
422  PT_TYPE_ENUM pt_desired_type;
423  PT_NODE *temp_val, *def_val, *initial_def_val = NULL;
424 #if 0
425  HFID *hfid;
426 #endif
428  bool partition_savepoint = false;
429  const PT_ALTER_CODE alter_code = alter->info.alter.code;
430 #if defined (ENABLE_RENAME_CONSTRAINT)
431  SM_CONSTRAINT_FAMILY constraint_family;
432 #endif
433  unsigned int save_custom;
434  PT_NODE *super_node = NULL;
435  MOP super_class;
436  DB_DEFAULT_EXPR default_expr;
437 
438  entity_name = alter->info.alter.entity_name->info.name.original;
439  if (entity_name == NULL)
440  {
441  ERROR1 (error, ER_UNEXPECTED, "Expecting a class or virtual class name.");
442  return error;
443  }
444 
445  vclass = db_find_class (entity_name);
446  if (vclass == NULL)
447  {
448  assert (er_errid () != NO_ERROR);
449  return er_errid ();
450  }
451 
452  db_make_null (&src_val);
453  db_make_null (&dest_val);
454 
455  ctemplate = dbt_edit_class (vclass);
456  if (ctemplate == NULL)
457  {
458  /* when dbt_edit_class fails (e.g. because the server unilaterally aborts us), we must record the associated
459  * error message into the parser. Otherwise, we may get a confusing error msg of the form: "so_and_so is not a
460  * class". */
461  pt_record_error (parser, parser->statement_number - 1, alter->line_number, alter->column_number, er_msg (), NULL);
462  return er_errid ();
463  }
464 
465  switch (alter_code)
466  {
467  case PT_ADD_QUERY:
468  error = do_add_queries (parser, ctemplate, alter->info.alter.alter_clause.query.query);
469  if (error != NO_ERROR)
470  {
471  break;
472  }
473 
474  /* set vclass comment if it exists */
475  if (alter->info.alter.alter_clause.query.view_comment != NULL)
476  {
477  error = do_alter_change_tbl_comment (parser, alter);
478  }
479  break;
480 
481  case PT_DROP_QUERY:
482  vlist = alter->info.alter.alter_clause.query.query_no_list;
483  if (vlist == NULL)
484  {
485  error = dbt_drop_query_spec (ctemplate, 1);
486  }
487  else if (vlist->next == NULL)
488  { /* ie, only one element in list */
489  error = dbt_drop_query_spec (ctemplate, vlist->info.value.data_value.i);
490  }
491  else
492  {
493  slist = pt_sort_in_desc_order (vlist);
494  for (; slist; slist = slist->next)
495  {
496  error = dbt_drop_query_spec (ctemplate, slist->info.value.data_value.i);
497  if (error != NO_ERROR)
498  {
499  break;
500  }
501  }
502  }
503  break;
504 
505  case PT_MODIFY_QUERY:
506  if (alter->info.alter.alter_clause.query.query_no_list)
507  {
508  query_no = alter->info.alter.alter_clause.query.query_no_list->info.value.data_value.i;
509  }
510  else
511  {
512  query_no = 1;
513  }
514  save_custom = parser->custom_print;
516  new_query = parser_print_tree_with_quotes (parser, alter->info.alter.alter_clause.query.query);
517  parser->custom_print = save_custom;
518  error = dbt_change_query_spec (ctemplate, new_query, query_no);
519  if (error != NO_ERROR)
520  {
521  break;
522  }
523 
524  /* set vclass comment if it exists */
525  if (alter->info.alter.alter_clause.query.view_comment != NULL)
526  {
527  error = do_alter_change_tbl_comment (parser, alter);
528  }
529  break;
530 
531  case PT_ADD_ATTR_MTHD:
532 #if 0
533  /* we currently core dump when adding a unique constraint at the same time as an attribute, whether the unique
534  * constraint is on the new attribute or another. Therefore we temporarily disallow adding a unique constraint
535  * and an attribute in the same alter statement if the class has or has had any instances. Note that we should be
536  * checking for instances in the entire subhierarchy, not just the current class. */
537  if ((hfid = sm_get_ch_heap (vclass)) && !HFID_IS_NULL (hfid)
538  && alter->info.alter.alter_clause.attr_mthd.attr_def_list)
539  {
540  for (p = alter->info.alter.constraint_list; p != NULL; p = p->next)
541  {
543  {
546  (void) dbt_abort_class (ctemplate);
547  return error;
548  }
549  }
550  PT_END;
551  }
552 #endif
554  if (error == NO_ERROR)
555  {
556  error =
557  do_add_attributes (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.attr_def_list,
558  alter->info.alter.constraint_list, NULL);
559  if (error != NO_ERROR)
560  {
561  dbt_abort_class (ctemplate);
563  return error;
564  }
565 
566 
567  vclass = dbt_finish_class (ctemplate);
568  if (vclass == NULL)
569  {
570  assert (er_errid () != NO_ERROR);
571  error = er_errid ();
572  dbt_abort_class (ctemplate);
574  return error;
575  }
576 
577  ctemplate = dbt_edit_class (vclass);
578  if (ctemplate == NULL)
579  {
580  assert (er_errid () != NO_ERROR);
581  error = er_errid ();
583  return error;
584  }
585 
586  error = do_add_constraints (ctemplate, alter->info.alter.constraint_list);
587  if (error != NO_ERROR)
588  {
589  dbt_abort_class (ctemplate);
591  return error;
592  }
593 
594  error = do_check_fk_constraints (ctemplate, alter->info.alter.constraint_list);
595  if (error != NO_ERROR)
596  {
597  (void) dbt_abort_class (ctemplate);
599  return error;
600  }
601 
602  if (alter->info.alter.alter_clause.attr_mthd.mthd_def_list != NULL)
603  {
604  error = do_add_methods (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.mthd_def_list);
605  }
606  if (error != NO_ERROR)
607  {
608  dbt_abort_class (ctemplate);
610  return error;
611  }
612 
613  if (alter->info.alter.alter_clause.attr_mthd.mthd_file_list != NULL)
614  {
615  error = do_add_method_files (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.mthd_file_list);
616  }
617  if (error != NO_ERROR)
618  {
619  dbt_abort_class (ctemplate);
621  return error;
622  }
623 
624  assert (alter->info.alter.create_index == NULL);
625  }
626  break;
627 
628  case PT_RESET_QUERY:
629  {
630  DB_ATTRIBUTE *cur_attr = db_get_attributes (vclass);
631 
632  assert (db_get_subclasses (vclass) == NULL);
633  assert (db_get_superclasses (vclass) == NULL);
634 
635  /* drop all attributes */
636  while (cur_attr)
637  {
638  assert (cur_attr->header.name != NULL);
639  error = dbt_drop_attribute (ctemplate, cur_attr->header.name);
640  if (error != NO_ERROR)
641  {
642  goto reset_query_error;
643  }
644  cur_attr = db_attribute_next (cur_attr);
645  }
646 
647  /* also drop any query specs there may have been */
648  error = dbt_reset_query_spec (ctemplate);
649  if (error != NO_ERROR)
650  {
651  goto reset_query_error;
652  }
653 
654  /* add the new attributes */
655  error =
656  do_add_attributes (parser, ctemplate, alter->info.alter.alter_clause.query.attr_def_list,
657  alter->info.alter.constraint_list, NULL);
658  if (error != NO_ERROR)
659  {
660  goto reset_query_error;
661  }
662 
663  /* and add the single query spec we allow */
664  error = do_add_queries (parser, ctemplate, alter->info.alter.alter_clause.query.query);
665  if (error != NO_ERROR)
666  {
667  goto reset_query_error;
668  }
669 
670  /* set vclass comment if it exists */
671  if (alter->info.alter.alter_clause.query.view_comment != NULL)
672  {
673  error = do_alter_change_tbl_comment (parser, alter);
674  }
675  if (error != NO_ERROR)
676  {
677  goto reset_query_error;
678  }
679 
680  break;
681 
682  reset_query_error:
683  dbt_abort_class (ctemplate);
684  return error;
685  }
686  break;
687 
688  case PT_DROP_ATTR_MTHD:
689  p = alter->info.alter.alter_clause.attr_mthd.attr_mthd_name_list;
690  for (; p && p->node_type == PT_NAME; p = p->next)
691  {
692  attr_mthd_name = p->info.name.original;
693  if (p->info.name.meta_class == PT_META_ATTR)
694  {
695  found_attr = db_get_class_attribute (vclass, attr_mthd_name);
696  if (found_attr)
697  {
698  error = dbt_drop_class_attribute (ctemplate, attr_mthd_name);
699  }
700  else
701  {
702  found_mthd = db_get_class_method (vclass, attr_mthd_name);
703  if (found_mthd)
704  {
705  error = dbt_drop_class_method (ctemplate, attr_mthd_name);
706  }
707  }
708  }
709  else
710  {
711  found_attr = db_get_attribute (vclass, attr_mthd_name);
712  if (found_attr)
713  {
714  error = dbt_drop_attribute (ctemplate, attr_mthd_name);
715  }
716  else
717  {
718  found_mthd = db_get_method (vclass, attr_mthd_name);
719  if (found_mthd)
720  {
721  error = dbt_drop_method (ctemplate, attr_mthd_name);
722  }
723  }
724  }
725 
726  if (error != NO_ERROR)
727  {
728  dbt_abort_class (ctemplate);
729  return error;
730  }
731  }
732 
733  p = alter->info.alter.alter_clause.attr_mthd.mthd_file_list;
734  for (;
735  p && p->node_type == PT_FILE_PATH && (path = p->info.file_path.string) != NULL && path->node_type == PT_VALUE
736  && (path->type_enum == PT_TYPE_VARCHAR || path->type_enum == PT_TYPE_CHAR || path->type_enum == PT_TYPE_NCHAR
737  || path->type_enum == PT_TYPE_VARNCHAR); p = p->next)
738  {
739  mthd_file = (char *) path->info.value.data_value.str->bytes;
740  error = dbt_drop_method_file (ctemplate, mthd_file);
741  if (error != NO_ERROR)
742  {
743  dbt_abort_class (ctemplate);
744  return error;
745  }
746  }
747 
748  break;
749 
750  case PT_MODIFY_ATTR_MTHD:
751  p = alter->info.alter.alter_clause.attr_mthd.attr_def_list;
752  for (; p && p->node_type == PT_ATTR_DEF; p = p->next)
753  {
754  attr_name = p->info.attr_def.attr_name->info.name.original;
756  {
757  class_attr = 1;
758  }
759  else
760  {
761  class_attr = 0;
762  }
763  data_type = p->data_type;
764 
765  domain = pt_node_to_db_domain_name (p);
766  error = dbt_change_domain (ctemplate, attr_name, class_attr, domain);
767 
768  if (data_type && pt_is_set_type (p))
769  {
770  nodelist = data_type->data_type;
771  for (node = nodelist; node != NULL; node = node->next)
772  {
773  domain = pt_data_type_to_db_domain_name (node);
774  error = dbt_add_set_attribute_domain (ctemplate, attr_name, class_attr, domain);
775  if (error != NO_ERROR)
776  {
777  dbt_abort_class (ctemplate);
778  return error;
779  }
780  }
781  }
782 
783  data_default = p->info.attr_def.data_default;
784  if (data_default != NULL && data_default->node_type == PT_DATA_DEFAULT)
785  {
786  pt_desired_type = p->type_enum;
787 
788  if (pt_desired_type == PT_TYPE_BLOB || pt_desired_type == PT_TYPE_CLOB)
789  {
792  break;
793  }
794 
795  /* try to coerce the default value into the attribute's type */
796  d = data_default->info.data_default.default_value;
797  d = pt_semantic_check (parser, d);
798  if (pt_has_error (parser))
799  {
801  dbt_abort_class (ctemplate);
802  return er_errid ();
803  }
804 
805  if (d != NULL)
806  {
807  error = pt_coerce_value (parser, d, d, pt_desired_type, p->data_type);
808  if (error != NO_ERROR)
809  {
810  break;
811  }
812  }
813 
814  pt_evaluate_tree (parser, d, &dest_val, 1);
815  if (pt_has_error (parser))
816  {
818  dbt_abort_class (ctemplate);
819  return er_errid ();
820  }
821 
822  error = dbt_change_default (ctemplate, attr_name, class_attr, &dest_val);
823  if (error != NO_ERROR)
824  {
825  dbt_abort_class (ctemplate);
826  return error;
827  }
828  }
829  }
830 
831  /* the order in which methods are defined will change; currently there's no way around this problem. */
832  p = alter->info.alter.alter_clause.attr_mthd.mthd_def_list;
833  for (; p && p->node_type == PT_METHOD_DEF; p = p->next)
834  {
835  mthd_name = p->info.method_def.method_name->info.name.original;
836  error = dbt_drop_method (ctemplate, mthd_name);
837  if (error == NO_ERROR)
838  {
839  error = do_add_methods (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.mthd_def_list);
840  }
841  if (error != NO_ERROR)
842  {
843  dbt_abort_class (ctemplate);
844  return error;
845  }
846  }
847  break;
848 
849  case PT_ADD_SUPCLASS:
850  /* here we need to check if the super classes are partitioned, as it is not allowed to inherit from partition
851  * tables. */
852  assert (error == NO_ERROR);
853  super_node = alter->info.alter.super.sup_class_list;
854 
855  while (super_node)
856  {
857  super_class = db_find_class (super_node->info.name.original);
858 
859  if (super_class == NULL)
860  {
861  error = er_errid ();
862  assert (error != NO_ERROR);
863  }
864  else
865  {
866  error = sm_is_partitioned_class (super_class);
867  if (error > 0)
868  {
870  error = er_errid ();
871  }
872  }
873 
874  if (error != NO_ERROR)
875  {
876  dbt_abort_class (ctemplate);
877  return error;
878  }
879 
880  super_node = super_node->next;
881  }
882 
883  error = do_add_supers (parser, ctemplate, alter->info.alter.super.sup_class_list);
884  break;
885 
886  case PT_DROP_SUPCLASS:
887  for (p = alter->info.alter.super.sup_class_list; p && p->node_type == PT_NAME; p = p->next)
888  {
889  sup_class = db_find_class (p->info.name.original);
890  if (sup_class == NULL)
891  {
892  assert (er_errid () != NO_ERROR);
893  error = er_errid ();
894  }
895  else
896  {
897  error = dbt_drop_super (ctemplate, sup_class);
898  }
899  if (error != NO_ERROR)
900  {
901  (void) dbt_abort_class (ctemplate);
902  return error;
903  }
904  }
905  break;
906 
907  case PT_DROP_RESOLUTION:
908  for (p = alter->info.alter.super.resolution_list; p && p->node_type == PT_RESOLUTION; p = p->next)
909  {
911  attr_mthd_name = p->info.resolution.attr_mthd_name->info.name.original;
912  error = dbt_drop_resolution (ctemplate, sup_class, attr_mthd_name);
913  if (error != NO_ERROR)
914  {
915  (void) dbt_abort_class (ctemplate);
916  return error;
917  }
918  }
919  break;
920 
921  case PT_MODIFY_DEFAULT:
922  case PT_ALTER_DEFAULT:
923  n = alter->info.alter.alter_clause.ch_attr_def.attr_name_list;
924  d = alter->info.alter.alter_clause.ch_attr_def.data_default_list;
925  for (; n && d; n = n->next, d = d->next)
926  {
927  /* try to coerce the default value into the attribute's type */
928  d = pt_semantic_check (parser, d);
929  if (d == NULL)
930  {
931  if (pt_has_error (parser))
932  {
934  error = er_errid ();
935  }
936  else
937  {
938  error = ER_GENERIC_ERROR;
939  }
940  break;
941  }
942 
943  attr_name = n->info.name.original;
944  if (n->info.name.meta_class == PT_META_ATTR)
945  {
946  def_attr = db_get_class_attribute (vclass, attr_name);
947  }
948  else
949  {
950  def_attr = db_get_attribute (vclass, attr_name);
951  }
952  if (!def_attr || !(def_domain = db_attribute_domain (def_attr)))
953  {
954  assert (er_errid () != NO_ERROR);
955  error = er_errid ();
956  break;
957  }
958  db_desired_type = TP_DOMAIN_TYPE (def_domain);
959  pt_desired_type = (PT_TYPE_ENUM) pt_db_to_type_enum (db_desired_type);
960  data_type = pt_domain_to_data_type (parser, def_domain);
961  if (data_type == NULL)
962  {
964  error = ER_FAILED;
965  break;
966  }
967 
968  def_val = d->info.data_default.default_value;
969  if (d->info.data_default.default_expr_type == DB_DEFAULT_NONE)
970  {
971  initial_def_val = parser_copy_tree (parser, def_val);
972  if (initial_def_val == NULL)
973  {
974  error = ER_FAILED;
975  break;
976  }
977  error = pt_coerce_value_for_default_value (parser, def_val, def_val, pt_desired_type, data_type,
979  if (error != NO_ERROR)
980  {
981  if (pt_has_error (parser))
982  {
983  /* forget previous one to set the better error */
984  pt_reset_error (parser);
985  }
986 
987  if (error == ER_IT_DATA_OVERFLOW)
988  {
990  pt_short_print (parser, initial_def_val), pt_short_print (parser, data_type));
991  }
992  else
993  {
995  pt_short_print (parser, initial_def_val), pt_short_print (parser, data_type));
996  }
997 
998  parser_free_tree (parser, data_type);
999  break;
1000  }
1001 
1002  pt_evaluate_tree (parser, d->info.data_default.default_value, &src_val, 1);
1003 
1004  /* Fix CUBRIDSUS-8035. FOR Primary Key situation, we will throw another ERROR in function
1005  * dbt_change_default, so I excluded it from here. */
1006  if (DB_IS_NULL (&src_val) && (def_attr->flags & SM_ATTFLAG_NON_NULL)
1007  && !(def_attr->flags & SM_ATTFLAG_PRIMARY_KEY))
1008  {
1009  db_value_clear (&src_val);
1010  parser_free_tree (parser, data_type);
1011  ERROR1 (error, ER_CANNOT_HAVE_NOTNULL_DEFAULT_NULL, attr_name);
1012  break;
1013  }
1014 
1015  if (n->info.name.meta_class == PT_META_ATTR)
1016  {
1017  error = dbt_change_default (ctemplate, attr_name, 1, &src_val);
1018  }
1019  else
1020  {
1021  error = dbt_change_default (ctemplate, attr_name, 0, &src_val);
1022  }
1023  }
1024  else
1025  {
1026  def_val = pt_semantic_type (parser, def_val, NULL);
1027  if (pt_has_error (parser) || def_val == NULL)
1028  {
1029  parser_free_tree (parser, data_type);
1030  pt_report_to_ersys (parser, PT_SEMANTIC);
1031  error = er_errid ();
1032  break;
1033  }
1034 
1035  pt_evaluate_tree_having_serial (parser, def_val, &src_val, 1);
1036  if (pt_has_error (parser))
1037  {
1038  parser_free_tree (parser, data_type);
1039  pt_report_to_ersys (parser, PT_SEMANTIC);
1040  error = er_errid ();
1041  break;
1042  }
1043 
1044  temp_val = pt_dbval_to_value (parser, &src_val);
1045  if (temp_val == NULL)
1046  {
1047  parser_free_tree (parser, data_type);
1048  db_value_clear (&src_val);
1049  pt_report_to_ersys (parser, PT_SEMANTIC);
1050  error = er_errid ();
1051  break;
1052  }
1053 
1054  error = pt_coerce_value_for_default_value (parser, temp_val, temp_val, pt_desired_type, data_type,
1056  db_value_clear (&src_val);
1057  temp_val->info.value.db_value_is_in_workspace = 0;
1058  parser_free_node (parser, temp_val);
1059  if (error != NO_ERROR)
1060  {
1061  if (pt_has_error (parser))
1062  {
1063  /* forget previous one to set the better error */
1064  pt_reset_error (parser);
1065  }
1066 
1067  if (error == ER_IT_DATA_OVERFLOW)
1068  {
1070  pt_short_print (parser, def_val), pt_short_print (parser, data_type));
1071  }
1072  else
1073  {
1075  pt_short_print (parser, def_val), pt_short_print (parser, data_type));
1076  }
1077  parser_free_tree (parser, data_type);
1078  break;
1079  }
1080 
1081  pt_get_default_expression_from_data_default_node (parser, d, &default_expr);
1082  smt_set_attribute_default (ctemplate, attr_name, 0, &src_val, &default_expr);
1083  }
1084  if (pt_has_error (parser))
1085  {
1086  pt_report_to_ersys (parser, PT_SEMANTIC);
1087  error = er_errid ();
1088  break;
1089  }
1090 
1091  if (error != NO_ERROR)
1092  {
1093  break;
1094  }
1095 
1096  parser_free_tree (parser, data_type);
1097  pr_clear_value (&src_val);
1098  pr_clear_value (&dest_val);
1099  }
1100  break;
1101 
1102  /* If merely renaming resolution, will be done after switch statement */
1103  case PT_RENAME_RESOLUTION:
1104  break;
1105 
1106  case PT_RENAME_ATTR_MTHD:
1107  if (alter->info.alter.alter_clause.rename.old_name)
1108  {
1109  old_name = alter->info.alter.alter_clause.rename.old_name->info.name.original;
1110  }
1111  else
1112  {
1113  old_name = NULL;
1114  }
1115 
1116  new_name = alter->info.alter.alter_clause.rename.new_name->info.name.original;
1117 
1118  if (alter->info.alter.alter_clause.rename.meta == PT_META_ATTR)
1119  {
1120  class_attr = 1;
1121  }
1122  else
1123  {
1124  class_attr = 0;
1125  }
1126 
1127  switch (alter->info.alter.alter_clause.rename.element_type)
1128  {
1129  case PT_ATTRIBUTE:
1130  case PT_METHOD:
1131  error = dbt_rename (ctemplate, old_name, class_attr, new_name);
1132  break;
1133 
1134  case PT_FUNCTION_RENAME:
1135  mthd_name = alter->info.alter.alter_clause.rename.mthd_name->info.name.original;
1136  error = dbt_change_method_implementation (ctemplate, mthd_name, class_attr, new_name);
1137  break;
1138 
1139  /* the following case is not yet supported, but hey, when it is, there'll code for it :-) */
1140 
1141  /* There's code now. this drops the old file name and puts the new file name in its place., I took out the
1142  * class_attr, since for our purpose we don't need it */
1143 
1144  case PT_FILE_RENAME:
1145  {
1146  PT_NODE *old_name_node, *new_name_node;
1147 
1148  old_name_node = alter->info.alter.alter_clause.rename.old_name;
1149  new_name_node = alter->info.alter.alter_clause.rename.new_name;
1150 
1151  old_name = (char *) old_name_node->info.file_path.string->info.value.data_value.str->bytes;
1152  new_name = (char *) new_name_node->info.file_path.string->info.value.data_value.str->bytes;
1153 
1154  error = dbt_rename_method_file (ctemplate, old_name, new_name);
1155  }
1156  break;
1157 
1158  default:
1159  /* actually, it means that a wrong thing is being renamed, and is really an error condition. */
1160  assert (false);
1161  break;
1162  }
1163  break;
1164 
1165  case PT_DROP_CONSTRAINT:
1166  case PT_DROP_FK_CLAUSE:
1168  {
1169  SM_CLASS_CONSTRAINT *cons = NULL;
1170  const char *constraint_name = NULL;
1171 
1172  if (alter_code == PT_DROP_PRIMARY_CLAUSE)
1173  {
1174  assert (alter->info.alter.constraint_list == NULL);
1175  cons = classobj_find_class_primary_key (ctemplate->current);
1176  if (cons != NULL)
1177  {
1179  constraint_name = cons->name;
1180  }
1181  else
1182  {
1183  /* We set a name to print the error message. */
1184  constraint_name = "primary key";
1185  }
1186  }
1187  else
1188  {
1189  assert (alter->info.alter.constraint_list->next == NULL);
1191  constraint_name = alter->info.alter.constraint_list->info.name.original;
1192  assert (constraint_name != NULL);
1193  cons = classobj_find_class_index (ctemplate->current, constraint_name);
1194  }
1195 
1196  if (cons != NULL)
1197  {
1198  const DB_CONSTRAINT_TYPE constraint_type = db_constraint_type (cons);
1199 
1200  if (alter_code == PT_DROP_FK_CLAUSE && constraint_type != DB_CONSTRAINT_FOREIGN_KEY)
1201  {
1203  error = er_errid ();
1204  }
1205  else
1206  {
1208  {
1209  /* We warn the user that dropping a foreign key behaves differently in CUBRID (the associated index
1210  * is also dropped while MySQL's associated index is kept and only the foreign key constraint is
1211  * dropped). This difference is not important enough to be an error but a warning or a notification
1212  * might help. */
1214  }
1215  error = dbt_drop_constraint (ctemplate, constraint_type, constraint_name, NULL, 0);
1216  }
1217  }
1218  else
1219  {
1221  error = er_errid ();
1222  }
1223  }
1224  break;
1225 
1226  case PT_APPLY_PARTITION:
1227  case PT_REMOVE_PARTITION:
1228  case PT_ADD_PARTITION:
1229  case PT_ADD_HASHPARTITION:
1230  case PT_COALESCE_PARTITION:
1231  case PT_REORG_PARTITION:
1232  case PT_DROP_PARTITION:
1233  case PT_ANALYZE_PARTITION:
1234  case PT_PROMOTE_PARTITION:
1235  /* initialize partition alteration context */
1236  pinfo.promoted_count = 0;
1237  pinfo.promoted_names = NULL;
1238  pinfo.root_tmpl = ctemplate;
1239  pinfo.root_op = vclass;
1240  pinfo.keycol[0] = 0;
1241 
1243  if (error != NO_ERROR)
1244  {
1245  dbt_abort_class (ctemplate);
1246  return error;
1247  }
1248  partition_savepoint = true;
1249 
1250  error = do_alter_partitioning_pre (parser, alter, &pinfo);
1251  break;
1252 
1253 #if defined (ENABLE_RENAME_CONSTRAINT)
1254  case PT_RENAME_CONSTRAINT:
1255  case PT_RENAME_INDEX:
1256 
1257  old_name = alter->info.alter.alter_clause.rename.old_name->info.name.original;
1258  new_name = alter->info.alter.alter_clause.rename.new_name->info.name.original;
1259 
1260  if (alter->info.alter.alter_clause.rename.element_type == PT_CONSTRAINT_NAME)
1261  {
1262  constraint_family = SM_CONSTRAINT_NAME;
1263  }
1264  else /* if (alter->info.alter.alter_clause. rename.element_type == PT_INDEX_NAME) */
1265  {
1266  constraint_family = SM_INDEX_NAME;
1267  }
1268 
1269  error = smt_rename_constraint (ctemplate, old_name, new_name, constraint_family);
1270  break;
1271 #endif
1272 
1273  default:
1274  assert (false);
1275  dbt_abort_class (ctemplate);
1276  return error;
1277  }
1278 
1279  if (initial_def_val != NULL)
1280  {
1281  parser_free_tree (parser, initial_def_val);
1282  }
1283 
1284  /* Process resolution list if appropriate */
1285  if (error == NO_ERROR)
1286  {
1287  if (alter->info.alter.super.resolution_list != NULL && alter->info.alter.code != PT_DROP_RESOLUTION)
1288  {
1289  error = do_add_resolutions (parser, ctemplate, alter->info.alter.super.resolution_list);
1290  }
1291  }
1292 
1293  if (error != NO_ERROR)
1294  {
1295  dbt_abort_class (ctemplate);
1296  if (partition_savepoint)
1297  {
1298  goto alter_partition_fail;
1299  }
1300  return error;
1301  }
1302 
1303  vclass = dbt_finish_class (ctemplate);
1304 
1305  /* the dbt_finish_class() failed, the template was not freed */
1306  if (vclass == NULL)
1307  {
1308  assert (er_errid () != NO_ERROR);
1309  error = er_errid ();
1310  dbt_abort_class (ctemplate);
1311  if (partition_savepoint)
1312  {
1313  goto alter_partition_fail;
1314  }
1315  return error;
1316  }
1317 
1318  /* If we have an ADD COLUMN x NOT NULL without a default value, the existing rows will be filled with NULL for the
1319  * new column by default. For compatibility with MySQL, we can auto-fill some column types with "hard defaults", like
1320  * 0 for integer types. THIS CAN TAKE A LONG TIME (it runs an UPDATE), and can be turned off by setting
1321  * "add_col_not_null_no_default_behavior" to "cubrid". The parameter is true by default. */
1322  if (alter_code == PT_ADD_ATTR_MTHD)
1323  {
1324  error = do_update_new_notnull_cols_without_default (parser, alter, vclass);
1325  if (error != NO_ERROR)
1326  {
1327  if (error != ER_LK_UNILATERALLY_ABORTED)
1328  {
1330  }
1331  return error;
1332  }
1333 
1334  /*
1335  * if we ADD COLUMN with DEFAULT expression the existing rows will be filled with default expression for the
1336  * new column. That's because we need to set the column value right now (the default expression may be date/time).
1337  */
1338  error = do_update_new_cols_with_default_expression (parser, alter, vclass);
1339  if (error != NO_ERROR)
1340  {
1341  if (error != ER_LK_UNILATERALLY_ABORTED)
1342  {
1344  }
1345  return error;
1346  }
1347  }
1348 
1349  switch (alter_code)
1350  {
1351  case PT_APPLY_PARTITION:
1352  case PT_REMOVE_PARTITION:
1353  case PT_ADD_PARTITION:
1354  case PT_ADD_HASHPARTITION:
1355  case PT_COALESCE_PARTITION:
1356  case PT_REORG_PARTITION:
1357  case PT_DROP_PARTITION:
1358  case PT_ANALYZE_PARTITION:
1359  case PT_PROMOTE_PARTITION:
1360  /* root class template has been edited and finished, update the references in the pinfo object */
1361  pinfo.root_op = vclass;
1362  pinfo.root_tmpl = NULL;
1363  error = do_alter_partitioning_post (parser, alter, &pinfo);
1364 
1365  if (pinfo.promoted_names != NULL)
1366  {
1367  /* cleanup promoted names if any */
1368  int i;
1369  for (i = 0; i < pinfo.promoted_count; i++)
1370  {
1371  free_and_init (pinfo.promoted_names[i]);
1372  }
1373  free_and_init (pinfo.promoted_names);
1374  }
1375 
1376  if (error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
1377  {
1378  goto alter_partition_fail;
1379  }
1380  break;
1381 
1382  default:
1383  break;
1384  }
1385  return error;
1386 
1387 alter_partition_fail:
1388  if (partition_savepoint && error != NO_ERROR && error != ER_LK_UNILATERALLY_ABORTED)
1389  {
1391  }
1392  return error;
1393 }
1394 
1395 /*
1396  * do_alter_clause_rename_entity() - Executes an ALTER TABLE RENAME TO clause
1397  * return: Error code
1398  * parser(in): Parser context
1399  * alter(in/out): Parse tree of a PT_RENAME_ENTITY clause potentially
1400  * followed by the rest of the clauses in the ALTER
1401  * statement.
1402  * Note: The clauses following the PT_RENAME_ENTITY clause will be updated to
1403  * the new name of the class.
1404  */
1405 static int
1407 {
1408  int error_code = NO_ERROR;
1409  const PT_ALTER_CODE alter_code = alter->info.alter.code;
1410  const char *const old_name = alter->info.alter.entity_name->info.name.original;
1411  const char *const new_name = alter->info.alter.alter_clause.rename.new_name->info.name.original;
1412  PT_NODE *tmp_clause = NULL;
1413 
1414  assert (alter_code == PT_RENAME_ENTITY);
1415  assert (alter->info.alter.super.resolution_list == NULL);
1416 
1417  error_code = do_rename_internal (old_name, new_name);
1418  if (error_code != NO_ERROR)
1419  {
1420  goto error_exit;
1421  }
1422 
1423  error_code = do_recreate_renamed_class_indexes (parser, old_name, new_name);
1424  if (error_code != NO_ERROR)
1425  {
1426  goto error_exit;
1427  }
1428 
1429  /* We now need to update the current name of the class for the rest of the ALTER clauses. */
1430  for (tmp_clause = alter->next; tmp_clause != NULL; tmp_clause = tmp_clause->next)
1431  {
1432  parser_free_tree (parser, tmp_clause->info.alter.entity_name);
1433  tmp_clause->info.alter.entity_name = parser_copy_tree (parser, alter->info.alter.alter_clause.rename.new_name);
1434  if (tmp_clause->info.alter.entity_name == NULL)
1435  {
1436  error_code = ER_FAILED;
1437  goto error_exit;
1438  }
1439  }
1440 
1441  return error_code;
1442 
1443 error_exit:
1444  return error_code;
1445 }
1446 
1447 /*
1448  * do_alter_clause_add_index() - Executes an ALTER TABLE ADD INDEX clause
1449  * return: Error code
1450  * parser(in): Parser context
1451  * alter(in/out): Parse tree of a PT_ADD_INDEX_CLAUSE clause potentially
1452  * followed by the rest of the clauses in the ALTER
1453  * statement.
1454  * Note: The clauses following the PT_ADD_INDEX_CLAUSE clause are not
1455  * affected in any way.
1456  */
1457 static int
1459 {
1460 
1461  int error = NO_ERROR;
1462  PT_NODE *create_index = NULL;
1463 
1464  assert (alter->info.alter.create_index != NULL);
1465  assert (alter->info.alter.constraint_list == NULL);
1466  assert (alter->info.alter.alter_clause.attr_mthd.attr_def_list == NULL);
1467  assert (alter->info.alter.alter_clause.attr_mthd.mthd_def_list == NULL);
1468  assert (alter->info.alter.alter_clause.attr_mthd.mthd_file_list == NULL);
1469 
1470  create_index = alter->info.alter.create_index;
1471 
1472  for (; create_index != NULL; create_index = create_index->next)
1473  {
1474  error = do_create_index (parser, create_index);
1475  if (error != NO_ERROR)
1476  {
1477  break;
1478  }
1479  }
1480 
1481  return error;
1482 }
1483 
1484 
1485 /*
1486  * do_alter_clause_drop_index() - Executes an ALTER TABLE DROP INDEX clause
1487  * return: Error code
1488  * parser(in): Parser context
1489  * alter(in/out): Parse tree of a PT_DROP_INDEX_CLAUSE clause potentially
1490  * followed by the rest of the clauses in the ALTER
1491  * statement.
1492  * Note: The clauses following the PT_DROP_INDEX_CLAUSE clause are not
1493  * affected in any way.
1494  */
1495 static int
1497 {
1498  int error_code = NO_ERROR;
1499  const PT_ALTER_CODE alter_code = alter->info.alter.code;
1500  DB_OBJECT *obj = NULL;
1501  DB_CONSTRAINT_TYPE index_type;
1502  bool is_reverse;
1503  bool is_unique;
1504 
1505  assert (alter_code == PT_DROP_INDEX_CLAUSE);
1506  assert (alter->info.alter.constraint_list != NULL);
1507  assert (alter->info.alter.constraint_list->next == NULL);
1509 
1510  index_type =
1512  alter->info.alter.alter_clause.index.unique);
1513 
1515  if (obj == NULL)
1516  {
1517  assert (er_errid () != NO_ERROR);
1518  error_code = er_errid ();
1519  return error_code;
1520  }
1521 
1522  if (index_type == DB_CONSTRAINT_INDEX)
1523  {
1524  error_code =
1525  get_index_type_qualifiers (obj, &is_reverse, &is_unique, alter->info.alter.constraint_list->info.name.original);
1526  if (error_code != NO_ERROR)
1527  {
1528  return error_code;
1529  }
1530  }
1531  else
1532  {
1533  is_reverse = alter->info.alter.alter_clause.index.reverse;
1534  is_unique = alter->info.alter.alter_clause.index.unique;
1535  }
1536 
1537  error_code =
1539  is_unique, NULL, NULL, NULL, NULL, -1, 0, NULL, NULL, obj,
1541  return error_code;
1542 }
1543 
1544 
1545 /*
1546  * do_alter_change_auto_increment() - Executes an
1547  * ALTER TABLE ... AUTO_INCREMENT = x statement.
1548  * return: Error code
1549  * parser(in): Parser context
1550  * alter(in/out): Parse tree of a PT_CHANGE_AUTO_INCREMENT clause.
1551  */
1552 
1553 static int
1555 {
1556  const char *entity_name = NULL;
1558  DB_ATTRIBUTE *cur_attr = NULL;
1559  MOP ai_serial = NULL;
1560  int error = NO_ERROR;
1561  int au_save = 0;
1562 
1563  entity_name = alter->info.alter.entity_name->info.name.original;
1564  if (entity_name == NULL)
1565  {
1566  ERROR1 (error, ER_UNEXPECTED, "Expecting a class name.");
1567  goto change_ai_error;
1568  }
1569 
1570  class_obj = db_find_class (entity_name);
1571  if (class_obj == NULL)
1572  {
1573  assert (er_errid () != NO_ERROR);
1574  error = er_errid ();
1575  goto change_ai_error;
1576  }
1577 
1578  cur_attr = db_get_attributes (class_obj);
1579 
1580  /* find the attribute that has auto_increment */
1581  for (cur_attr = db_get_attributes (class_obj); cur_attr != NULL; cur_attr = db_attribute_next (cur_attr))
1582  {
1583  if (cur_attr->auto_increment == NULL)
1584  {
1585  continue;
1586  }
1587  if (ai_serial != NULL)
1588  {
1589  /* we already found a serial. AMBIGUITY! */
1591  goto change_ai_error;
1592  }
1593  else
1594  {
1595  ai_serial = cur_attr->auto_increment;
1596  }
1597  }
1598 
1599  if (ai_serial == NULL)
1600  {
1601  /* we ought to have exactly ONE proper attribute with auto increment */
1603  goto change_ai_error;
1604  }
1605 
1606  AU_DISABLE (au_save);
1607  error =
1608  do_change_auto_increment_serial (parser, ai_serial, alter->info.alter.alter_clause.auto_increment.start_value);
1609  AU_ENABLE (au_save);
1610 
1611 
1612  return error;
1613 
1614 change_ai_error:
1615  return error;
1616 }
1617 
1618 
1619 /*
1620  * do_alter() -
1621  * return: Error code
1622  * parser(in): Parser context
1623  * alter(in/out): Parse tree of an alter statement
1624  */
1625 int
1627 {
1628  int error_code = NO_ERROR;
1629  PT_NODE *crt_clause = NULL;
1630  bool do_semantic_checks = false;
1631  bool do_rollback = false;
1632 
1634 
1635  /* Multiple alter operations in a single statement need to be atomic. */
1637  if (error_code != NO_ERROR)
1638  {
1639  goto error_exit;
1640  }
1641  do_rollback = true;
1642 
1643  for (crt_clause = alter; crt_clause != NULL; crt_clause = crt_clause->next)
1644  {
1645  PT_NODE *const save_next = crt_clause->next;
1646  const PT_ALTER_CODE alter_code = crt_clause->info.alter.code;
1647 
1648  /* The first ALTER clause has already been checked, we call the semantic check starting with the second clause. */
1649  if (do_semantic_checks)
1650  {
1651  PT_NODE *crt_result = NULL;
1652 
1653  crt_clause->next = NULL;
1654  crt_result = pt_compile (parser, crt_clause);
1655  crt_clause->next = save_next;
1656  if (!crt_result || pt_has_error (parser))
1657  {
1658  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, crt_clause);
1659  error_code = er_errid ();
1660  goto error_exit;
1661  }
1662  assert (crt_result == crt_clause);
1663  }
1664 
1665  switch (alter_code)
1666  {
1667  case PT_RENAME_ENTITY:
1668  error_code = do_alter_clause_rename_entity (parser, crt_clause);
1669  break;
1670  case PT_ADD_INDEX_CLAUSE:
1671  error_code = do_alter_clause_add_index (parser, crt_clause);
1672  break;
1673  case PT_DROP_INDEX_CLAUSE:
1674  error_code = do_alter_clause_drop_index (parser, crt_clause);
1675  break;
1677  error_code = do_alter_change_auto_increment (parser, crt_clause);
1678  break;
1679  case PT_CHANGE_ATTR:
1680  error_code = do_alter_clause_change_attribute (parser, crt_clause);
1681  break;
1682  case PT_CHANGE_OWNER:
1683  error_code = do_alter_change_owner (parser, crt_clause);
1684  break;
1685  case PT_CHANGE_COLLATION:
1686  error_code = do_alter_change_default_cs_coll (parser, crt_clause);
1687  break;
1689  error_code = do_alter_change_tbl_comment (parser, crt_clause);
1690  break;
1692  error_code = do_alter_change_col_comment (parser, crt_clause);
1693  break;
1694  default:
1695  /* This code might not correctly handle a list of ALTER clauses so we keep crt_clause->next to NULL during
1696  * its execution just to be on the safe side. */
1697  crt_clause->next = NULL;
1698 
1699  error_code = do_alter_one_clause_with_template (parser, crt_clause);
1700 
1701  crt_clause->next = save_next;
1702  }
1703 
1704  if (error_code != NO_ERROR)
1705  {
1706  goto error_exit;
1707  }
1708  do_semantic_checks = true;
1709  }
1710 
1711  return error_code;
1712 
1713 error_exit:
1714  if (do_rollback && error_code != ER_LK_UNILATERALLY_ABORTED)
1715  {
1717  }
1718 
1719  return error_code;
1720 }
1721 
1722 
1723 
1724 
1725 /*
1726  * Function Group :
1727  * DO functions for user management
1728  *
1729  */
1730 
1731 #define IS_NAME(n) ((n)->node_type == PT_NAME)
1732 #define IS_STRING(n) ((n)->node_type == PT_VALUE && \
1733  ((n)->type_enum == PT_TYPE_VARCHAR || \
1734  (n)->type_enum == PT_TYPE_CHAR || \
1735  (n)->type_enum == PT_TYPE_VARNCHAR || \
1736  (n)->type_enum == PT_TYPE_NCHAR))
1737 #define GET_NAME(n) ((char *) (n)->info.name.original)
1738 #define GET_STRING(n) ((char *) (n)->info.value.data_value.str->bytes)
1739 
1740 /*
1741  * do_grant() - Grants priviledges
1742  * return: Error code if grant fails
1743  * parser(in): Parser context
1744  * statement(in): Parse tree of a grant statement
1745  */
1746 int
1747 do_grant (const PARSER_CONTEXT * parser, const PT_NODE * statement)
1748 {
1749  int error = NO_ERROR;
1750  PT_NODE *user, *user_list;
1751  DB_OBJECT *user_obj, *class_mop;
1752  PT_NODE *auth_cmd_list, *auth_list, *auth;
1753  DB_AUTH db_auth;
1754  PT_NODE *spec_list, *s_list, *spec;
1755  PT_NODE *entity_list, *entity;
1756  int grant_option;
1757  bool set_savepoint = false;
1758 
1760 
1761  user_list = statement->info.grant.user_list;
1762  auth_cmd_list = statement->info.grant.auth_cmd_list;
1763  spec_list = statement->info.grant.spec_list;
1764 
1765  if (statement->info.grant.grant_option == PT_GRANT_OPTION)
1766  {
1767  grant_option = true;
1768  }
1769  else
1770  {
1771  grant_option = false;
1772  }
1773 
1775  if (error != NO_ERROR)
1776  {
1777  return error;
1778  }
1779  set_savepoint = true;
1780 
1781  for (user = user_list; user != NULL; user = user->next)
1782  {
1783  user_obj = db_find_user (user->info.name.original);
1784  if (user_obj == NULL)
1785  {
1786  assert (er_errid () != NO_ERROR);
1787  error = er_errid ();
1788  goto end;
1789  }
1790 
1791  auth_list = auth_cmd_list;
1792  for (auth = auth_list; auth != NULL; auth = auth->next)
1793  {
1794  db_auth = pt_auth_to_db_auth (auth);
1795 
1796  s_list = spec_list;
1797  for (spec = s_list; spec != NULL; spec = spec->next)
1798  {
1799  entity_list = spec->info.spec.flat_entity_list;
1800  for (entity = entity_list; entity != NULL; entity = entity->next)
1801  {
1802  class_mop = db_find_class (entity->info.name.original);
1803  if (class_mop == NULL)
1804  {
1805  assert (er_errid () != NO_ERROR);
1806  error = er_errid ();
1807  goto end;
1808  }
1809 
1810  error = db_grant (user_obj, class_mop, db_auth, grant_option);
1811  if (error != NO_ERROR)
1812  {
1813  goto end;
1814  }
1815  }
1816  }
1817  }
1818  }
1819 
1820 end:
1821  if (set_savepoint && error != NO_ERROR && !ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
1822  {
1824  }
1825 
1826  return error;
1827 }
1828 
1829 /*
1830  * do_revoke() - Revokes priviledges
1831  * return: Error code if revoke fails
1832  * parser(in): Parser context
1833  * statement(in): Parse tree of a revoke statement
1834  */
1835 int
1836 do_revoke (const PARSER_CONTEXT * parser, const PT_NODE * statement)
1837 {
1838  int error = NO_ERROR;
1839 
1840  PT_NODE *user, *user_list;
1841  DB_OBJECT *user_obj, *class_mop;
1842  PT_NODE *auth_cmd_list, *auth_list, *auth;
1843  DB_AUTH db_auth;
1844  PT_NODE *spec_list, *s_list, *spec;
1845  PT_NODE *entity_list, *entity;
1846  bool set_savepoint = false;
1847 
1849 
1850  user_list = statement->info.revoke.user_list;
1851  auth_cmd_list = statement->info.revoke.auth_cmd_list;
1852  spec_list = statement->info.revoke.spec_list;
1853 
1855  if (error != NO_ERROR)
1856  {
1857  return error;
1858  }
1859  set_savepoint = true;
1860 
1861  for (user = user_list; user != NULL; user = user->next)
1862  {
1863  user_obj = db_find_user (user->info.name.original);
1864  if (user_obj == NULL)
1865  {
1866  assert (er_errid () != NO_ERROR);
1867  error = er_errid ();
1868  goto end;
1869  }
1870 
1871  auth_list = auth_cmd_list;
1872  for (auth = auth_list; auth != NULL; auth = auth->next)
1873  {
1874  db_auth = pt_auth_to_db_auth (auth);
1875 
1876  s_list = spec_list;
1877  for (spec = s_list; spec != NULL; spec = spec->next)
1878  {
1879  entity_list = spec->info.spec.flat_entity_list;
1880  for (entity = entity_list; entity != NULL; entity = entity->next)
1881  {
1882  class_mop = db_find_class (entity->info.name.original);
1883  if (class_mop == NULL)
1884  {
1885  assert (er_errid () != NO_ERROR);
1886  error = er_errid ();
1887  goto end;
1888  }
1889 
1890  error = db_revoke (user_obj, class_mop, db_auth);
1891  if (error != NO_ERROR)
1892  {
1893  goto end;
1894  }
1895  }
1896  }
1897  }
1898  }
1899 
1900 end:
1901  if (set_savepoint && error != NO_ERROR && !ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
1902  {
1904  }
1905 
1906  return error;
1907 }
1908 
1909 /*
1910  * do_create_user() - Create a user
1911  * return: Error code if creation fails
1912  * parser(in): Parser context
1913  * statement(in): Parse tree of a create user statement
1914  */
1915 int
1916 do_create_user (const PARSER_CONTEXT * parser, const PT_NODE * statement)
1917 {
1918  int error = NO_ERROR;
1919  DB_OBJECT *user, *group, *member;
1920  int exists;
1921  PT_NODE *node, *node2;
1922  const char *user_name, *password, *comment;
1923  const char *group_name, *member_name;
1924  bool set_savepoint = false;
1925 
1927 
1928  if (parser == NULL || statement == NULL)
1929  {
1931  return ER_OBJ_INVALID_ARGUMENTS;
1932  }
1933 
1934  node = statement->info.create_user.user_name;
1935  if (node == NULL || node->node_type != PT_NAME || node->info.name.original == NULL)
1936  {
1939  }
1940 
1941  user_name = node->info.name.original;
1942  if (user_name == NULL)
1943  {
1944  error = ER_AU_INVALID_USER;
1945  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
1946  return error;
1947  }
1948 
1949  /* first, check if user_name is in group or member clause */
1950  for (node = statement->info.create_user.groups; node != NULL; node = node->next)
1951  {
1952  if (node == NULL || node->node_type != PT_NAME || node->info.name.original == NULL)
1953  {
1956  }
1957 
1958  group_name = node->info.name.original;
1959  if (intl_identifier_casecmp (user_name, group_name) == 0)
1960  {
1963  }
1964  }
1965 
1966  for (node = statement->info.create_user.members; node != NULL; node = node->next)
1967  {
1968  member_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
1969  if (member_name == NULL)
1970  {
1972  return ER_OBJ_INVALID_ARGUMENTS;
1973  }
1974 
1975  if (intl_identifier_casecmp (user_name, member_name) == 0
1976  || intl_identifier_casecmp (member_name, AU_PUBLIC_USER_NAME) == 0)
1977  {
1980  }
1981  }
1982 
1983  /* second, check if group name is in member clause */
1984  for (node = statement->info.create_user.groups; node != NULL; node = node->next)
1985  {
1986  group_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
1987  if (group_name == NULL)
1988  {
1990  return ER_OBJ_INVALID_ARGUMENTS;
1991  }
1992 
1993  for (node2 = statement->info.create_user.members; node2 != NULL; node2 = node2->next)
1994  {
1995  member_name = (node2 && IS_NAME (node2)) ? GET_NAME (node2) : NULL;
1996  if (member_name == NULL)
1997  {
1999  return ER_OBJ_INVALID_ARGUMENTS;
2000  }
2001 
2002  if (intl_identifier_casecmp (group_name, member_name) == 0)
2003  {
2006  }
2007  }
2008  }
2009 
2011  if (error != NO_ERROR)
2012  {
2013  return error;
2014  }
2015  set_savepoint = true;
2016 
2017  exists = 0;
2018  user = db_add_user (user_name, &exists);
2019  if (user == NULL)
2020  {
2021  assert (er_errid () != NO_ERROR);
2022  error = er_errid ();
2023  goto end;
2024  }
2025  else if (exists)
2026  {
2027  error = ER_AU_USER_EXISTS;
2028  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, user_name);
2029  goto end;
2030  }
2031 
2032  /* Now treats optional password, group, member and comment of the created user */
2033 
2034  /* password */
2035  node = statement->info.create_user.password;
2036  password = (node && IS_STRING (node)) ? GET_STRING (node) : NULL;
2037  if (password != NULL)
2038  {
2039  error = au_set_password (user, password);
2040  if (error != NO_ERROR)
2041  {
2042  goto end;
2043  }
2044  }
2045 
2046  /* group */
2047  node = statement->info.create_user.groups;
2048  group_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2049  if (group_name != NULL)
2050  {
2051  do
2052  {
2053  group = db_find_user (group_name);
2054 
2055  if (group == NULL)
2056  {
2057  assert (er_errid () != NO_ERROR);
2058  error = er_errid ();
2059  }
2060  else
2061  {
2062  error = db_add_member (group, user);
2063  }
2064 
2065  if (error != NO_ERROR)
2066  {
2067  goto end;
2068  }
2069 
2070  node = node->next;
2071  group_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2072  }
2073  while (group_name != NULL);
2074  }
2075 
2076  /* member */
2077  node = statement->info.create_user.members;
2078  member_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2079  if (member_name != NULL)
2080  {
2081  do
2082  {
2083  member = db_find_user (member_name);
2084 
2085  if (member == NULL)
2086  {
2087  assert (er_errid () != NO_ERROR);
2088  error = er_errid ();
2089  }
2090  else
2091  {
2092  error = db_add_member (user, member);
2093  }
2094 
2095  if (error != NO_ERROR)
2096  {
2097  goto end;
2098  }
2099 
2100  node = node->next;
2101  member_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2102  }
2103  while (member_name != NULL);
2104  }
2105 
2106  /* comment */
2107  node = statement->info.create_user.comment;
2108  if (node != NULL)
2109  {
2110  assert (node->node_type == PT_VALUE);
2111 
2112  comment = (char *) PT_VALUE_GET_BYTES (node);
2113  error = au_set_user_comment (user, comment);
2114  if (error != NO_ERROR)
2115  {
2116  goto end;
2117  }
2118  }
2119 
2120 end:
2121  if (set_savepoint && error != NO_ERROR && !ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
2122  {
2124  }
2125 
2126  return error;
2127 }
2128 
2129 /*
2130  * do_drop_user() - Drop the user
2131  * return: Error code if dropping fails
2132  * parser(in): Parser context
2133  * statement(in): Parse tree of a drop user statement
2134  */
2135 int
2136 do_drop_user (const PARSER_CONTEXT * parser, const PT_NODE * statement)
2137 {
2138  int error = NO_ERROR;
2139  DB_OBJECT *user = NULL;
2140  PT_NODE *node;
2141  const char *user_name;
2142  bool set_savepoint = false;
2143 
2145 
2146  if (parser == NULL || statement == NULL)
2147  {
2149  return ER_OBJ_INVALID_ARGUMENTS;
2150  }
2151 
2152  node = statement->info.create_user.user_name;
2153  user_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2154 
2155  if (user_name == NULL)
2156  {
2157  error = ER_AU_INVALID_USER;
2158  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
2159  return error;
2160  }
2161 
2162  error = db_find_user_to_drop (user_name, &user);
2163  if (error != NO_ERROR)
2164  {
2165  return error;
2166  }
2167 
2168  assert (user != NULL);
2169 
2171  if (error != NO_ERROR)
2172  {
2173  return error;
2174  }
2175  set_savepoint = true;
2176 
2177  error = db_drop_user (user);
2178 
2179  if (set_savepoint && error != NO_ERROR && !ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
2180  {
2182  }
2183 
2184  return error;
2185 }
2186 
2187 /*
2188  * do_alter_user() - Change the user's password
2189  * return: Error code if alter fails
2190  * parser(in): Parser context
2191  * statement(in): Parse tree of an alter statement
2192  */
2193 int
2194 do_alter_user (const PARSER_CONTEXT * parser, const PT_NODE * statement)
2195 {
2196  int error = NO_ERROR;
2197  DB_OBJECT *user;
2198  PT_NODE *node;
2199  const char *user_name, *password, *comment;
2200  bool set_savepoint = false;
2201 
2203 
2204  if (parser == NULL || statement == NULL)
2205  {
2207  return ER_OBJ_INVALID_ARGUMENTS;
2208  }
2209 
2210  node = statement->info.alter_user.user_name;
2211  user_name = (node && IS_NAME (node)) ? GET_NAME (node) : NULL;
2212 
2213  if (user_name == NULL)
2214  {
2215  error = ER_AU_INVALID_USER;
2216  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
2217  return error;
2218  }
2219 
2220  user = db_find_user (user_name);
2221  if (user == NULL)
2222  {
2223  assert (er_errid () != NO_ERROR);
2224  error = er_errid ();
2225  return error;
2226  }
2227 
2229  if (error != NO_ERROR)
2230  {
2231  return error;
2232  }
2233  set_savepoint = true;
2234 
2235  /*
2236  * here, both password and comment are optional,
2237  * either password or comment shall exist,
2238  * csql_grammar denies the error case with the missing of both.
2239  */
2240 
2241  /* password */
2242  node = statement->info.alter_user.password;
2243  if (node != NULL)
2244  {
2245  password = IS_STRING (node) ? GET_STRING (node) : NULL;
2246  error = au_set_password (user, password);
2247  if (error != NO_ERROR)
2248  {
2249  goto end;
2250  }
2251  }
2252 
2253  /* comment */
2254  node = statement->info.alter_user.comment;
2255  if (node != NULL)
2256  {
2257  assert (node->node_type == PT_VALUE);
2258 
2259  comment = (char *) PT_VALUE_GET_BYTES (node);
2260  error = au_set_user_comment (user, comment);
2261  if (error != NO_ERROR)
2262  {
2263  goto end;
2264  }
2265  }
2266 
2267 end:
2268  if (set_savepoint && error != NO_ERROR && !ER_IS_ABORTED_DUE_TO_DEADLOCK (error))
2269  {
2271  }
2272 
2273  return error;
2274 }
2275 
2276 /*
2277  * Function Group :
2278  * Code for dropping a Classes by Parse Tree descriptions.
2279  *
2280  */
2281 
2282 /*
2283  * drop_class_name() - This static routine drops a class by name.
2284  * return: Error code
2285  * name(in): Class name to drop
2286  * is_cascade_constraints(in): whether drop relative FK constraints
2287  */
2288 static int
2289 drop_class_name (const char *name, bool is_cascade_constraints)
2290 {
2291  DB_OBJECT *class_mop;
2292 
2293  class_mop = db_find_class (name);
2294 
2295  if (class_mop)
2296  {
2297  return db_drop_class_ex (class_mop, is_cascade_constraints);
2298  }
2299  else
2300  {
2301  /* if class is null, return the global error. */
2302  assert (er_errid () != NO_ERROR);
2303  return er_errid ();
2304  }
2305 }
2306 
2307 /*
2308  * do_drop() - Drops a vclass, class
2309  * return: Error code if a vclass is not deleted.
2310  * parser(in): Parser context
2311  * statement(in/out): Parse tree of a drop statement
2312  */
2313 int
2315 {
2316  int error = NO_ERROR;
2317  PT_NODE *entity_spec_list, *entity_spec;
2318  PT_NODE *entity;
2319  PT_NODE *entity_list;
2320 
2322 
2323  /* partitioned sub-class check */
2324  entity_spec_list = statement->info.drop.spec_list;
2325  for (entity_spec = entity_spec_list; entity_spec != NULL; entity_spec = entity_spec->next)
2326  {
2327  entity_list = entity_spec->info.spec.flat_entity_list;
2328  for (entity = entity_list; entity != NULL; entity = entity->next)
2329  {
2331  {
2333  return er_errid ();
2334  }
2335  }
2336  }
2337 
2339  if (error != NO_ERROR)
2340  {
2341  return error;
2342  }
2343 
2344  entity_spec_list = statement->info.drop.spec_list;
2345  for (entity_spec = entity_spec_list; entity_spec != NULL; entity_spec = entity_spec->next)
2346  {
2347  entity_list = entity_spec->info.spec.flat_entity_list;
2348  for (entity = entity_list; entity != NULL; entity = entity->next)
2349  {
2350  error = drop_class_name (entity->info.name.original, statement->info.drop.is_cascade_constraints);
2351  if (error != NO_ERROR)
2352  {
2353  goto error_exit;
2354  }
2355  }
2356  }
2357 
2358  return error;
2359 
2360 error_exit:
2361  if (error != ER_LK_UNILATERALLY_ABORTED)
2362  {
2364  }
2365 
2366  return error;
2367 }
2368 
2369 /*
2370  * update_locksets_for_multiple_rename() - Adds a class name to one of the two
2371  * sets: either names to be reserved
2372  * or classes to be locked
2373  * return: Error code
2374  * class_name(in): A class name involved in a rename operation
2375  * num_mops(in/out): The number of MOPs
2376  * mop_set(in/out): The MOPs to lock before the rename operation
2377  * num_names(in/out): The number of class names
2378  * name_set(in/out): The class names to reserve before the rename operation
2379  * error_on_misssing_class(in/out): Whether to return an error if a class
2380  * with the given class_name is not found
2381  */
2382 int
2383 update_locksets_for_multiple_rename (const char *class_name, int *num_mops, MOP * mop_set, int *num_names,
2384  char **name_set, bool error_on_misssing_class)
2385 {
2386  DB_OBJECT *class_mop = NULL;
2387  char realname[SM_MAX_IDENTIFIER_LENGTH];
2388  int i = 0;
2389 
2390  sm_downcase_name (class_name, realname, SM_MAX_IDENTIFIER_LENGTH);
2391 
2392  class_mop = db_find_class (realname);
2393  if (class_mop == NULL && error_on_misssing_class)
2394  {
2395  assert (er_errid () != NO_ERROR);
2396  return er_errid ();
2397  }
2398 
2399  if (class_mop != NULL)
2400  {
2401  /* Classes that exist are locked. */
2402  /* Duplicates are harmless; they are handled by locator_fetch_set () anyway. */
2403  mop_set[*num_mops] = class_mop;
2404  ++(*num_mops);
2405  }
2406  else
2407  {
2408  /* Class names that don't yet exist are reserved. */
2409  for (i = 0; i < *num_names; ++i)
2410  {
2411  if (intl_identifier_casecmp (name_set[i], realname) == 0)
2412  {
2413  /* The class name is used more than once, we ignore its current occurence. */
2414  return NO_ERROR;
2415  }
2416  }
2417  name_set[*num_names] = strdup (realname);
2418  if (name_set[*num_names] == NULL)
2419  {
2421  (strlen (realname) + 1) * sizeof (char));
2422  return ER_OUT_OF_VIRTUAL_MEMORY;
2423  }
2424  ++(*num_names);
2425  }
2426  return NO_ERROR;
2427 }
2428 
2429 /*
2430  * acquire_locks_for_multiple_rename() - Performs the necessary locking for an
2431  * atomic multiple rename operation
2432  * return: Error code
2433  * statement(in): Parse tree of a rename statement
2434  *
2435  * Note: We need to lock all the classes and vclasses involved in the rename
2436  * operation. When doing multiple renames we preventively lock all the
2437  * names involved in the rename operation. For statements such as:
2438  * RENAME A to tmp, B to A, tmp to B;
2439  * "A" and "B" will be exclusively locked (locator_fetch_set ())
2440  * and the name "tmp" will be reserved for renaming operations
2441  * (locator_reserve_class_names ()).
2442  */
2443 int
2445 {
2446  int error = NO_ERROR;
2447  const PT_NODE *current_rename = NULL;
2448  int num_rename = 0;
2449  int num_mops = 0;
2450  MOP *mop_set = NULL;
2451  int num_names = 0;
2452  char **name_set = NULL;
2453  OID *oid_set = NULL;
2455  LC_FIND_CLASSNAME reserve_result = LC_CLASSNAME_ERROR;
2456  int i = 0;
2457 
2458  num_rename = pt_length_of_list (statement);
2459 
2460  mop_set = (MOP *) malloc (2 * num_rename * sizeof (MOP));
2461  if (mop_set == NULL)
2462  {
2463  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, 2 * num_rename * sizeof (MOP));
2464  error = ER_OUT_OF_VIRTUAL_MEMORY;
2465  goto error_exit;
2466  }
2467  num_mops = 0;
2468 
2469  name_set = (char **) malloc (2 * num_rename * sizeof (char *));
2470  if (name_set == NULL)
2471  {
2472  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, 2 * num_rename * sizeof (char *));
2473  error = ER_OUT_OF_VIRTUAL_MEMORY;
2474  goto error_exit;
2475  }
2476  num_names = 0;
2477 
2478  for (current_rename = statement; current_rename != NULL; current_rename = current_rename->next)
2479  {
2480  const bool is_first_rename = current_rename == statement ? true : false;
2481  const char *old_name = current_rename->info.rename.old_name->info.name.original;
2482  const char *new_name = current_rename->info.rename.new_name->info.name.original;
2483 
2484  bool found = false;
2485 
2486  for (i = 0; i < num_names; i++)
2487  {
2488  if (strcmp (name_set[i], old_name) == 0)
2489  {
2490  found = true;
2491  break;
2492  }
2493  }
2494 
2495  if (!found)
2496  {
2497  error = update_locksets_for_multiple_rename (old_name, &num_mops, mop_set, &num_names, name_set, true);
2498  if (error != NO_ERROR)
2499  {
2500  goto error_exit;
2501  }
2502 
2503  if (is_first_rename)
2504  {
2505  /* We have made sure the first class to be renamed can be locked. */
2506  assert (num_mops == 1);
2507  }
2508  }
2509 
2510  error = update_locksets_for_multiple_rename (new_name, &num_mops, mop_set, &num_names, name_set, false);
2511  if (error != NO_ERROR)
2512  {
2513  goto error_exit;
2514  }
2515  if (is_first_rename && num_names != 1)
2516  {
2518  error = ER_LC_CLASSNAME_EXIST;
2519  goto error_exit;
2520  }
2521  /* We have made sure the first name to be used can be reserved. */
2522  }
2523 
2524  assert (num_mops != 0 && num_names != 0);
2525 
2526  fetch_result = locator_fetch_set (num_mops, mop_set, DB_FETCH_WRITE, DB_FETCH_WRITE, 1);
2527  if (fetch_result == NULL)
2528  {
2530  error = ER_CANNOT_GET_LOCK;
2531  goto error_exit;
2532  }
2533 
2534  oid_set = (OID *) malloc (num_names * sizeof (OID));
2535  if (oid_set == NULL)
2536  {
2537  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, num_names * sizeof (OID));
2538  error = ER_OUT_OF_VIRTUAL_MEMORY;
2539  goto error_exit;
2540  }
2541 
2542  for (i = 0; i < num_names; ++i)
2543  {
2544  /* Each reserved name will point to the OID of the first class to be renamed. This is ok as the associated
2545  * transient table entries will only be used for the multiple rename operation. */
2546  COPY_OID (&oid_set[i], ws_oid (mop_set[0]));
2547  }
2548 
2549  reserve_result = locator_reserve_class_names (num_names, (const char **) name_set, oid_set);
2550  if (reserve_result != LC_CLASSNAME_RESERVED)
2551  {
2553  error = ER_CANNOT_GET_LOCK;
2554  goto error_exit;
2555  }
2556 
2557 error_exit:
2558 
2559  if (oid_set != NULL)
2560  {
2561  assert (num_names > 0);
2562  free_and_init (oid_set);
2563  }
2564  if (name_set != NULL)
2565  {
2566  for (i = 0; i < num_names; ++i)
2567  {
2568  assert (name_set[i] != NULL);
2569  free_and_init (name_set[i]);
2570  }
2571  free_and_init (name_set);
2572  }
2573  if (mop_set != NULL)
2574  {
2575  free_and_init (mop_set);
2576  }
2577  return error;
2578 }
2579 
2580 /*
2581  * do_rename() - Renames several vclasses or classes
2582  * return: Error code
2583  * parser(in): Parser context
2584  * statement(in): Parse tree of a rename statement
2585  */
2586 int
2587 do_rename (const PARSER_CONTEXT * parser, const PT_NODE * statement)
2588 {
2589  int error = NO_ERROR;
2590  const PT_NODE *current_rename = NULL;
2591 
2593 
2594  /* Renaming operations in a single statement need to be atomic. */
2596  if (error != NO_ERROR)
2597  {
2598  return error;
2599  }
2600 
2601  if (statement->next != NULL)
2602  {
2603  error = acquire_locks_for_multiple_rename (statement);
2604  if (error != NO_ERROR)
2605  {
2606  return error;
2607  }
2608  }
2609 
2610  for (current_rename = statement; current_rename != NULL; current_rename = current_rename->next)
2611  {
2612  const char *old_name = current_rename->info.rename.old_name->info.name.original;
2613  const char *new_name = current_rename->info.rename.new_name->info.name.original;
2614 
2615  error = do_rename_internal (old_name, new_name);
2616  if (error != NO_ERROR)
2617  {
2618  goto error_exit;
2619  }
2620 
2621  error = do_recreate_renamed_class_indexes (parser, old_name, new_name);
2622  if (error != NO_ERROR)
2623  {
2624  goto error_exit;
2625  }
2626  }
2627 
2628  return error;
2629 
2630 error_exit:
2631  if (error != ER_LK_UNILATERALLY_ABORTED)
2632  {
2634  }
2635 
2636  return error;
2637 }
2638 
2639 static int
2640 do_rename_internal (const char *const old_name, const char *const new_name)
2641 {
2642  DB_OBJECT *old_class = NULL;
2643 
2644  if (do_is_partitioned_subclass (NULL, old_name, NULL))
2645  {
2647  return er_errid ();
2648  }
2649 
2650  old_class = db_find_class (old_name);
2651  if (old_class == NULL)
2652  {
2653  assert (er_errid () != NO_ERROR);
2654  return er_errid ();
2655  }
2656 
2657  return db_rename_class (old_class, new_name);
2658 }
2659 
2660 /*
2661  * Function Group :
2662  * Parse tree to index commands translation.
2663  *
2664  */
2665 
2666 static DB_CONSTRAINT_TYPE
2667 get_reverse_unique_index_type (const bool is_reverse, const bool is_unique)
2668 {
2669  if (is_unique)
2670  {
2671  return is_reverse ? DB_CONSTRAINT_REVERSE_UNIQUE : DB_CONSTRAINT_UNIQUE;
2672  }
2673  else
2674  {
2675  return is_reverse ? DB_CONSTRAINT_REVERSE_INDEX : DB_CONSTRAINT_INDEX;
2676  }
2677 }
2678 
2679 /*
2680  * create_or_drop_index_helper()
2681  * return: Error code
2682  * parser(in): Parser context
2683  * constraint_name(in): If NULL the default constraint name is used;
2684  * column_names must be non-NULL in this case.
2685  * is_reverse(in):
2686  * is_unique(in):
2687  * column_names(in): Can be NULL if dropping a constraint and providing the
2688  * constraint name.
2689  * column_prefix_length(in):
2690  * where_predicate(in):
2691  * func_index_pos(in):
2692  * func_index_args_count(in):
2693  * function_expr(in):
2694  * comment(in): index comment
2695  * obj(in): Class object
2696  * do_index(in) : The operation to be performed (creating or dropping)
2697  */
2698 static int
2699 create_or_drop_index_helper (PARSER_CONTEXT * parser, const char *const constraint_name, const bool is_reverse,
2700  const bool is_unique, PT_NODE * spec, PT_NODE * column_names,
2701  PT_NODE * column_prefix_length, PT_NODE * where_predicate, int func_index_pos,
2702  int func_index_args_count, PT_NODE * function_expr, PT_NODE * comment,
2703  DB_OBJECT * const obj, SM_INDEX_STATUS index_status, DO_INDEX do_index)
2704 {
2705  int error = NO_ERROR;
2706  int i = 0, nnames = 0;
2708  const PT_NODE *c = NULL, *n = NULL;
2709  char **attnames = NULL;
2710  int *asc_desc = NULL;
2711  int *attrs_prefix_length = NULL;
2712  char *cname = NULL;
2713  char const *colname = NULL;
2714  const char *comment_str = NULL;
2715  bool mysql_index_name = false;
2716  bool free_packing_buff = false;
2717  PRED_EXPR_WITH_CONTEXT *filter_predicate = NULL;
2718  SM_PREDICATE_INFO pred_index_info = { NULL, NULL, 0, NULL, 0 };
2719  SM_PREDICATE_INFO *p_pred_index_info = NULL;
2720  SM_FUNCTION_INFO *func_index_info = NULL;
2721  int is_partition = DB_NOT_PARTITIONED_CLASS;
2722 
2723  error = sm_partitioned_class_type (obj, &is_partition, NULL, NULL);
2724  if (error != NO_ERROR)
2725  {
2726  return error;
2727  }
2728  if (is_partition == DB_PARTITION_CLASS)
2729  {
2732  }
2733 
2734  if (comment != NULL)
2735  {
2736  assert (comment->node_type == PT_VALUE);
2737  comment_str = (char *) PT_VALUE_GET_BYTES (comment);
2738  }
2739 
2740  nnames = pt_length_of_list (column_names);
2741 
2742  if (do_index == DO_INDEX_CREATE && nnames == 1 && column_prefix_length)
2743  {
2744  n = column_names->info.sort_spec.expr;
2745  if (n)
2746  {
2747  colname = n->info.name.original;
2748  }
2749 
2750  if (colname && (sm_att_unique_constrained (obj, colname) || sm_att_fk_constrained (obj, colname)))
2751  {
2753 
2755  }
2756  }
2757 
2758  attnames = (char **) malloc ((nnames + 1) * sizeof (const char *));
2759  if (attnames == NULL)
2760  {
2761  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (nnames + 1) * sizeof (const char *));
2762  return ER_OUT_OF_VIRTUAL_MEMORY;
2763  }
2764 
2765  asc_desc = (int *) malloc ((nnames) * sizeof (int));
2766  if (asc_desc == NULL)
2767  {
2768  free_and_init (attnames);
2769  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, nnames * sizeof (int));
2770  return ER_OUT_OF_VIRTUAL_MEMORY;
2771  }
2772 
2773  if (do_index == DO_INDEX_CREATE)
2774  {
2775  attrs_prefix_length = (int *) malloc ((nnames) * sizeof (int));
2776  if (attrs_prefix_length == NULL)
2777  {
2778  free_and_init (attnames);
2779  free_and_init (asc_desc);
2780  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, nnames * sizeof (int));
2781  return ER_OUT_OF_VIRTUAL_MEMORY;
2782  }
2783  }
2784 
2785  for (c = column_names, i = 0; c != NULL; c = c->next, i++)
2786  {
2787  asc_desc[i] = c->info.sort_spec.asc_or_desc == PT_ASC ? 0 : 1;
2788  /* column name node */
2789  n = c->info.sort_spec.expr;
2790  attnames[i] = (char *) n->info.name.original;
2791  if (do_index == DO_INDEX_CREATE)
2792  {
2793  attrs_prefix_length[i] = -1;
2794  }
2795  }
2796  attnames[i] = NULL;
2797 
2798  if (do_index == DO_INDEX_CREATE && nnames == 1 && attrs_prefix_length && column_prefix_length)
2799  {
2800  attrs_prefix_length[0] = column_prefix_length->info.value.data_value.i;
2801  }
2802 
2803  ctype = get_reverse_unique_index_type (is_reverse, is_unique);
2804 
2806  && constraint_name != NULL && nnames == 0)
2807  {
2808  mysql_index_name = true;
2809  }
2810 
2811  if (function_expr)
2812  {
2814  free_packing_buff = true;
2815  func_index_info = pt_node_to_function_index (parser, spec, function_expr, do_index);
2816  if (func_index_info == NULL)
2817  {
2819  error = ER_FAILED;
2820  goto end;
2821  }
2822  else
2823  {
2824  func_index_info->col_id = func_index_pos;
2825  func_index_info->attr_index_start = nnames - func_index_args_count;
2826  }
2827  }
2828 
2829  cname = sm_produce_constraint_name (sm_get_ch_name (obj), ctype, (const char **) attnames, asc_desc, constraint_name);
2830  if (cname == NULL)
2831  {
2832  assert (er_errid () != NO_ERROR);
2833  error = er_errid ();
2834  }
2835  else
2836  {
2837  if (do_index == DO_INDEX_CREATE)
2838  {
2839  if (where_predicate)
2840  {
2841  PARSER_VARCHAR *filter_expr = NULL;
2842  unsigned int save_custom;
2843 
2844  /* free at parser_free_parser */
2845  /* make sure paren_type is 0 so parenthesis are not printed */
2846  where_predicate->info.expr.paren_type = 0;
2847  save_custom = parser->custom_print;
2849  filter_expr = pt_print_bytes ((PARSER_CONTEXT *) parser, (PT_NODE *) where_predicate);
2850  parser->custom_print = save_custom;
2851  if (filter_expr)
2852  {
2853  pred_index_info.pred_string = (char *) filter_expr->bytes;
2855  {
2857  PT_ERRORmf ((PARSER_CONTEXT *) parser, where_predicate, MSGCAT_SET_ERROR,
2859  goto end;
2860  }
2861  }
2862 
2864  free_packing_buff = true;
2865  filter_predicate =
2866  pt_to_pred_with_context ((PARSER_CONTEXT *) parser, (PT_NODE *) where_predicate, (PT_NODE *) spec);
2867  if (filter_predicate)
2868  {
2869  error =
2870  xts_map_filter_pred_to_stream (filter_predicate, &(pred_index_info.pred_stream),
2871  &(pred_index_info.pred_stream_size));
2872  if (error != NO_ERROR)
2873  {
2874  PT_ERRORm ((PARSER_CONTEXT *) parser, where_predicate, MSGCAT_SET_PARSER_RUNTIME,
2876  goto end;
2877  }
2878  pred_index_info.att_ids = filter_predicate->attrids_pred;
2879  pred_index_info.num_attrs = filter_predicate->num_attrs_pred;
2880  p_pred_index_info = &pred_index_info;
2881  }
2882  else
2883  {
2884  assert (er_errid () != NO_ERROR);
2885  error = er_errid ();
2886  goto end;
2887  }
2888  }
2889 
2890  assert (index_status != SM_NO_INDEX);
2891 
2892  error = sm_add_constraint (obj, ctype, cname, (const char **) attnames, asc_desc, attrs_prefix_length, false,
2893  p_pred_index_info, func_index_info, comment_str, index_status);
2894  }
2895  else
2896  {
2897  assert (do_index == DO_INDEX_DROP);
2898  error = sm_drop_constraint (obj, ctype, cname, (const char **) attnames, false, mysql_index_name);
2899  }
2900  }
2901 
2902 end:
2903 
2904  /* free function index info */
2905  if (func_index_info)
2906  {
2907  sm_free_function_index_info (func_index_info);
2908  db_ws_free (func_index_info);
2909  func_index_info = NULL;
2910  }
2911 
2912  /* free 'stream' that is allocated inside of xts_map_xasl_to_stream() */
2913  if (pred_index_info.pred_stream)
2914  {
2915  free_and_init (pred_index_info.pred_stream);
2916  }
2917 
2918  if (free_packing_buff)
2919  {
2920  /* mark the end of another level of xasl packing */
2922  }
2923 
2924  free_and_init (attnames);
2925  free_and_init (asc_desc);
2926  if (attrs_prefix_length)
2927  {
2928  free_and_init (attrs_prefix_length);
2929  }
2930 
2931  if (cname != NULL)
2932  {
2933  free_and_init (cname);
2934  }
2935 
2936  return error;
2937 }
2938 
2939 /*
2940  * do_create_index() - Creates an index
2941  * return: Error code if it fails
2942  * parser(in): Parser context
2943  * statement(in) : Parse tree of a create index statement
2944  */
2945 int
2947 {
2948  PT_NODE *cls;
2949  DB_OBJECT *obj;
2950  const char *index_name = NULL;
2951  int error = NO_ERROR;
2952 
2954 
2955  /* class should be already available */
2956  assert (statement->info.index.indexed_class);
2957 
2958  cls = statement->info.index.indexed_class->info.spec.entity_name;
2959 
2960  obj = db_find_class (cls->info.name.original);
2961  if (obj == NULL)
2962  {
2963  assert (er_errid () != NO_ERROR);
2964  return er_errid ();
2965  }
2966 
2967  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
2968 
2970  {
2971  ib_thread_count = statement->info.index.ib_threads;
2972  }
2973 
2974  error =
2975  create_or_drop_index_helper (parser, index_name, statement->info.index.reverse, statement->info.index.unique,
2976  statement->info.index.indexed_class, statement->info.index.column_names,
2977  statement->info.index.prefix_length, statement->info.index.where,
2978  statement->info.index.func_pos, statement->info.index.func_no_args,
2979  statement->info.index.function_expr, statement->info.index.comment, obj,
2980  statement->info.index.index_status, DO_INDEX_CREATE);
2981  return error;
2982 }
2983 
2984 /*
2985  * do_drop_index() - Drops an index on a class.
2986  * return: Error code if it fails
2987  * parser(in) : Parser context
2988  * statement(in): Parse tree of a drop index statement
2989  */
2990 int
2992 {
2993  PT_NODE *cls = NULL;
2994  DB_OBJECT *obj = NULL;
2995  const char *index_name = NULL;
2996  int error_code = NO_ERROR;
2997  const char *class_name = NULL;
2998  DB_CONSTRAINT_TYPE index_type;
2999  bool is_reverse;
3000  bool is_unique;
3001 
3003 
3004  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
3005 
3006  if (index_name == NULL)
3007  {
3009  return error_code;
3010  }
3011 
3012  if (statement->info.index.indexed_class)
3013  {
3014  cls = statement->info.index.indexed_class->info.spec.flat_entity_list;
3015  }
3016 
3017  assert (cls != NULL);
3018 
3019  index_type = get_reverse_unique_index_type (statement->info.index.reverse, statement->info.index.unique);
3020 
3021  class_name = cls->info.name.resolved;
3022  obj = db_find_class (class_name);
3023 
3024  if (obj == NULL)
3025  {
3026  assert (er_errid () != NO_ERROR);
3027  error_code = er_errid ();
3028  return error_code;
3029  }
3030 
3031  if (index_type == DB_CONSTRAINT_INDEX)
3032  {
3033  error_code = get_index_type_qualifiers (obj, &is_reverse, &is_unique, index_name);
3034  if (error_code != NO_ERROR)
3035  {
3036  return error_code;
3037  }
3038  }
3039  else
3040  {
3041  is_reverse = statement->info.index.reverse;
3042  is_unique = statement->info.index.unique;
3043  }
3044 
3045  error_code =
3046  create_or_drop_index_helper (parser, index_name, is_reverse, is_unique,
3047  statement->info.index.indexed_class, statement->info.index.column_names, NULL, NULL,
3048  statement->info.index.func_pos, statement->info.index.func_no_args,
3049  statement->info.index.function_expr, NULL, obj, statement->info.index.index_status,
3050  DO_INDEX_DROP);
3051 
3052  return error_code;
3053 }
3054 
3055 /*
3056  * do_alter_index_rebuild() - Alters an index on a class (drop and create).
3057  * INDEX REBUILD statement ignores any type of the
3058  * qualifier, column, and filter predicate (filtered
3059  * index). The purpose of this feature is that
3060  * reconstructing the corrupted index or improving
3061  * the efficiency of indexes. For the backward
3062  * compatibility, this function supports the
3063  * previous grammar.
3064  * return: Error code if it fails
3065  * parser(in): Parser context
3066  * statement(in): Parse tree of a alter index statement
3067  */
3068 static int
3070 {
3071  int error = NO_ERROR;
3072  DB_OBJECT *obj;
3073  PT_NODE *cls = NULL;
3074  int i, nnames;
3075  DB_CONSTRAINT_TYPE ctype, original_ctype;
3076  char **attnames = NULL;
3077  int *asc_desc = NULL;
3078  int *attrs_prefix_length = NULL;
3079  SM_CLASS *smcls;
3080  SM_CLASS_CONSTRAINT *idx = NULL;
3081  SM_ATTRIBUTE **attp;
3082  const char *index_name = NULL;
3083  bool free_pred_string = false;
3084  bool free_packing_buff = false;
3085  SM_FUNCTION_INFO *func_index_info = NULL;
3086  SM_PREDICATE_INFO pred_index_info = { NULL, NULL, 0, NULL, 0 };
3087  SM_PREDICATE_INFO *p_pred_index_info = NULL;
3088  const char *class_name = NULL;
3089  const char *comment_str = NULL;
3090  bool do_rollback = false;
3091  SM_INDEX_STATUS saved_index_status = SM_NORMAL_INDEX;
3092 
3093  /* TODO refactor this code, the code in create_or_drop_index_helper and the code in do_drop_index in order to remove
3094  * duplicate code */
3095 
3097 
3098  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
3099 
3100  assert (index_name != NULL);
3101 
3102  if (statement->info.index.indexed_class)
3103  {
3104  cls = statement->info.index.indexed_class->info.spec.flat_entity_list;
3105  }
3106 
3107  assert (cls != NULL);
3108 
3109  class_name = cls->info.name.resolved;
3110 
3111  obj = db_find_class (class_name);
3112  if (obj == NULL)
3113  {
3114  assert (er_errid () != NO_ERROR);
3115  error = er_errid ();
3116  goto error_exit;
3117  }
3118 
3119  if (au_fetch_class (obj, &smcls, AU_FETCH_READ, AU_SELECT) != NO_ERROR)
3120  {
3121  assert (er_errid () != NO_ERROR);
3122  error = er_errid ();
3123  goto error_exit;
3124  }
3125 
3126  idx = classobj_find_class_index (smcls, index_name);
3127  if (idx == NULL)
3128  {
3130  error = ER_SM_NO_INDEX;
3131  goto error_exit;
3132  }
3133 
3134  saved_index_status = idx->index_status;
3135 
3136  if (statement->info.index.comment != NULL)
3137  {
3138  assert (statement->info.index.comment->node_type == PT_VALUE);
3139  comment_str = (char *) PT_VALUE_GET_BYTES (statement->info.index.comment);
3140  }
3141 
3142  /* check the index type */
3143  ctype = get_reverse_unique_index_type (statement->info.index.reverse, statement->info.index.unique);
3144  original_ctype = db_constraint_type (idx);
3145  if (ctype != original_ctype)
3146  {
3148  }
3149 
3150  /* get attributes of the index */
3151  attp = idx->attributes;
3152  if (attp == NULL)
3153  {
3155  error = ER_OBJ_INVALID_ATTRIBUTE;
3156  goto error_exit;
3157  }
3158 
3159  nnames = 0;
3160  while (*attp++)
3161  {
3162  nnames++;
3163  }
3164 
3165  attnames = (char **) malloc ((nnames + 1) * sizeof (const char *));
3166  if (attnames == NULL)
3167  {
3168  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (nnames + 1) * sizeof (const char *));
3169  error = ER_OUT_OF_VIRTUAL_MEMORY;
3170  goto error_exit;
3171  }
3172 
3173  for (i = 0, attp = idx->attributes; *attp; i++, attp++)
3174  {
3175  attnames[i] = strdup ((*attp)->header.name);
3176  if (attnames[i] == NULL)
3177  {
3178  int j;
3179  for (j = 0; j < i; ++j)
3180  {
3181  free_and_init (attnames[j]);
3182  }
3183  free_and_init (attnames);
3185  (strlen ((*attp)->header.name) + 1) * sizeof (char));
3186  error = ER_OUT_OF_VIRTUAL_MEMORY;
3187  goto error_exit;
3188  }
3189  }
3190  attnames[i] = NULL;
3191 
3192  if (idx->asc_desc)
3193  {
3194  asc_desc = (int *) malloc ((nnames) * sizeof (int));
3195  if (asc_desc == NULL)
3196  {
3197  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, nnames * sizeof (int));
3198  error = ER_OUT_OF_VIRTUAL_MEMORY;
3199  goto error_exit;
3200  }
3201 
3202  for (i = 0; i < nnames; i++)
3203  {
3204  asc_desc[i] = idx->asc_desc[i];
3205  }
3206  }
3207 
3208  if (original_ctype == DB_CONSTRAINT_INDEX)
3209  {
3210  assert (idx->attrs_prefix_length);
3211 
3212  attrs_prefix_length = (int *) malloc ((nnames) * sizeof (int));
3213  if (attrs_prefix_length == NULL)
3214  {
3215  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, nnames * sizeof (int));
3216  error = ER_OUT_OF_VIRTUAL_MEMORY;
3217  goto error_exit;
3218  }
3219 
3220  for (i = 0; i < nnames; i++)
3221  {
3222  attrs_prefix_length[i] = idx->attrs_prefix_length[i];
3223  }
3224  }
3225 
3226  if (idx->filter_predicate)
3227  {
3228  int pred_str_len;
3230 
3231  pred_str_len = strlen (idx->filter_predicate->pred_string);
3232 
3233  pred_index_info.pred_string = strdup (idx->filter_predicate->pred_string);
3234  if (pred_index_info.pred_string == NULL)
3235  {
3237  (strlen (idx->filter_predicate->pred_string) + 1) * sizeof (char));
3238  error = ER_OUT_OF_VIRTUAL_MEMORY;
3239  goto error_exit;
3240  }
3241  free_pred_string = true;
3242 
3243  pred_index_info.pred_stream = (char *) malloc (idx->filter_predicate->pred_stream_size * sizeof (char));
3244  if (pred_index_info.pred_stream == NULL)
3245  {
3247  idx->filter_predicate->pred_stream_size * sizeof (char));
3248  error = ER_OUT_OF_VIRTUAL_MEMORY;
3249  goto error_exit;
3250  }
3251 
3252  memcpy (pred_index_info.pred_stream, idx->filter_predicate->pred_stream, idx->filter_predicate->pred_stream_size);
3253 
3254  pred_index_info.pred_stream_size = idx->filter_predicate->pred_stream_size;
3255 
3256  if (idx->filter_predicate->num_attrs == 0)
3257  {
3258  pred_index_info.att_ids = NULL;
3259  }
3260  else
3261  {
3262  pred_index_info.att_ids = (int *) calloc (idx->filter_predicate->num_attrs, sizeof (int));
3263  if (pred_index_info.att_ids == NULL)
3264  {
3266  idx->filter_predicate->num_attrs * sizeof (int));
3267  error = ER_OUT_OF_VIRTUAL_MEMORY;
3268  goto error_exit;
3269  }
3270  for (i = 0; i < idx->filter_predicate->num_attrs; i++)
3271  {
3272  pred_index_info.att_ids[i] = idx->filter_predicate->att_ids[i];
3273  }
3274  }
3275  pred_index_info.num_attrs = idx->filter_predicate->num_attrs;
3276  p_pred_index_info = &pred_index_info;
3277  }
3278 
3279  if (idx->func_index_info)
3280  {
3281  func_index_info = (SM_FUNCTION_INFO *) db_ws_alloc (sizeof (SM_FUNCTION_INFO));
3282  if (func_index_info == NULL)
3283  {
3284  error = ER_OUT_OF_VIRTUAL_MEMORY;
3285  goto error_exit;
3286  }
3287  func_index_info->fi_domain = tp_domain_copy (idx->func_index_info->fi_domain, true);
3288  func_index_info->expr_str = strdup (idx->func_index_info->expr_str);
3289  if (func_index_info->expr_str == NULL)
3290  {
3291  error = ER_OUT_OF_VIRTUAL_MEMORY;
3293  (strlen (idx->func_index_info->expr_str) + 1) * sizeof (char));
3294  goto error_exit;
3295  }
3296  func_index_info->expr_stream = (char *) calloc (idx->func_index_info->expr_stream_size, sizeof (char));
3297  if (func_index_info->expr_stream == NULL)
3298  {
3299  error = ER_OUT_OF_VIRTUAL_MEMORY;
3300  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, idx->func_index_info->expr_stream_size * sizeof (char));
3301  goto error_exit;
3302  }
3303  memcpy (func_index_info->expr_stream, idx->func_index_info->expr_stream, idx->func_index_info->expr_stream_size);
3304  func_index_info->expr_stream_size = idx->func_index_info->expr_stream_size;
3305  func_index_info->col_id = idx->func_index_info->col_id;
3306  func_index_info->attr_index_start = idx->func_index_info->attr_index_start;
3307  }
3308 
3310  if (error != NO_ERROR)
3311  {
3312  goto error_exit;
3313  }
3314  do_rollback = true;
3315 
3316  error = sm_drop_constraint (obj, original_ctype, index_name, (const char **) attnames, false, false);
3317  if (error != NO_ERROR)
3318  {
3319  goto error_exit;
3320  }
3321 
3322  error =
3323  sm_add_constraint (obj, original_ctype, index_name, (const char **) attnames, asc_desc, attrs_prefix_length, false,
3324  p_pred_index_info, func_index_info, comment_str, saved_index_status);
3325  if (error != NO_ERROR)
3326  {
3327  goto error_exit;
3328  }
3329 
3330 end:
3331  if (func_index_info)
3332  {
3333  sm_free_function_index_info (func_index_info);
3334  db_ws_free (func_index_info);
3335  func_index_info = NULL;
3336  }
3337 
3338  if (pred_index_info.pred_stream != NULL)
3339  {
3340  free_and_init (pred_index_info.pred_stream);
3341  }
3342 
3343  if (free_pred_string)
3344  {
3345  free_and_init (pred_index_info.pred_string);
3346  /* free allocated attribute ids */
3347  if (pred_index_info.att_ids != NULL)
3348  {
3349  free_and_init (pred_index_info.att_ids);
3350  }
3351  }
3352 
3353  if (free_packing_buff)
3354  {
3355  /* mark the end of another level of xasl packing */
3357  }
3358 
3359  if (attnames)
3360  {
3361  for (i = 0; attnames[i]; i++)
3362  {
3363  free_and_init (attnames[i]);
3364  }
3365  free_and_init (attnames);
3366  }
3367 
3368  if (asc_desc)
3369  {
3370  free_and_init (asc_desc);
3371  }
3372 
3373  if (attrs_prefix_length)
3374  {
3375  free_and_init (attrs_prefix_length);
3376  }
3377 
3378  return error;
3379 
3380 error_exit:
3381 
3382  if (do_rollback == true)
3383  {
3384  if (do_rollback && error != ER_LK_UNILATERALLY_ABORTED)
3385  {
3387  }
3388  }
3389  error = (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
3390 
3391  goto end;
3392 }
3393 
3394 #if defined (ENABLE_RENAME_CONSTRAINT)
3395 /*
3396  * do_alter_index_rename() - renames an index on a class.
3397  * return: Error code if it fails
3398  * parser(in): Parser context
3399  * statement(in): Parse tree of a alter index statement
3400  */
3401 static int
3402 do_alter_index_rename (PARSER_CONTEXT * parser, const PT_NODE * statement)
3403 {
3404  int error = NO_ERROR;
3405  DB_OBJECT *obj;
3406  PT_NODE *cls = NULL;
3407  SM_TEMPLATE *ctemplate = NULL;
3408  const char *class_name = NULL;
3409  const char *index_name = NULL;
3410  const char *new_index_name = NULL;
3411  const char *comment = NULL;
3412  bool do_rollback = false;
3413 
3414  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
3415 
3416  new_index_name = statement->info.index.new_name ? statement->info.index.new_name->info.name.original : NULL;
3417 
3418  if (index_name == NULL || new_index_name == NULL)
3419  {
3420  goto error_exit;
3421  }
3422 
3423  if (statement->info.index.comment != NULL)
3424  {
3425  assert (statement->info.index.comment->node_type == PT_VALUE);
3426  comment = (char *) PT_VALUE_GET_BYTES (statement->info.index.comment);
3427  }
3428 
3429  cls = statement->info.index.indexed_class ? statement->info.index.indexed_class->info.spec.flat_entity_list : NULL;
3430 
3431  if (cls == NULL)
3432  {
3433  goto error_exit;
3434  }
3435 
3436  class_name = cls->info.name.resolved;
3437  obj = db_find_class (class_name);
3438 
3439  if (obj == NULL)
3440  {
3441  error = er_errid ();
3442  assert (error != NO_ERROR);
3443  goto error_exit;
3444  }
3445 
3447  if (error != NO_ERROR)
3448  {
3449  goto error_exit;
3450  }
3451 
3452  do_rollback = true;
3453 
3454 
3455  ctemplate = smt_edit_class_mop (obj, AU_INDEX);
3456  if (ctemplate == NULL)
3457  {
3458  assert (er_errid () != NO_ERROR);
3459  error = er_errid ();
3460  assert (error != NO_ERROR);
3461  goto error_exit;
3462  }
3463 
3464  error = smt_rename_constraint (ctemplate, index_name, new_index_name, SM_INDEX_NAME);
3465  if (error != NO_ERROR)
3466  {
3467  goto error_exit;
3468  }
3469 
3470  if (comment != NULL)
3471  {
3472  error = smt_change_constraint_comment (ctemplate, new_index_name, comment);
3473  if (error != NO_ERROR)
3474  {
3475  goto error_exit;
3476  }
3477  }
3478 
3479  /* classobj_free_template() is included in sm_update_class() */
3480  error = sm_update_class (ctemplate, NULL);
3481  if (error != NO_ERROR)
3482  {
3483  /* Even though sm_update() did not return NO_ERROR, ctemplate is already freed */
3484  ctemplate = NULL;
3485  goto error_exit;
3486  }
3487 
3488 end:
3489 
3490  return error;
3491 
3492 error_exit:
3493  if (ctemplate != NULL)
3494  {
3495  /* smt_quit() always returns NO_ERROR */
3496  smt_quit (ctemplate);
3497  }
3498 
3499  if (do_rollback == true)
3500  {
3501  if (do_rollback && error != ER_LK_UNILATERALLY_ABORTED)
3502  {
3504  }
3505  }
3506  error = (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
3507 
3508  goto end;
3509 }
3510 #endif
3511 
3512 /*
3513  * do_alter_index_comment() - alter an index comment on a class.
3514  * return: Error code if it fails
3515  * parser(in): Parser context
3516  * statement(in): Parse tree of a alter index statement
3517  */
3518 static int
3519 do_alter_index_comment (PARSER_CONTEXT * parser, const PT_NODE * statement)
3520 {
3521  int error = NO_ERROR;
3522  DB_OBJECT *obj;
3523  PT_NODE *cls = NULL;
3524  SM_TEMPLATE *ctemplate = NULL;
3525  const char *class_name = NULL;
3526  const char *index_name = NULL;
3527  const char *comment = NULL;
3528  bool do_rollback = false;
3529 
3530  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
3531 
3532  if (index_name == NULL)
3533  {
3534  goto error_exit;
3535  }
3536 
3537  if (statement->info.index.comment != NULL)
3538  {
3539  assert (statement->info.index.comment->node_type == PT_VALUE);
3540  comment = (char *) PT_VALUE_GET_BYTES (statement->info.index.comment);
3541  }
3542 
3543  cls = statement->info.index.indexed_class ? statement->info.index.indexed_class->info.spec.flat_entity_list : NULL;
3544 
3545  if (cls == NULL)
3546  {
3547  goto error_exit;
3548  }
3549 
3550  class_name = cls->info.name.resolved;
3551  obj = db_find_class (class_name);
3552 
3553  if (obj == NULL)
3554  {
3555  error = er_errid ();
3556  assert (error != NO_ERROR);
3557  goto error_exit;
3558  }
3559 
3561  if (error != NO_ERROR)
3562  {
3563  goto error_exit;
3564  }
3565 
3566  do_rollback = true;
3567 
3568  ctemplate = smt_edit_class_mop (obj, AU_INDEX);
3569  if (ctemplate == NULL)
3570  {
3571  error = er_errid ();
3572  assert (error != NO_ERROR);
3573  goto error_exit;
3574  }
3575 
3576  error = smt_change_constraint_comment (ctemplate, index_name, comment);
3577  if (error != NO_ERROR)
3578  {
3579  goto error_exit;
3580  }
3581 
3582  /* classobj_free_template() is included in sm_update_class() */
3583  error = sm_update_class (ctemplate, NULL);
3584  if (error != NO_ERROR)
3585  {
3586  /* Even though sm_update() did not return NO_ERROR, ctemplate is already freed */
3587  ctemplate = NULL;
3588  goto error_exit;
3589  }
3590 
3591 end:
3592 
3593  return error;
3594 
3595 error_exit:
3596  if (ctemplate != NULL)
3597  {
3598  /* smt_quit() always returns NO_ERROR */
3599  smt_quit (ctemplate);
3600  }
3601 
3602  if (do_rollback == true)
3603  {
3604  if (do_rollback && error != ER_LK_UNILATERALLY_ABORTED)
3605  {
3607  }
3608  }
3609  error = (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
3610 
3611  goto end;
3612 }
3613 
3614 /*
3615  * do_alter_index() - Alters an index on a class.
3616  * return: Error code if it fails
3617  * parser(in): Parser context
3618  * statement(in): Parse tree of a alter index statement
3619  */
3620 int
3621 do_alter_index (PARSER_CONTEXT * parser, const PT_NODE * statement)
3622 {
3623  int error = NO_ERROR;
3624 
3626 
3627  if (statement->info.index.code == PT_REBUILD_INDEX)
3628  {
3629  error = do_alter_index_rebuild (parser, statement);
3630  }
3631 #if defined (ENABLE_RENAME_CONSTRAINT)
3632  else if (statement->info.index.code == PT_RENAME_INDEX)
3633  {
3634  error = do_alter_index_rename (parser, statement);
3635  }
3636 #endif
3637  else if (statement->info.index.code == PT_CHANGE_INDEX_COMMENT)
3638  {
3639  error = do_alter_index_comment (parser, statement);
3640  }
3641  else if (statement->info.index.code == PT_CHANGE_INDEX_STATUS)
3642  {
3643  error = do_alter_index_status (parser, statement);
3644  }
3645  else
3646  {
3647  return ER_FAILED;
3648  }
3649 
3650  return error;
3651 }
3652 
3653 /*
3654  * do_create_partition() - Creates partitions
3655  * return: Error code if partitions are not created
3656  * parser(in): Parser context
3657  * alter(in): The parse tree of a create class
3658  * pinfo(in): partition alter context
3659  *
3660  * Note:
3661  */
3662 static int
3664 {
3665  int error;
3666  PT_NODE *alter_info, *hash_parts, *newparts, *hashtail;
3667  PT_NODE *parts, *parts_save, *fmin;
3668  PT_NODE *parttemp, *entity_name = NULL;
3669  PART_CLASS_INFO pci = { NULL, NULL, NULL, NULL };
3670  PART_CLASS_INFO *newpci, *wpci;
3671  char class_name[DB_MAX_IDENTIFIER_LENGTH];
3672  DB_VALUE *minval, *parts_val, *fmin_val, partsize;
3673  int part_cnt = 0, part_add = -1;
3674  size_t buf_size;
3675  SM_CLASS *smclass;
3676  bool reuse_oid = false;
3677  TDE_ALGORITHM tde_algo = TDE_ALGORITHM_NONE;
3678 
3680 
3681  alter_info = hash_parts = newparts = hashtail = NULL;
3682  parts = parts_save = fmin = NULL;
3683 
3684  if (alter->node_type == PT_ALTER)
3685  {
3686  alter_info = alter->info.alter.alter_clause.partition.info;
3687  if (alter->info.alter.code == PT_ADD_PARTITION || alter->info.alter.code == PT_REORG_PARTITION)
3688  {
3689  parts = alter->info.alter.alter_clause.partition.parts;
3690  part_add = parts->info.parts.type;
3691  }
3692  else if (alter->info.alter.code == PT_ADD_HASHPARTITION)
3693  {
3694  part_add = PT_PARTITION_HASH;
3695  }
3696  entity_name = alter->info.alter.entity_name;
3697  intl_identifier_lower ((char *) entity_name->info.name.original, class_name);
3698  }
3699  else if (alter->node_type == PT_CREATE_ENTITY)
3700  {
3701  entity_name = alter->info.create_entity.entity_name;
3702  alter_info = alter->info.create_entity.partition_info;
3703  intl_identifier_lower ((char *) entity_name->info.name.original, class_name);
3704  }
3705  else
3706  {
3707  return NO_ERROR;
3708  }
3709 
3710  if (part_add == -1)
3711  { /* create or apply partition */
3712  if (!alter_info)
3713  {
3714  return NO_ERROR;
3715  }
3716 
3717  parts = alter_info->info.partition.parts;
3718  }
3719 
3720  parts_save = parts;
3721  parttemp = parser_new_node (parser, PT_CREATE_ENTITY);
3722  if (parttemp == NULL)
3723  {
3724  assert (er_errid () != NO_ERROR);
3725  error = er_errid ();
3726  goto end_create;
3727  }
3728 
3729  error = au_fetch_class (pinfo->root_op, &smclass, AU_FETCH_READ, AU_SELECT);
3730  if (error != NO_ERROR)
3731  {
3732  assert (er_errid () != NO_ERROR);
3733  error = er_errid ();
3734  goto end_create;
3735  }
3736 
3737  /* If the current class is part of a hierarchy and the class is
3738  * not partitioned, end this as we do not allow partitions on hierarchies.
3739  */
3740  if (smclass->partition == NULL && (smclass->users != NULL || smclass->inheritance != NULL))
3741  {
3744  goto end_create;
3745  }
3746 
3747  reuse_oid = (smclass->flags & SM_CLASSFLAG_REUSE_OID) ? true : false;
3748  tde_algo = (TDE_ALGORITHM) smclass->tde_algorithm;
3749 
3750  parttemp->info.create_entity.entity_type = PT_CLASS;
3751  parttemp->info.create_entity.entity_name = parser_new_node (parser, PT_NAME);
3752  parttemp->info.create_entity.supclass_list = parser_new_node (parser, PT_NAME);
3753  if (parttemp->info.create_entity.entity_name == NULL || parttemp->info.create_entity.supclass_list == NULL)
3754  {
3755  assert (er_errid () != NO_ERROR);
3756  error = er_errid ();
3757  goto end_create;
3758  }
3760 
3761  error = NO_ERROR;
3762  if (part_add == PT_PARTITION_HASH
3763  || (alter_info && alter_info->node_type != PT_VALUE && alter_info->info.partition.type == PT_PARTITION_HASH))
3764  {
3765  int pi, org_hashsize, new_hashsize;
3766 
3767  hash_parts = parser_new_node (parser, PT_PARTS);
3768  if (hash_parts == NULL)
3769  {
3770  assert (er_errid () != NO_ERROR);
3771  error = er_errid ();
3772  goto end_create;
3773  }
3774  hash_parts->info.parts.name = parser_new_node (parser, PT_NAME);
3775  if (hash_parts->info.parts.name == NULL)
3776  {
3777  assert (er_errid () != NO_ERROR);
3778  error = er_errid ();
3779  goto end_create;
3780  }
3781 
3782  hash_parts->info.parts.type = PT_PARTITION_HASH;
3783  if (part_add == PT_PARTITION_HASH)
3784  {
3785  org_hashsize = do_get_partition_size (pinfo->root_op);
3786  if (org_hashsize < 0)
3787  {
3788  error = org_hashsize;
3789  goto end_create;
3790  }
3791  new_hashsize = alter->info.alter.alter_clause.partition.size->info.value.data_value.i;
3792  }
3793  else
3794  {
3795  org_hashsize = 0;
3796  new_hashsize = alter_info->info.partition.hashsize->info.value.data_value.i;
3797  }
3798 
3799  for (pi = 0; pi < new_hashsize; pi++)
3800  {
3801  newpci = (PART_CLASS_INFO *) malloc (sizeof (PART_CLASS_INFO));
3802  if (newpci == NULL)
3803  {
3805  error = ER_OUT_OF_VIRTUAL_MEMORY;
3806  goto end_create;
3807  }
3808 
3809  memset (newpci, 0x0, sizeof (PART_CLASS_INFO));
3810 
3811  newpci->next = pci.next;
3812  pci.next = newpci;
3813 
3814  buf_size = strlen (class_name) + 5 + 13;
3815  newpci->pname = (char *) malloc (buf_size);
3816  if (newpci->pname == NULL)
3817  {
3819  error = ER_OUT_OF_VIRTUAL_MEMORY;
3820  goto end_create;
3821  }
3822 
3823  sprintf (newpci->pname, "%s" PARTITIONED_SUB_CLASS_TAG "p%d", class_name, pi + org_hashsize);
3824  if (strlen (newpci->pname) >= PARTITION_VARCHAR_LEN)
3825  {
3827  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
3828  goto end_create;
3829  }
3830  newpci->temp = dbt_create_class (newpci->pname);
3831  if (newpci->temp == NULL)
3832  {
3833  assert (er_errid () != NO_ERROR);
3834  error = er_errid ();
3835  goto end_create;
3836  }
3837 
3838  parttemp->info.create_entity.entity_name->info.name.original = newpci->pname;
3839  parttemp->info.create_entity.supclass_list->info.name.original = class_name;
3840 
3841  error = do_create_local (parser, newpci->temp, parttemp, NULL);
3842  if (error != NO_ERROR)
3843  {
3844  dbt_abort_class (newpci->temp);
3845  goto end_create;
3846  }
3847 
3848  newpci->temp->partition_parent_atts = smclass->attributes;
3849 
3850  hash_parts->info.parts.name->info.name.original =
3852  hash_parts->info.parts.values = NULL;
3853 
3854  newpci->temp->partition =
3855  pt_node_to_partition_info (parser, hash_parts, NULL, class_name, newpci->pname, NULL);
3856  if (newpci->temp->partition == NULL)
3857  {
3858  error = er_errid ();
3859  dbt_abort_class (newpci->temp);
3860  goto end_create;
3861  }
3862 
3863  newpci->obj = dbt_finish_class (newpci->temp);
3864  if (newpci->obj == NULL)
3865  {
3866  dbt_abort_class (newpci->temp);
3867  assert (er_errid () != NO_ERROR);
3868  error = er_errid ();
3869  goto end_create;
3870  }
3871  else if (er_errid () == ER_LC_UNKNOWN_CLASSNAME)
3872  {
3873  /* The class doesn't exist. We are creating the class. */
3874  er_clear ();
3875  }
3876 
3877  if (reuse_oid)
3878  {
3879  error = sm_set_class_flag (newpci->obj, SM_CLASSFLAG_REUSE_OID, 1);
3880  if (error != NO_ERROR)
3881  {
3882  goto end_create;
3883  }
3884  }
3885  if (tde_algo != TDE_ALGORITHM_NONE)
3886  {
3887  error = sm_set_class_tde_algorithm (newpci->obj, tde_algo);
3888  if (error != NO_ERROR)
3889  {
3890  goto end_create;
3891  }
3892  }
3893 
3894  if (locator_create_heap_if_needed (newpci->obj, reuse_oid) == NULL
3895  || locator_flush_class (newpci->obj) != NO_ERROR)
3896  {
3897  error = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
3898  goto end_create;
3899  }
3900 
3901  if (part_add == PT_PARTITION_HASH)
3902  {
3903  hash_parts->next = NULL;
3904  hash_parts->info.parts.name->info.name.db_object = newpci->obj;
3905  newparts = parser_copy_tree (parser, hash_parts);
3906  if (alter->info.alter.alter_clause.partition.parts == NULL)
3907  {
3908  alter->info.alter.alter_clause.partition.parts = newparts;
3909  }
3910  else
3911  {
3912  if (hashtail != NULL)
3913  {
3914  hashtail->next = newparts;
3915  }
3916  }
3917 
3918  hashtail = newparts;
3919  }
3920  if (tde_algo != TDE_ALGORITHM_NONE)
3921  {
3922  error = file_apply_tde_to_class_files (&newpci->obj->oid_info.oid);
3923  if (error != NO_ERROR)
3924  {
3925  goto end_create;
3926  }
3927  }
3928  error = NO_ERROR;
3929  }
3930  }
3931  else
3932  { /* RANGE or LIST */
3933  char *part_name;
3934 
3935  for (; parts; parts = parts->next, part_cnt++)
3936  {
3937  newpci = (PART_CLASS_INFO *) malloc (sizeof (PART_CLASS_INFO));
3938  if (newpci == NULL)
3939  {
3941  error = ER_OUT_OF_VIRTUAL_MEMORY;
3942  goto end_create;
3943  }
3944 
3945  memset (newpci, 0x0, sizeof (PART_CLASS_INFO));
3946 
3947  newpci->next = pci.next;
3948  pci.next = newpci;
3949 
3950  part_name = (char *) parts->info.parts.name->info.name.original;
3951  buf_size = strlen (class_name) + 5 + 1 + strlen (part_name);
3952 
3953  newpci->pname = (char *) malloc (buf_size);
3954  if (newpci->pname == NULL)
3955  {
3957  error = ER_OUT_OF_VIRTUAL_MEMORY;
3958  goto end_create;
3959  }
3960  sprintf (newpci->pname, "%s" PARTITIONED_SUB_CLASS_TAG "%s", class_name, part_name);
3961 
3962  if (strlen (newpci->pname) >= PARTITION_VARCHAR_LEN)
3963  {
3965  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
3966  goto end_create;
3967  }
3968 
3969  if (alter->info.alter.code == PT_REORG_PARTITION && parts->flag.partition_pruned)
3970  { /* reused partition */
3971  newpci->obj = ws_find_class (newpci->pname);
3972  if (newpci->obj == NULL)
3973  {
3974  assert (er_errid () != NO_ERROR);
3975  error = er_errid ();
3976  goto end_create;
3977  }
3978 
3979  newpci->temp = dbt_edit_class (newpci->obj);
3980  if (newpci->temp == NULL)
3981  {
3982  assert (er_errid () != NO_ERROR);
3983  error = er_errid ();
3984  goto end_create;
3985  }
3986 
3987  newpci->temp->partition =
3988  pt_node_to_partition_info (parser, parts, NULL, class_name, newpci->pname, NULL);
3989  if (newpci->temp->partition == NULL)
3990  {
3991  error = er_errid ();
3992  dbt_abort_class (newpci->temp);
3993  goto end_create;
3994  }
3995 
3996  newpci->obj = dbt_finish_class (newpci->temp);
3997  if (newpci->obj == NULL)
3998  {
3999  dbt_abort_class (newpci->temp);
4000  assert (er_errid () != NO_ERROR);
4001  error = er_errid ();
4002  goto end_create;
4003  }
4004 
4005  continue;
4006  }
4007 
4008  newpci->temp = dbt_create_class (newpci->pname);
4009  if (newpci->temp == NULL)
4010  {
4011  assert (er_errid () != NO_ERROR);
4012  error = er_errid ();
4013  goto end_create;
4014  }
4015 
4016  parttemp->info.create_entity.entity_name->info.name.original = newpci->pname;
4017  parttemp->info.create_entity.supclass_list->info.name.original = class_name;
4018 
4019  error = do_create_local (parser, newpci->temp, parttemp, NULL);
4020  if (error != NO_ERROR)
4021  {
4022  dbt_abort_class (newpci->temp);
4023  goto end_create;
4024  }
4025 
4026  newpci->temp->partition_parent_atts = smclass->attributes;
4027 
4028  /* RANGE-MIN VALUE search */
4029  minval = NULL;
4030  if ((alter_info && alter_info->node_type != PT_VALUE && alter_info->info.partition.type == PT_PARTITION_RANGE)
4031  || part_add == PT_PARTITION_RANGE)
4032  {
4033  parts_val = pt_value_to_db (parser, parts->info.parts.values);
4034  for (fmin = parts_save; fmin; fmin = fmin->next)
4035  {
4036  if (fmin == parts)
4037  {
4038  continue;
4039  }
4040  if (fmin->info.parts.values == NULL)
4041  {
4042  continue; /* RANGE-MAXVALUE */
4043  }
4044  fmin_val = pt_value_to_db (parser, fmin->info.parts.values);
4045  if (fmin_val == NULL)
4046  {
4047  continue;
4048  }
4049  if (parts->info.parts.values == NULL || db_value_compare (parts_val, fmin_val) == DB_GT)
4050  {
4051  if (minval == NULL)
4052  {
4053  minval = fmin_val;
4054  }
4055  else
4056  {
4057  if (db_value_compare (minval, fmin_val) == DB_LT)
4058  {
4059  minval = fmin_val;
4060  }
4061  }
4062  }
4063  }
4064  }
4065  if (part_add == PT_PARTITION_RANGE && minval == NULL && alter_info && alter_info->node_type == PT_VALUE)
4066  {
4067  /* set in pt_check_alter_partition */
4068  minval = pt_value_to_db (parser, alter_info);
4069  }
4070 
4071  newpci->temp->partition = pt_node_to_partition_info (parser, parts, NULL, class_name, newpci->pname, minval);
4072  if (newpci->temp->partition == NULL)
4073  {
4074  error = er_errid ();
4075  dbt_abort_class (newpci->temp);
4076  goto end_create;
4077  }
4078 
4079  newpci->obj = dbt_finish_class (newpci->temp);
4080 
4081  if (newpci->obj == NULL)
4082  {
4083  dbt_abort_class (newpci->temp);
4084  assert (er_errid () != NO_ERROR);
4085  error = er_errid ();
4086  goto end_create;
4087  }
4088  else if (er_errid () == ER_LC_UNKNOWN_CLASSNAME)
4089  {
4090  /* The class doesn't exist. We are creating the class. */
4091  er_clear ();
4092  }
4093 
4094  parts->info.parts.name->info.name.db_object = newpci->obj;
4095 
4096  sm_set_class_collation (newpci->obj, smclass->collation_id);
4097 
4098  if (reuse_oid)
4099  {
4100  error = sm_set_class_flag (newpci->obj, SM_CLASSFLAG_REUSE_OID, 1);
4101  if (error != NO_ERROR)
4102  {
4103  assert (er_errid () != NO_ERROR);
4104  error = er_errid ();
4105  goto end_create;
4106  }
4107  }
4108  if (tde_algo != TDE_ALGORITHM_NONE)
4109  {
4110  error = sm_set_class_tde_algorithm (newpci->obj, tde_algo);
4111  if (error != NO_ERROR)
4112  {
4113  assert (er_errid () != NO_ERROR);
4114  error = er_errid ();
4115  goto end_create;
4116  }
4117  }
4118  if (locator_create_heap_if_needed (newpci->obj, reuse_oid) == NULL
4119  || locator_flush_class (newpci->obj) != NO_ERROR)
4120  {
4121  assert (er_errid () != NO_ERROR);
4122  error = er_errid ();
4123  goto end_create;
4124  }
4125  if (tde_algo != TDE_ALGORITHM_NONE)
4126  {
4127  error = file_apply_tde_to_class_files (&newpci->obj->oid_info.oid);
4128  if (error != NO_ERROR)
4129  {
4130  assert (er_errid () != NO_ERROR);
4131  error = er_errid ();
4132  goto end_create;
4133  }
4134  }
4135 
4136  error = NO_ERROR;
4137  }
4138  }
4139 
4140  if (part_add != -1)
4141  {
4142  /* partition size update */
4143  error = adjust_partition_size (pinfo->root_op, pinfo->root_tmpl);
4144  if (error != NO_ERROR)
4145  {
4146  goto end_create;
4147  }
4148 
4149  if (alter->info.alter.code == PT_REORG_PARTITION && part_add == PT_PARTITION_RANGE)
4150  {
4151  error = au_fetch_class (pinfo->root_op, &smclass, AU_FETCH_READ, AU_SELECT);
4152  if (error != NO_ERROR)
4153  {
4154  goto end_create;
4155  }
4156  error = adjust_partition_range (smclass->users);
4157  if (error != NO_ERROR)
4158  {
4159  goto end_create;
4160  }
4161  }
4162  }
4163  else
4164  {
4165  /* set parent's partition info */
4166  DB_CTMPL *root_tmpl = NULL;
4167  bool abort_template = false;
4168 
4169  db_make_int (&partsize, part_cnt);
4170 
4171  if (pinfo->root_tmpl != NULL)
4172  {
4173  root_tmpl = pinfo->root_tmpl;
4174  }
4175  else
4176  {
4177  root_tmpl = dbt_edit_class (pinfo->root_op);
4178  if (root_tmpl == NULL)
4179  {
4180  error = er_errid ();
4181  goto end_create;
4182  }
4183  abort_template = true;
4184  }
4185 
4186  root_tmpl->partition =
4187  pt_node_to_partition_info (parser, alter_info, entity_name, class_name, class_name, &partsize);
4188  if (root_tmpl->partition == NULL)
4189  {
4190  error = er_errid ();
4191  if (abort_template == true)
4192  {
4193  dbt_abort_class (root_tmpl);
4194  }
4195  goto end_create;
4196  }
4197 
4198  if (abort_template == true)
4199  {
4200  if (dbt_finish_class (root_tmpl) == NULL)
4201  {
4202  dbt_abort_class (root_tmpl);
4203  error = er_errid ();
4204  goto end_create;
4205  }
4206  }
4207  }
4208 
4209 end_create:
4210  for (wpci = pci.next; wpci;)
4211  {
4212  if (wpci->pname)
4213  {
4214  free_and_init (wpci->pname);
4215  }
4216  newpci = wpci;
4217  wpci = wpci->next;
4218  free_and_init (newpci);
4219  }
4220  if (parttemp != NULL)
4221  {
4222  parser_free_tree (parser, parttemp);
4223  }
4224  if (error != NO_ERROR)
4225  {
4226  return error;
4227  }
4228 
4230 
4231  return NO_ERROR;
4232 }
4233 
4234 /*
4235  * compile_partition_expression () - compile the partition expression and
4236  * serialize it to a stream
4237  *
4238  * return : serialized expression or NULL
4239  * parser (in) : parser context
4240  * entity_name (in) : the name of the partitioned table
4241  * pinfo (in) : partition information node
4242  *
4243  */
4244 static SM_FUNCTION_INFO *
4246 {
4247  PT_NODE *spec = NULL, *expr = NULL;
4248  SM_FUNCTION_INFO *part_expr = NULL;
4249 
4250  if (pinfo->node_type != PT_PARTITION)
4251  {
4252  assert (false);
4254  return NULL;
4255  }
4256 
4257  spec = pt_entity (parser, entity_name, NULL, NULL);
4258  if (spec == NULL)
4259  {
4261  return NULL;
4262  }
4263 
4264  /* perform semantic check on the expression */
4265  expr = pinfo->info.partition.expr;
4266  mq_clear_ids (parser, expr, NULL);
4267  if (pt_semantic_quick_check_node (parser, &spec, &expr) == NULL)
4268  {
4270  return NULL;
4271  }
4272 
4273  /* pack the partition expression */
4275  part_expr = pt_node_to_function_index (parser, spec, expr, DO_INDEX_CREATE);
4277 
4278  parser_free_node (parser, spec);
4279 
4280  return part_expr;
4281 }
4282 
4283 /*
4284  * do_check_partitioned_class() - Checks partitioned class
4285  * return: Error code if check_map or keyattr is checked
4286  * classop(in): MOP of class
4287  * class_map(in/out): Checking method(CHECK_PARTITION_NONE, _PARTITION_PARENT,
4288  * _PARTITION_SUBS)
4289  * keyattr(in): Partition key attribute to check
4290  *
4291  * Note:
4292  */
4293 int
4294 do_check_partitioned_class (DB_OBJECT * classop, int check_map, char *keyattr)
4295 {
4296  int error = NO_ERROR;
4297  int is_partition = 0;
4298  char attr_name[DB_MAX_IDENTIFIER_LENGTH + 1];
4299 
4300  if (classop == NULL)
4301  {
4303 
4305  }
4306 
4307  error = sm_partitioned_class_type (classop, &is_partition, (keyattr) ? attr_name : NULL, NULL);
4308  if (error != NO_ERROR)
4309  {
4310  return error;
4311  }
4312 
4313  if (is_partition > 0)
4314  {
4315  if (((check_map & CHECK_PARTITION_PARENT) && is_partition == 1)
4316  || ((check_map & CHECK_PARTITION_SUBS) && is_partition == 2))
4317  {
4319  }
4320  else if (keyattr)
4321  {
4322  if (intl_identifier_casecmp (keyattr, attr_name) == 0)
4323  {
4325  }
4326  }
4327 
4328  if (error != NO_ERROR)
4329  {
4331  }
4332  }
4333 
4334  return error;
4335 }
4336 
4337 /*
4338  * do_get_partition_parent () -
4339  * return: NO_ERROR or error code
4340  * classop(in): MOP of class
4341  * parentop(out): MOP of the parent of the sub-partition or NULL if not a
4342  * sub-partition
4343  */
4344 int
4345 do_get_partition_parent (DB_OBJECT * const classop, MOP * const parentop)
4346 {
4347  int error = NO_ERROR;
4348  int au_save = 0;
4349  SM_CLASS *smclass = NULL;
4350 
4351  if (classop == NULL)
4352  {
4353  assert_release (classop != NULL);
4354  return ER_FAILED;
4355  }
4356 
4357  if (parentop == NULL || *parentop != NULL)
4358  {
4359  assert_release (parentop == NULL || *parentop != NULL);
4360  return ER_FAILED;
4361  }
4362  *parentop = NULL;
4363 
4364  AU_DISABLE (au_save);
4365 
4366  error = au_fetch_class (classop, &smclass, AU_FETCH_READ, AU_SELECT);
4367  if (error != NO_ERROR)
4368  {
4369  goto error_exit;
4370  }
4371 
4372  if (smclass->partition == NULL)
4373  {
4374  /* not a partitioned class */
4375  goto end;
4376  }
4377  if (smclass->inheritance == NULL || smclass->users != NULL)
4378  {
4379  /* this is the partitioned table, not a partition */
4380  goto end;
4381  }
4382 
4383  if (smclass->inheritance->next != NULL)
4384  {
4385  assert (false);
4386  goto error_exit;
4387  }
4388 
4389  *parentop = smclass->inheritance->op;
4390 
4391 end:
4392  AU_ENABLE (au_save);
4393  smclass = NULL;
4394 
4395  return error;
4396 
4397 error_exit:
4398  AU_ENABLE (au_save);
4399  smclass = NULL;
4400  *parentop = NULL;
4401 
4402  return error;
4403 }
4404 
4405 /*
4406  * do_is_partitioned_subclass() -
4407  * return: 1 if success, else error code
4408  * is_partitioned(in/out):
4409  * classname(in):
4410  * keyattr(in):
4411  *
4412  * Note:
4413  */
4414 int
4415 do_is_partitioned_subclass (int *is_partitioned, const char *classname, char *keyattr)
4416 {
4417  MOP classop;
4418  SM_CLASS *smclass;
4419  DB_VALUE attrname;
4420  int ret = 0;
4421 
4422  if (!classname)
4423  {
4424  return 0;
4425  }
4426  if (is_partitioned)
4427  {
4428  *is_partitioned = 0;
4429  }
4430 
4431  classop = db_find_class (classname);
4432  if (classop == NULL)
4433  {
4434  return 0;
4435  }
4436 
4437  if (au_fetch_class (classop, &smclass, AU_FETCH_READ, AU_SELECT) != NO_ERROR || !smclass->partition)
4438  {
4439  return 0;
4440  }
4441 
4442  if (smclass->partition->pname != NULL)
4443  {
4444  ret = 1; /* partitioned sub-class */
4445  }
4446  else
4447  {
4448  if (is_partitioned)
4449  {
4450  *is_partitioned = 1;
4451  }
4452 
4453  if (keyattr)
4454  {
4455  const char *p = NULL;
4456 
4457  keyattr[0] = 0;
4458 
4459  if (set_get_element_nocopy (smclass->partition->values, 0, &attrname) == NO_ERROR && !DB_IS_NULL (&attrname)
4460  && (p = db_get_string (&attrname)))
4461  {
4462  strncpy (keyattr, p, DB_MAX_IDENTIFIER_LENGTH);
4463  if (strlen (p) < DB_MAX_IDENTIFIER_LENGTH)
4464  {
4465  keyattr[strlen (p)] = 0;
4466  }
4467  else
4468  {
4469  keyattr[DB_MAX_IDENTIFIER_LENGTH] = 0;
4470  }
4471  }
4472  }
4473  }
4474 
4475  return ret;
4476 }
4477 
4478 /*
4479  * do_drop_partition() -
4480  * return: Error code
4481  * class(in):
4482  * drop_sub_flag(in):
4483  * is_cascade_constraints(in):
4484  *
4485  * Note:
4486  */
4487 int
4488 do_drop_partitioned_class (MOP class_, int drop_sub_flag, bool is_cascade_constraints)
4489 {
4490  DB_OBJLIST *objs;
4491  SM_CLASS *smclass, *subclass;
4492  MOP delobj;
4493  int error = NO_ERROR;
4494 
4496 
4497  if (!class_)
4498  {
4499  return ER_FAILED;
4500  }
4501 
4502  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
4503  if (error != NO_ERROR)
4504  {
4505  goto fail_return;
4506  }
4507  if (!smclass->partition)
4508  {
4509  goto fail_return;
4510  }
4511 
4512  if (smclass->users == NULL)
4513  {
4514  /* this is a partition, not the partitioned table */
4516  error = ER_FAILED;
4517  goto fail_return;
4518  }
4519 
4520  for (objs = smclass->users; objs;)
4521  {
4522  error = au_fetch_class (objs->op, &subclass, AU_FETCH_READ, AU_SELECT);
4523  if (error != NO_ERROR)
4524  {
4525  goto fail_return;
4526  }
4527  if (subclass->partition)
4528  {
4529  delobj = objs->op;
4530  objs = objs->next;
4531  if (drop_sub_flag)
4532  {
4533  error = sm_delete_class_mop (delobj, is_cascade_constraints);
4534  if (error != NO_ERROR)
4535  {
4536  goto fail_return;
4537  }
4538  }
4539  }
4540  else
4541  {
4542  objs = objs->next;
4543  }
4544  }
4545 
4546  error = NO_ERROR;
4547 
4548 fail_return:
4549  return error;
4550 }
4551 
4552 /*
4553  * partition_rename() -
4554  * return: Error code
4555  * old_class(in):
4556  * newname(in):
4557  *
4558  * Note:
4559  */
4560 int
4561 do_rename_partition (MOP old_class, const char *newname)
4562 {
4563  DB_OBJLIST *objs;
4564  SM_CLASS *smclass, *subclass;
4565  int newlen;
4566  int error;
4567  char new_subname[PARTITION_VARCHAR_LEN + 1], *ptr;
4568 
4569  if (!old_class || !newname)
4570  {
4571  return ER_FAILED;
4572  }
4573 
4574  newlen = strlen (newname);
4575 
4576  error = au_fetch_class (old_class, &smclass, AU_FETCH_READ, AU_SELECT);
4577  if (error != NO_ERROR)
4578  {
4579  goto end_rename;
4580  }
4581 
4582  for (objs = smclass->users; objs; objs = objs->next)
4583  {
4584  error = au_fetch_class (objs->op, &subclass, AU_FETCH_READ, AU_SELECT);
4585  if (error != NO_ERROR)
4586  {
4587  goto end_rename;
4588  }
4589  if (subclass->partition)
4590  {
4591  ptr = strstr ((char *) sm_ch_name ((MOBJ) subclass), PARTITIONED_SUB_CLASS_TAG);
4592  if (ptr == NULL)
4593  {
4595  error = ER_PARTITION_WORK_FAILED;
4596  goto end_rename;
4597  }
4598 
4599  if ((newlen + strlen (ptr)) >= PARTITION_VARCHAR_LEN)
4600  {
4602  error = ER_PARTITION_WORK_FAILED;
4603  goto end_rename;
4604  }
4605  sprintf (new_subname, "%s%s", newname, ptr);
4606 
4607  error = sm_rename_class (objs->op, new_subname);
4608  if (error != NO_ERROR)
4609  {
4610  break;
4611  }
4612  }
4613  }
4614 
4615 end_rename:
4616 
4617  return error;
4618 }
4619 
4620 /*
4621  * do_redistribute_partitions_data() -
4622  * return: error code or NO_ERROR
4623  * classname(in):
4624  * keyname(in):
4625  * promoted(in):
4626  * promoted_count(in):
4627  * alter_op(in):
4628  * should_update(in):
4629  * should_insert(in):
4630  * Note:
4631  */
4632 static int
4633 do_redistribute_partitions_data (const char *classname, const char *keyname, char **promoted, int promoted_count,
4634  PT_ALTER_CODE alter_op, bool should_update, bool should_insert)
4635 {
4636  int error = NO_ERROR;
4637  DB_QUERY_RESULT *query_result;
4638  DB_QUERY_ERROR query_error;
4639  char *query_buf;
4640  size_t query_size;
4641  int i = 0;
4642  MOP subclass_mop, class_mop;
4643  OID *partitions = NULL;
4644  SM_CONSTRAINT_INFO *index_save_info = NULL;
4645 
4646  if (should_update)
4647  {
4648  query_size = 0;
4649  query_size += 7; /* 'UPDATE ' */
4650  query_size += strlen (classname) + 2;
4651  query_size += 5; /* ' SET ' */
4652  query_size += strlen (keyname) * 2 + 6; /* [keyname]=[keyname]; */
4653  query_buf = (char *) malloc (query_size + 1);
4654  if (query_buf == NULL)
4655  {
4657  return ER_FAILED;
4658  }
4659  sprintf (query_buf, "UPDATE [%s] SET [%s]=[%s];", classname, keyname, keyname);
4660 
4661  error = db_compile_and_execute_local (query_buf, &query_result, &query_error);
4662  if (error >= 0)
4663  {
4664  error = NO_ERROR;
4665  db_query_end (query_result);
4666  }
4667  free_and_init (query_buf);
4668  if (error < 0)
4669  {
4670  return error;
4671  }
4672  }
4673 
4674  if (should_insert)
4675  {
4676  class_mop = sm_find_class (classname);
4677  if (class_mop == NULL)
4678  {
4679  assert (er_errid () != NO_ERROR);
4680  error = er_errid ();
4681  goto exit;
4682  }
4683 
4684  if (alter_op != PT_REORG_PARTITION)
4685  {
4686  error = do_save_all_indexes (class_mop, &index_save_info);
4687  if (error != NO_ERROR)
4688  {
4689  goto exit;
4690  }
4691 
4692  error = do_drop_saved_indexes (class_mop, index_save_info);
4693  if (error != NO_ERROR)
4694  {
4695  goto exit;
4696  }
4697  }
4698 
4699  partitions = (OID *) malloc (promoted_count * sizeof (OID));
4700  if (partitions == NULL)
4701  {
4702  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, promoted_count * sizeof (OID));
4703  error = ER_OUT_OF_VIRTUAL_MEMORY;
4704  goto exit;
4705  }
4706 
4707  for (i = 0; i < promoted_count; i++)
4708  {
4709  subclass_mop = sm_find_class (promoted[i]);
4710  if (subclass_mop == NULL)
4711  {
4712  assert (er_errid () != NO_ERROR);
4713  error = er_errid ();
4714  goto exit;
4715  }
4716  COPY_OID (&partitions[i], &subclass_mop->oid_info.oid);
4717  }
4718 
4719  error = locator_redistribute_partition_data (&class_mop->oid_info.oid, promoted_count, partitions);
4720  if (error != NO_ERROR)
4721  {
4722  goto exit;
4723  }
4724 
4725  if (alter_op != PT_REORG_PARTITION)
4726  {
4727  error = do_recreate_saved_indexes (class_mop, index_save_info);
4728  }
4729  }
4730 
4731 exit:
4732  if (partitions != NULL)
4733  {
4734  free_and_init (partitions);
4735  }
4736  if (index_save_info != NULL)
4737  {
4738  sm_free_constraint_info (&index_save_info);
4739  }
4740  return error;
4741 }
4742 
4743 
4744 /*
4745  * do_find_auto_increment_serial() -
4746  * return: Error code
4747  * auto_increment_obj(out):
4748  * class_name(in):
4749  * atrr_name(in):
4750  *
4751  * Note:
4752  */
4753 static int
4754 do_find_auto_increment_serial (MOP * auto_increment_obj, const char *class_name, const char *attr_name)
4755 {
4756  MOP serial_class = NULL;
4757  char *serial_name = NULL;
4758  size_t serial_name_size;
4759  DB_IDENTIFIER serial_obj_id;
4760  int error = NO_ERROR;
4761 
4762  assert (class_name != NULL && attr_name != NULL);
4763 
4764  *auto_increment_obj = NULL;
4765 
4766  serial_class = sm_find_class (CT_SERIAL_NAME);
4767  if (serial_class == NULL)
4768  {
4770  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4771  goto end;
4772  }
4773 
4774  serial_name_size = strlen (class_name) + strlen (attr_name) + AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH + 1;
4775 
4776  serial_name = (char *) malloc (serial_name_size);
4777  if (serial_name == NULL)
4778  {
4779  error = ER_OUT_OF_VIRTUAL_MEMORY;
4780  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, serial_name_size);
4781  goto end;
4782  }
4783 
4784  SET_AUTO_INCREMENT_SERIAL_NAME (serial_name, class_name, attr_name);
4785 
4786  *auto_increment_obj = do_get_serial_obj_id (&serial_obj_id, serial_class, serial_name);
4787  if (*auto_increment_obj == NULL)
4788  {
4789  error = ER_QPROC_SERIAL_NOT_FOUND;
4790  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, serial_name);
4791  goto end;
4792  }
4793 
4794 end:
4795  if (serial_name != NULL)
4796  {
4797  free_and_init (serial_name);
4798  }
4799 
4800  return error;
4801 }
4802 
4803 /*
4804  * adjust_partition_range() -
4805  * return: Error code
4806  * objs(in):
4807  *
4808  * Note:
4809  */
4810 static int
4812 {
4813  DB_OBJLIST *subs;
4814  SM_CLASS *subclass;
4815  DB_VALUE minval, maxval, seqval, *wrtval;
4816  int error = NO_ERROR;
4817  char check_flag = 1;
4818  DB_VALUE_SLIST *ranges = NULL, *rfind, *new_range, *prev_range;
4819  DB_COLLECTION *dbc = NULL;
4820  SM_TEMPLATE *tmpl = NULL;
4821 
4822  db_make_null (&minval);
4823  db_make_null (&maxval);
4824 
4825  for (subs = objs; subs; subs = subs->next)
4826  {
4827  error = au_fetch_class (subs->op, &subclass, AU_FETCH_READ, AU_SELECT);
4828  if (error != NO_ERROR)
4829  {
4830  break;
4831  }
4832  if (!subclass->partition)
4833  {
4834  continue;
4835  }
4836 
4837  if (check_flag)
4838  { /* RANGE check */
4839  if (subclass->partition->partition_type != PT_PARTITION_RANGE)
4840  {
4841  break;
4842  }
4843  check_flag = 0;
4844  }
4845 
4846  if (subclass->partition->expr != NULL)
4847  {
4848  continue; /* reorg deleted partition */
4849  }
4850  error = set_get_element_nocopy (subclass->partition->values, 0, &minval);
4851  if (error != NO_ERROR)
4852  {
4853  break;
4854  }
4855  error = set_get_element_nocopy (subclass->partition->values, 1, &maxval);
4856  if (error != NO_ERROR)
4857  {
4858  break;
4859  }
4860  if ((new_range = (DB_VALUE_SLIST *) malloc (sizeof (DB_VALUE_SLIST))) == NULL)
4861  {
4862  error = ER_OUT_OF_VIRTUAL_MEMORY;
4863  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, sizeof (DB_VALUE_SLIST));
4864  break;
4865  }
4866  new_range->partition = subclass->partition;
4867  new_range->class_obj = subs->op;
4868  new_range->min = db_value_copy (&minval);
4869  new_range->max = db_value_copy (&maxval);
4870  new_range->next = NULL;
4871 
4872  if (ranges == NULL)
4873  {
4874  ranges = new_range;
4875  }
4876  else
4877  { /* sort ranges */
4878  for (rfind = ranges, prev_range = NULL; rfind; rfind = rfind->next)
4879  {
4880  if (DB_IS_NULL (rfind->max) || db_value_compare (rfind->max, new_range->max) == DB_GT)
4881  {
4882  if (prev_range == NULL)
4883  {
4884  new_range->next = ranges;
4885  ranges = new_range;
4886  }
4887  else
4888  {
4889  new_range->next = prev_range->next;
4890  prev_range->next = new_range;
4891  }
4892  break;
4893  }
4894  prev_range = rfind;
4895  }
4896 
4897  if (rfind == NULL)
4898  {
4899  prev_range->next = new_range;
4900  }
4901  }
4902  }
4903 
4904  for (rfind = ranges, prev_range = NULL; rfind; rfind = rfind->next)
4905  {
4906  wrtval = NULL;
4907  if (prev_range == NULL)
4908  { /* Min value of first range is low infinite */
4909  if (!DB_IS_NULL (rfind->min))
4910  {
4911  db_make_null (&minval);
4912  wrtval = &minval;
4913  }
4914  }
4915  else
4916  {
4917  if (db_value_compare (prev_range->max, rfind->min) != DB_EQ)
4918  {
4919  wrtval = prev_range->max;
4920  }
4921  }
4922  if (wrtval != NULL)
4923  { /* adjust min value of range */
4924  dbc = set_create_sequence (0);
4925  if (dbc != NULL)
4926  {
4927  set_add_element (dbc, wrtval);
4928  set_add_element (dbc, rfind->max);
4929  db_make_sequence (&seqval, dbc);
4930 
4931  tmpl = dbt_edit_class (rfind->class_obj);
4932  if (tmpl == NULL)
4933  {
4934  set_free (dbc);
4935  error = ER_FAILED;
4936  break;
4937  }
4938 
4939  if (tmpl->partition->values != NULL)
4940  {
4941  /* free previous set */
4942  set_free (tmpl->partition->values);
4943  tmpl->partition->values = NULL;
4944  }
4945 
4946  tmpl->partition->values = db_seq_copy (dbc);
4947  if (tmpl->partition->values == NULL)
4948  {
4949  set_free (dbc);
4950  dbt_abort_class (tmpl);
4951  error = ER_FAILED;
4952  break;
4953  }
4954 
4955  if (dbt_finish_class (tmpl) == NULL)
4956  {
4957  set_free (dbc);
4958  dbt_abort_class (tmpl);
4959  error = ER_FAILED;
4960  break;
4961  }
4962  set_free (dbc);
4963  }
4964 
4965  if (error != NO_ERROR)
4966  {
4967  break;
4968  }
4969  }
4970  prev_range = rfind;
4971  }
4972 
4973  for (rfind = ranges; rfind;)
4974  {
4975  db_value_free (rfind->min);
4976  db_value_free (rfind->max);
4977  prev_range = rfind->next;
4978  free_and_init (rfind);
4979  rfind = prev_range;
4980  }
4981 
4982  return error;
4983 }
4984 
4985 /*
4986  * adjust_partition_size() -
4987  * return: Error code
4988  * class(in):
4989  * tmpl (in): partitioned class template
4990  *
4991  * Note:
4992  */
4993 static int
4995 {
4996  int error = NO_ERROR;
4997  SM_CLASS *smclass, *subclass;
4998  DB_VALUE psize;
4999  DB_OBJLIST *subs;
5000  int partcnt;
5001 
5002  if (class_ == NULL)
5003  {
5005  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5006  return error;
5007  }
5008 
5009  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
5010  if (error != NO_ERROR)
5011  {
5012  return error;
5013  }
5014 
5015  if (smclass->partition == NULL || tmpl == NULL)
5016  {
5018  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5019  return error;
5020  }
5021 
5022  db_make_null (&psize);
5023 
5024  for (subs = smclass->users, partcnt = 0; subs; subs = subs->next)
5025  {
5026  error = au_fetch_class (subs->op, &subclass, AU_FETCH_READ, AU_SELECT);
5027  if (error != NO_ERROR)
5028  {
5029  return error;
5030  }
5031  if (!subclass->partition)
5032  {
5033  continue;
5034  }
5035  partcnt++;
5036  }
5037 
5038  error = set_get_element_nocopy (tmpl->partition->values, 1, &psize);
5039  if (error != NO_ERROR)
5040  {
5041  return error;
5042  }
5043 
5044  if (psize.data.i != partcnt)
5045  {
5046  psize.data.i = partcnt;
5047  error = set_put_element (tmpl->partition->values, 1, &psize);
5048  if (error != NO_ERROR)
5049  {
5050  return error;
5051  }
5052  }
5053 
5054  return NO_ERROR;
5055 }
5056 
5057 /*
5058  * do_get_partition_size() -
5059  * return: Size if success, else error code
5060  * class(in):
5061  *
5062  * Note:
5063  */
5064 int
5066 {
5067  int error = NO_ERROR;
5068  SM_CLASS *smclass;
5069  DB_VALUE psize;
5070 
5071  if (class_ == NULL)
5072  {
5073  return ER_FAILED;
5074  }
5075  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
5076  if (error != NO_ERROR)
5077  {
5078  return error;
5079  }
5080 
5081  if (!smclass->partition)
5082  {
5084  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5085  return error;
5086  }
5087 
5088  db_make_null (&psize);
5089 
5090  error = set_get_element_nocopy (smclass->partition->values, 1, &psize);
5091  if (error != NO_ERROR)
5092  {
5093  return error;
5094  }
5095  error = psize.data.i;
5096  if (error == 0)
5097  {
5098  error = ER_FAILED;
5099  }
5100 
5101  return error;
5102 }
5103 
5104 /*
5105  * do_get_partition_keycol() -
5106  * return: Error code
5107  * keycol(out):
5108  * class(in):
5109  *
5110  * Note:
5111  */
5112 int
5113 do_get_partition_keycol (char *keycol, MOP class_)
5114 {
5115  int error = NO_ERROR;
5116  SM_CLASS *smclass;
5117  DB_VALUE keyname;
5118  const char *keyname_str;
5119 
5120  if (class_ == NULL || keycol == NULL)
5121  {
5123  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5124  return error;
5125  }
5126 
5127  *keycol = '\0';
5128 
5129  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
5130  if (error != NO_ERROR)
5131  {
5132  return error;
5133  }
5134 
5135  if (!smclass->partition)
5136  {
5138  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5139  return error;
5140  }
5141 
5142  db_make_null (&keyname);
5143 
5144  error = set_get_element_nocopy (smclass->partition->values, 0, &keyname);
5145  if (error != NO_ERROR)
5146  {
5147  return error;
5148  }
5149 
5150  if (DB_IS_NULL (&keyname))
5151  {
5152  return error;
5153  }
5154 
5155  keyname_str = db_get_string (&keyname);
5156  strncpy (keycol, keyname_str, DB_MAX_IDENTIFIER_LENGTH);
5157  error = NO_ERROR;
5158 
5159  return error;
5160 }
5161 
5162 /*
5163  * do_drop_partition_list() -
5164  * return: Error code
5165  * class(in):
5166  * name_list(in):
5167  * tmpl (in): partitioned class template
5168  *
5169  * Note:
5170  */
5171 int
5172 do_drop_partition_list (MOP class_, PT_NODE * name_list, DB_CTMPL * tmpl)
5173 {
5174  PT_NODE *names;
5175  int error = NO_ERROR;
5176  char subclass_name[DB_MAX_IDENTIFIER_LENGTH];
5177  SM_CLASS *smclass, *subclass;
5178  MOP classcata;
5179  OID *partitions = NULL;
5180  int no_partitions = 0;
5181  int i;
5182 
5183  if (class_ == NULL || name_list == NULL)
5184  {
5185  return ER_FAILED;
5186  }
5187 
5188  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
5189  if (error != NO_ERROR)
5190  {
5191  goto exit;
5192  }
5193 
5194  if (smclass->partition == NULL)
5195  {
5197  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5198  goto exit;
5199  }
5200 
5201  for (names = name_list; names; names = names->next)
5202  {
5203  no_partitions++;
5204  }
5205 
5206  partitions = (OID *) malloc (no_partitions * sizeof (OID));
5207  if (partitions == NULL)
5208  {
5209  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, no_partitions * sizeof (OID));
5210  error = ER_OUT_OF_VIRTUAL_MEMORY;
5211  goto exit;
5212  }
5213 
5214  for (names = name_list, i = 0; names; names = names->next, i++)
5215  {
5216  sprintf (subclass_name, "%s" PARTITIONED_SUB_CLASS_TAG "%s", sm_ch_name ((MOBJ) smclass),
5217  names->info.name.original);
5218  classcata = sm_find_class (subclass_name);
5219  if (classcata == NULL)
5220  {
5221  assert (er_errid () != NO_ERROR);
5222  error = er_errid ();
5223  goto exit;
5224  }
5225 
5226  COPY_OID (&partitions[i], &classcata->oid_info.oid);
5227  }
5228 
5229  for (names = name_list, i = 0; names; names = names->next, i++)
5230  {
5231  sprintf (subclass_name, "%s" PARTITIONED_SUB_CLASS_TAG "%s", smclass->header.ch_name, names->info.name.original);
5232  classcata = sm_find_class (subclass_name);
5233  if (classcata == NULL)
5234  {
5235  assert (er_errid () != NO_ERROR);
5236  error = er_errid ();
5237  goto exit;
5238  }
5239 
5240  COPY_OID (&partitions[i], &classcata->oid_info.oid);
5241 
5242  error = au_fetch_class (classcata, &subclass, AU_FETCH_READ, AU_SELECT);
5243  if (error != NO_ERROR)
5244  {
5245  goto exit;
5246  }
5247  if (subclass->partition)
5248  {
5249  error = sm_delete_class_mop (classcata, false);
5250  if (error != NO_ERROR)
5251  {
5252  goto exit;
5253  }
5254  }
5255  else
5256  {
5257  error = ER_PARTITION_NOT_EXIST;
5258  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
5259  goto exit;
5260  }
5261  }
5262 
5263  error = adjust_partition_range (smclass->users);
5264  if (error != NO_ERROR)
5265  {
5266  goto exit;
5267  }
5268 
5269  error = adjust_partition_size (class_, tmpl);
5270  if (error != NO_ERROR)
5271  {
5272  goto exit;
5273  }
5274 
5275  error = NO_ERROR;
5276 
5277 exit:
5278  if (partitions != NULL)
5279  {
5280  free_and_init (partitions);
5281  }
5282  return error;
5283 }
5284 
5285 /*
5286  * do_create_partition_constraints () - copy indexes from the root table to
5287  * partitions
5288  * return : error code or NO_ERROR
5289  * parser (in) : parser context
5290  * alter (in) : alter node
5291  * pinfo (in) : partition alter context
5292  *
5293  * Note: At the moment the following constraints are added to partitions:
5294  * - SM_CONSTRAINT_INDEX
5295  * - SM_CONSTRAINT_REVERSE_INDEX
5296  */
5297 static int
5299 {
5300  SM_CLASS *smclass = NULL;
5301  SM_CLASS_CONSTRAINT *cons = NULL;
5302  int error = NO_ERROR;
5303 
5304  /* sanity check */
5305  assert (parser != NULL && alter != NULL && pinfo != NULL);
5306  CHECK_3ARGS_ERROR (parser, alter, pinfo);
5307 
5308  smclass = sm_get_class_with_statistics (pinfo->root_op);
5309  if (smclass == NULL)
5310  {
5311  assert (er_errid () != NO_ERROR);
5312  return er_errid ();
5313  }
5314 
5315 
5316  for (cons = smclass->constraints; cons != NULL; cons = cons->next)
5317  {
5318  if (cons->type != SM_CONSTRAINT_INDEX && cons->type != SM_CONSTRAINT_REVERSE_INDEX)
5319  {
5320  continue;
5321  }
5322  error = do_create_partition_constraint (alter, smclass, cons, pinfo);
5323  if (error != NO_ERROR)
5324  {
5325  return error;
5326  }
5327  }
5328 
5329  return error;
5330 }
5331 
5332 /*
5333  * do_create_partition_constraint () - copy a constraint from the root class
5334  * to the new partitions
5335  * return : error code or NO_ERROR
5336  * alter (in) : alter node
5337  * root_class (in) : root class
5338  * constraint (in) : root constraint
5339  */
5340 static int
5342  SM_PARTITION_ALTER_INFO * pinfo)
5343 {
5344  int error = NO_ERROR, i = 0;
5345  char **namep = NULL, **attrnames = NULL;
5346  int *asc_desc = NULL;
5347  SM_CLASS *subclass = NULL;
5348  SM_ATTRIBUTE **attp = NULL;
5349  TP_DOMAIN *key_type = NULL;
5350  DB_OBJLIST *objs = NULL;
5351  PT_ALTER_CODE alter_op;
5352  PT_NODE *parts;
5353  SM_FUNCTION_INFO *new_func_index_info = NULL;
5354 
5355  alter_op = alter->info.alter.code;
5356  attp = constraint->attributes;
5357  i = 0;
5358  /* count attributes in constraint */
5359  while (*attp)
5360  {
5361  attp++;
5362  i++;
5363  }
5364  if (i == 0)
5365  {
5366  assert (false);
5368  error = ER_FAILED;
5369  goto cleanup;
5370  }
5371 
5372  namep = (char **) malloc ((i + 1) * sizeof (char *));
5373  if (namep == NULL)
5374  {
5375  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (i + 1) * sizeof (char *));
5376  error = ER_FAILED;
5377  goto cleanup;
5378  }
5379  asc_desc = (int *) malloc (i * sizeof (int));
5380  if (asc_desc == NULL)
5381  {
5383  error = ER_FAILED;
5384  goto cleanup;
5385  }
5386 
5387  attp = constraint->attributes;
5388  attrnames = namep;
5389  key_type = classobj_find_cons_index2_col_type_list (constraint, &pinfo->root_op->oid_info.oid);
5390  if (key_type == NULL)
5391  {
5392  if ((error = er_errid ()) == NO_ERROR)
5393  {
5394  /* set an error if none was set yet */
5395  error = ER_PARTITION_WORK_FAILED;
5397  }
5398  goto cleanup;
5399  }
5400 
5401  i = 0;
5402  while (*attp && key_type)
5403  {
5404  *attrnames = (char *) (*attp)->header.name;
5405  attrnames++;
5406  asc_desc[i] = 0; /* guess as Asc */
5407  if (DB_IS_CONSTRAINT_REVERSE_INDEX_FAMILY (constraint->type) || key_type->is_desc)
5408  {
5409  asc_desc[i] = 1; /* Desc */
5410  }
5411  i++;
5412  attp++;
5413  key_type = key_type->next;
5414  }
5415 
5416  *attrnames = NULL;
5417 
5418  if (alter_op == PT_ADD_PARTITION || alter_op == PT_REORG_PARTITION || alter_op == PT_ADD_HASHPARTITION)
5419  {
5420  /* only create constraint for new partitions */
5421  parts = alter->info.alter.alter_clause.partition.parts;
5422  for (; parts; parts = parts->next)
5423  {
5424  MOP subclass_op = parts->info.parts.name->info.name.db_object;
5425 
5426  if (alter_op == PT_REORG_PARTITION && parts->flag.partition_pruned)
5427  {
5428  continue; /* reused partition */
5429  }
5430  error = au_fetch_class (subclass_op, &subclass, AU_FETCH_READ, AU_SELECT);
5431  if (error != NO_ERROR)
5432  {
5433  assert (er_errid () != NO_ERROR);
5434  error = er_errid ();
5435  goto cleanup;
5436  }
5437 
5438  if (subclass->partition == NULL)
5439  {
5440  assert (false);
5441  error = ER_FAILED;
5443  goto cleanup;
5444  }
5445 
5446  if (constraint->func_index_info)
5447  {
5448  error = sm_save_function_index_info (&new_func_index_info, constraint->func_index_info);
5449  if (error != NO_ERROR)
5450  {
5451  goto cleanup;
5452  }
5453  error =
5454  do_recreate_func_index_constr (NULL, NULL, new_func_index_info, NULL, sm_ch_name ((MOBJ) root_class),
5455  sm_ch_name ((MOBJ) subclass));
5456  if (error != NO_ERROR)
5457  {
5458  goto cleanup;
5459  }
5460  }
5461  else
5462  {
5463  new_func_index_info = NULL;
5464  }
5465 
5466  error =
5467  sm_add_constraint (subclass_op, db_constraint_type (constraint), constraint->name, (const char **) namep,
5468  asc_desc, constraint->attrs_prefix_length, false, constraint->filter_predicate,
5469  new_func_index_info, constraint->comment, constraint->index_status);
5470  if (error != NO_ERROR)
5471  {
5472  goto cleanup;
5473  }
5474 
5475  if (new_func_index_info)
5476  {
5477  sm_free_function_index_info (new_func_index_info);
5478  free_and_init (new_func_index_info);
5479  }
5480  }
5481  }
5482  else
5483  {
5484  for (objs = root_class->users; objs; objs = objs->next)
5485  {
5486  error = au_fetch_class (objs->op, &subclass, AU_FETCH_READ, AU_SELECT);
5487  if (error != NO_ERROR)
5488  {
5489  assert (er_errid () != NO_ERROR);
5490  error = er_errid ();
5491  goto cleanup;
5492  }
5493 
5494  if (subclass->partition == NULL)
5495  {
5496  /* not partitioned */
5497  continue;
5498  }
5499 
5500  if (constraint->func_index_info)
5501  {
5502  error = sm_save_function_index_info (&new_func_index_info, constraint->func_index_info);
5503  if (error != NO_ERROR)
5504  {
5505  goto cleanup;
5506  }
5507  error =
5508  do_recreate_func_index_constr (NULL, NULL, new_func_index_info, NULL, sm_ch_name ((MOBJ) root_class),
5509  sm_ch_name ((MOBJ) subclass));
5510  if (error != NO_ERROR)
5511  {
5512  goto cleanup;
5513  }
5514  }
5515  else
5516  {
5517  new_func_index_info = NULL;
5518  }
5519 
5520  error =
5521  sm_add_constraint (objs->op, db_constraint_type (constraint), constraint->name, (const char **) namep,
5522  asc_desc, constraint->attrs_prefix_length, false, constraint->filter_predicate,
5523  new_func_index_info, constraint->comment, constraint->index_status);
5524  if (error != NO_ERROR)
5525  {
5526  goto cleanup;
5527  }
5528 
5529  if (new_func_index_info)
5530  {
5531  sm_free_function_index_info (new_func_index_info);
5532  free_and_init (new_func_index_info);
5533  }
5534  }
5535  }
5536 
5537 cleanup:
5538  if (namep != NULL)
5539  {
5540  free_and_init (namep);
5541  }
5542  if (asc_desc != NULL)
5543  {
5544  free_and_init (asc_desc);
5545  }
5546  if (new_func_index_info)
5547  {
5548  sm_free_function_index_info (new_func_index_info);
5549  free_and_init (new_func_index_info);
5550  }
5551  return error;
5552 }
5553 
5554 /*
5555  * do_alter_partitioning_pre () - perform partition manipulation
5556  * return : error code or NO_ERROR
5557  * parser (in) : parser context
5558  * alter (in) : the alter node
5559  * pinfo (in/out) : partition alter context
5560  *
5561  * Note: Altering a partitioned class is an action that that involves two
5562  * steps:
5563  * 1. modifying the schema of the partitioned class
5564  * 2. redistributing the data to the new schema
5565  * The "pre" action is the action responsible for schema modification.
5566  * We must ensure that the result of this action is a valid schema because
5567  * the redistributing action can only be performed on a valid schema.
5568  * The pre action performs the following actions:
5569  * PT_APPLY_PARTITION
5570  * PT_ADD_PARTITION
5571  * PT_ADD_HASHPARTITION
5572  * - create [new] partitions and update the root class with this info
5573  * PT_REMOVE_PARTITION
5574  * - promote all partitions from the schema to normal classes
5575  * PT_COALESCE_PARTITION
5576  * - promote partitions which will be dropped
5577  * PT_REORG_PARTITION
5578  * - promote partitions which will be reorganized
5579  * PT_ANALYZE_PARTITION
5580  * - N/A
5581  * PT_DROP_PARTITION
5582  * - drop partitions
5583  * PT_PROMOTE_PARTITION:
5584  * - promote partitions
5585  */
5586 static int
5588 {
5589  PT_ALTER_CODE alter_op;
5590  int error = NO_ERROR;
5591  const char *entity_name = NULL;
5592 
5593  /* sanity check */
5594  assert (parser != NULL && alter != NULL && pinfo != NULL);
5595  CHECK_3ARGS_ERROR (parser, alter, pinfo);
5596  assert (pinfo->root_op != NULL && pinfo->root_tmpl != NULL);
5597 
5598  entity_name = alter->info.alter.entity_name->info.name.original;
5599  if (entity_name == NULL)
5600  {
5601  ERROR1 (error, ER_UNEXPECTED, "Expecting a class or virtual class name.");
5602  return ER_FAILED;
5603  }
5604 
5605  alter_op = alter->info.alter.code;
5606  if (alter_op != PT_ANALYZE_PARTITION && alter_op != PT_ADD_PARTITION)
5607  {
5608  /* Check to see if the root class is referenced by foreign keys. If the class is referenced by a foreign key, we
5609  * only allow PT_ADD_PARTITION and PT_ANALYZE_PARTITION alter operations. All other alter operations will
5610  * probably move data through different classes which is hard to track and can cause the foreign key constraint
5611  * to be violated. */
5612  SM_CLASS *root_class = NULL;
5613  SM_CLASS_CONSTRAINT *pk;
5614  error = au_fetch_class (pinfo->root_op, &root_class, AU_FETCH_READ, AU_SELECT);
5615  if (error != NO_ERROR)
5616  {
5617  return error;
5618  }
5619 
5620  pk = classobj_find_cons_primary_key (root_class->constraints);
5621  if (pk != NULL && pk->fk_info != NULL && classobj_is_pk_referred (pinfo->root_op, pk->fk_info, true, NULL))
5622  {
5624  return ER_FAILED;
5625  }
5626  }
5627 
5628  if (alter_op != PT_APPLY_PARTITION)
5629  {
5630  /* get partition key, we're going to need it later on */
5631  error = do_get_partition_keycol (pinfo->keycol, pinfo->root_op);
5632  if (error != NO_ERROR)
5633  {
5634  return error;
5635  }
5636  }
5637 
5638  switch (alter_op)
5639  {
5640  case PT_APPLY_PARTITION:
5641  {
5642  PT_NODE *pt_key_col = NULL;
5643  const char *key_col_name = NULL;
5644  SM_ATTRIBUTE *attr = NULL;
5645  error = do_check_fk_constraints_internal (pinfo->root_tmpl, alter->info.alter.constraint_list, true);
5646  if (error != NO_ERROR)
5647  {
5648  return error;
5649  }
5650  /* Set SM_ATTFLAG_PARTITION_KEY on the partitioning key. Notice that at this point, we have access to the root
5651  * class template which is being edited. The calling function will call finish on this template and we will
5652  * create the actual partitions on the "post" action of the alter statement. */
5653  pt_key_col = alter->info.alter.alter_clause.partition.info->info.partition.keycol;
5654  key_col_name = pt_key_col->info.name.original;
5655  attr = pinfo->root_tmpl->attributes;
5656 
5657  while (attr != NULL)
5658  {
5659  if (SM_COMPARE_NAMES (key_col_name, attr->header.name) == 0)
5660  {
5662  break;
5663  }
5664  attr = (SM_ATTRIBUTE *) attr->header.next;
5665  }
5666  break;
5667  }
5668  case PT_ADD_PARTITION:
5669  case PT_ADD_HASHPARTITION:
5670  /* create new partitions */
5671  error = do_create_partition (parser, alter, pinfo);
5672  if (error != NO_ERROR)
5673  {
5674  return error;
5675  }
5676  error = do_check_fk_constraints (pinfo->root_tmpl, alter->info.alter.constraint_list);
5677  break;
5678  case PT_REMOVE_PARTITION:
5679  error = do_remove_partition_pre (parser, alter, pinfo);
5680  break;
5681  case PT_COALESCE_PARTITION:
5682  error = do_coalesce_partition_pre (parser, alter, pinfo);
5683  break;
5684  case PT_REORG_PARTITION:
5685  error = do_reorganize_partition_pre (parser, alter, pinfo);
5686  break;
5687  case PT_ANALYZE_PARTITION:
5688  break;
5689  case PT_DROP_PARTITION:
5690  error =
5691  do_drop_partition_list (pinfo->root_op, alter->info.alter.alter_clause.partition.name_list, pinfo->root_tmpl);
5692  break;
5693  case PT_PROMOTE_PARTITION:
5694  error = do_promote_partition_list (parser, alter, pinfo);
5695  break;
5696  default:
5697  error = ER_FAILED;
5698  break;
5699  }
5700 
5701  return error;
5702 }
5703 
5704 /*
5705  * do_alter_partitioning_post () - redistribute data for partition
5706  * manipulation
5707  * return : error code or NO_ERROR
5708  * parser (in) : parser context
5709  * alter (in) : the alter node
5710  * pinfo (in/out) : partition alter context
5711  *
5712  * Note: Altering a partitioned class is an action that that involves two
5713  * steps:
5714  * 1. modifying the schema of the partitioned class
5715  * 2. redistributing the data to the new schema
5716  * The "post" action is the action responsible for redistributing data.
5717  * The post action performs the following actions:
5718  * PT_APPLY_PARTITION
5719  * PT_ADD_HASHPARTITION
5720  * - redistribute data from the root table [and the old partitions] to the
5721  * new partitioning schema by performing "UPDATE t SET * = *"
5722  * PT_REMOVE_PARTITION
5723  * PT_COALESCE_PARTITION
5724  * PT_REORG_PARTITION
5725  * - redistribute data from the partitions promoted in the pre action to
5726  * the new schema (using INSERT SELECT)and drop the promoted partitions
5727  * PT_ANALYZE_PARTITION
5728  * - update statistics on partitions
5729  * PT_ADD_PARTITION
5730  * PT_DROP_PARTITION
5731  * PT_PROMOTE_PARTITION:
5732  * - N/A
5733  */
5734 static int
5736 {
5737  PT_ALTER_CODE alter_op;
5738  int error = NO_ERROR;
5739  const char *entity_name = NULL;
5740 
5741  assert (parser != NULL && alter != NULL && pinfo != NULL);
5742  CHECK_3ARGS_ERROR (parser, alter, pinfo);
5743 
5744  assert (alter != NULL);
5745  assert (alter->node_type == PT_ALTER);
5746 
5747  alter_op = alter->info.alter.code;
5748 
5749  entity_name = alter->info.alter.entity_name->info.name.original;
5750  if (entity_name == NULL)
5751  {
5752  ERROR1 (error, ER_UNEXPECTED, "Expecting a class or virtual class name.");
5753  return ER_FAILED;
5754  }
5755 
5756  switch (alter_op)
5757  {
5758  case PT_APPLY_PARTITION:
5759  error = do_create_partition (parser, alter, pinfo);
5760  if (error != NO_ERROR)
5761  {
5762  return error;
5763  }
5764 
5765  error = do_get_partition_keycol (pinfo->keycol, pinfo->root_op);
5766  if (error != NO_ERROR)
5767  {
5768  return error;
5769  }
5770  /* fall through */
5771  case PT_ADD_HASHPARTITION:
5772  error = do_redistribute_partitions_data (entity_name, pinfo->keycol, NULL, 0, PT_ADD_HASHPARTITION, true, false);
5773  break;
5774  case PT_COALESCE_PARTITION:
5775  error = do_coalesce_partition_post (parser, alter, pinfo);
5776  break;
5777  case PT_REORG_PARTITION:
5778  error = do_reorganize_partition_post (parser, alter, pinfo);
5779  break;
5780  case PT_REMOVE_PARTITION:
5781  error = do_remove_partition_post (parser, alter, pinfo);
5782  break;
5783  case PT_ANALYZE_PARTITION:
5784  case PT_ADD_PARTITION:
5785  case PT_DROP_PARTITION:
5786  case PT_PROMOTE_PARTITION:
5787  /* nothing to do */
5788  break;
5789  default:
5790  error = NO_ERROR;
5791  break;
5792  }
5793 
5794  if (error != NO_ERROR)
5795  {
5796  return error;
5797  }
5798 
5799  /* if we created new partitions, we need to propagate indexes here */
5800  switch (alter_op)
5801  {
5802  case PT_APPLY_PARTITION:
5803  case PT_ADD_PARTITION:
5804  case PT_REORG_PARTITION:
5805  case PT_ADD_HASHPARTITION:
5806  error = do_create_partition_constraints (parser, alter, pinfo);
5807  break;
5808  default:
5809  break;
5810  }
5811  return error;
5812 }
5813 
5814 
5815 /*
5816  * do_remove_partition_pre () - perform schema actions for partition removing
5817  *
5818  * return : error code or NO_ERROR
5819  * parser (in) : parser context
5820  * alter (in) : the alter node
5821  * pinfo (in/out) : the partition context for the alter operation
5822  *
5823  * Note: The "pre" action for removing partitions from a class is to promote
5824  * all partitions to stand alone tables.
5825  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
5826  * to understand the nature of post/pre actions
5827  */
5828 static int
5830 {
5831  SM_CLASS *class_ = NULL, *subclass = NULL;
5832  DB_OBJLIST *obj = NULL, *obj_next = NULL;
5833  int error;
5834  char **names = NULL;
5835  int names_count = 0, allocated = 0, i = 0;
5836 
5837  /* sanity checks */
5838  assert (parser && alter && pinfo);
5839  CHECK_3ARGS_ERROR (parser, alter, pinfo);
5840  assert (alter->node_type == PT_ALTER);
5841 
5842  error = au_fetch_class (pinfo->root_op, &class_, AU_FETCH_READ, AU_SELECT);
5843  if (error != NO_ERROR)
5844  {
5845  return error;
5846  }
5847 
5848  if (class_->partition == NULL)
5849  {
5851  return ER_FAILED;
5852  }
5853 
5854  /* preallocate 10 elements for the names array */
5855  names = (char **) malloc (10 * sizeof (char *));
5856  if (names == NULL)
5857  {
5858  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, 10 * sizeof (char *));
5859  return ER_FAILED;
5860  }
5861  allocated = 10;
5862  names_count = 0;
5863 
5864  obj = class_->users;
5865  while (obj != NULL)
5866  {
5867  /* save next because obj will be modified by the promote call below */
5868  obj_next = obj->next;
5869  error = au_fetch_class (obj->op, &subclass, AU_FETCH_READ, AU_SELECT);
5870  if (error != NO_ERROR)
5871  {
5872  goto error_return;
5873  }
5874  if (subclass->partition == NULL)
5875  {
5876  /* not a partition */
5877  obj = obj_next;
5878  continue;
5879  }
5880 
5881  if (names_count >= allocated - 1)
5882  {
5883  /* If the names array is to small to accept a new element, reallocate it */
5884  char **buf = (char **) realloc (names, (allocated + 10) * sizeof (char *));
5885  if (buf == NULL)
5886  {
5888  ((allocated + 10) * sizeof (char *)));
5889  error = ER_FAILED;
5890  goto error_return;
5891  }
5892  names = buf;
5893  allocated += 10;
5894  }
5895  names[names_count] = strdup (sm_ch_name ((MOBJ) subclass));
5896  if (names[names_count] == NULL)
5897  {
5899  ((strlen (sm_ch_name ((MOBJ) subclass)) + 1) * sizeof (char)));
5900  error = ER_FAILED;
5901  goto error_return;
5902  }
5903  names_count++;
5904  error = do_promote_partition (subclass);
5905  if (error != NO_ERROR)
5906  {
5907  goto error_return;
5908  }
5909  obj = obj_next;
5910  }
5911 
5912  /* keep the promoted names in the partition alter context */
5913  pinfo->promoted_names = names;
5914  pinfo->promoted_count = names_count;
5916  pinfo->root_tmpl->partition = NULL;
5917 
5918  return NO_ERROR;
5919 
5920 error_return:
5921  if (names != NULL)
5922  {
5923  for (i = 0; i < names_count; i++)
5924  {
5925  free_and_init (names[i]);
5926  }
5927  free_and_init (names);
5928  }
5929  return error;
5930 }
5931 
5932 /*
5933  * do_remove_partition_post () - redistribute data from removed partitions
5934  * return : error code or NO_ERROR
5935  * parser (in) : parser context
5936  * alter (in) : the alter node
5937  * pinfo (in/out) : the partition context for the alter operation
5938  *
5939  * Note: The "post" action for removing partitions from a class is to
5940  * redistribute data from promoted partitions in pre action to the root
5941  * table and drop the promoted partitions
5942  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
5943  * to understand the nature of post/pre actions
5944  */
5945 static int
5947 {
5948  int error = NO_ERROR, i = 0;
5949  const char *root_name = NULL;
5950  MOP subclass_mop = NULL;
5951 
5952  /* sanity checks */
5953  assert (parser && alter && pinfo);
5954  CHECK_3ARGS_ERROR (parser, alter, pinfo);
5955 
5956  /* At this point, the root class of the partitioned table has been modified not to be partitioned anymore and the all
5957  * the promoted partition names are stored in pinfo->promoted_names. step 1: do an INSERT ... SELECT to move all data
5958  * from promoted classes into the root class step 2: drop promoted classes; */
5959  root_name = alter->info.alter.entity_name->info.name.original;
5960 
5961  error =
5962  do_redistribute_partitions_data (root_name, pinfo->keycol, pinfo->promoted_names, pinfo->promoted_count,
5963  alter->info.alter.code, false, true);
5964  if (error != NO_ERROR)
5965  {
5966  return error;
5967  }
5968  for (i = 0; i < pinfo->promoted_count; i++)
5969  {
5970  subclass_mop = sm_find_class (pinfo->promoted_names[i]);
5971  if (subclass_mop == NULL)
5972  {
5973  assert (er_errid () != NO_ERROR);
5974  error = er_errid ();
5975  return error;
5976  }
5977  error = sm_delete_class_mop (subclass_mop, false);
5978  if (error != NO_ERROR)
5979  {
5980  return error;
5981  }
5982  }
5983  return error;
5984 }
5985 
5986 /*
5987  * do_coalesce_partition_pre () - perform schema actions for partition
5988  * coalescing
5989  * return : error code or NO_ERROR
5990  * parser (in) : parser context
5991  * alter (in) : the alter node
5992  * pinfo (in/out) : the partition context for the alter operation
5993  *
5994  * Note: The "pre" action for coalescing partitions from a class is to
5995  * promote the number of partitions requested by the user to stand alone
5996  * tables. This request is only valid for HASH partitions. For this type
5997  * of partitioning, the name of the partition classes is given
5998  * automatically by CUBRID and we will promote the last created ones.
5999  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
6000  * to understand the nature of post/pre actions
6001  */
6002 static int
6004 {
6005  SM_CLASS *class_ = NULL, *subclass = NULL;
6006  MOP subclass_op = NULL;
6007  int error;
6008  char **names = NULL;
6009  int names_count = 0, i = 0;
6010  int coalesce_count = 0, partitions_count = 0;
6011  OID *partitions = NULL;
6012 
6013  /* sanity checks */
6014  assert (parser && alter && pinfo);
6015  assert (parser && alter && pinfo);
6016  assert (alter->node_type == PT_ALTER);
6017  CHECK_3ARGS_ERROR (parser, alter, pinfo);
6018 
6019  partitions_count = do_get_partition_size (pinfo->root_op);
6020  if (partitions_count < 0)
6021  {
6022  return ER_FAILED;
6023  }
6024  else if (partitions_count == 0)
6025  {
6026  /* cannot coalesce partitions of a class which is not partitioned */
6028  return ER_FAILED;
6029  }
6030 
6031  coalesce_count = alter->info.alter.alter_clause.partition.size->info.value.data_value.i;
6032  if (coalesce_count >= partitions_count)
6033  {
6034  /* cannot coalesce partitions of a class which is not partitioned */
6036  return ER_FAILED;
6037  }
6038 
6039  error = au_fetch_class (pinfo->root_op, &class_, AU_FETCH_READ, AU_SELECT);
6040  if (error != NO_ERROR)
6041  {
6042  return error;
6043  }
6044 
6045  if (class_->partition == NULL)
6046  {
6048  return ER_FAILED;
6049  }
6050 
6051  /* Promote the last (partition_count - coalesce_count) partitions */
6052  names = (char **) malloc (coalesce_count * sizeof (char *));
6053  if (names == NULL)
6054  {
6055  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, coalesce_count * sizeof (char *));
6056  return ER_FAILED;
6057  }
6058 
6059  partitions = (OID *) malloc (partitions_count * sizeof (OID));
6060  if (partitions == NULL)
6061  {
6062  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, partitions_count * sizeof (OID));
6063  error = ER_OUT_OF_VIRTUAL_MEMORY;
6064  goto error_return;
6065  }
6066  for (i = partitions_count - 1, names_count = 0; i >= partitions_count - coalesce_count; i--)
6067  {
6068  names[names_count] = (char *) malloc (DB_MAX_IDENTIFIER_LENGTH + 1);
6069  if (names[names_count] == NULL)
6070  {
6072  (size_t) (DB_MAX_IDENTIFIER_LENGTH + 1));
6073  error = ER_FAILED;
6074  goto error_return;
6075  }
6076  sprintf (names[names_count], "%s" PARTITIONED_SUB_CLASS_TAG "p%d", sm_ch_name ((MOBJ) class_), i);
6077  subclass_op = sm_find_class (names[names_count]);
6078  if (subclass_op == NULL)
6079  {
6080  assert (er_errid () != NO_ERROR);
6081  error = er_errid ();
6082  goto error_return;
6083  }
6084  error = au_fetch_class (subclass_op, &subclass, AU_FETCH_READ, AU_SELECT);
6085  if (error != NO_ERROR)
6086  {
6087  goto error_return;
6088  }
6089 
6090  COPY_OID (&partitions[names_count], &subclass_op->oid_info.oid);
6091  names_count++;
6092 
6093  error = do_promote_partition (subclass);
6094  if (error != NO_ERROR)
6095  {
6096  goto error_return;
6097  }
6098  }
6099 
6100  error = adjust_partition_size (pinfo->root_op, pinfo->root_tmpl);
6101  if (error != NO_ERROR)
6102  {
6103  goto error_return;
6104  }
6105 
6106  /* keep the promoted names in the partition alter context */
6107  pinfo->promoted_names = names;
6108  pinfo->promoted_count = names_count;
6109 
6110  if (partitions != NULL)
6111  {
6112  free_and_init (partitions);
6113  }
6114 
6115  return NO_ERROR;
6116 
6117 error_return:
6118  if (names != NULL)
6119  {
6120  for (i = 0; i < names_count; i++)
6121  {
6122  free_and_init (names[i]);
6123  }
6124  free_and_init (names);
6125  }
6126  if (partitions != NULL)
6127  {
6128  free_and_init (partitions);
6129  }
6130  return error;
6131 }
6132 
6133 /*
6134  * do_coalesce_partition_post () - redistribute data from removed partitions
6135  * return : error code or NO_ERROR
6136  * parser (in) : parser context
6137  * alter (in) : the alter node
6138  * pinfo (in/out) : the partition context for the alter operation
6139  *
6140  * Note: The "post" action for coalescing partitions from a class is to
6141  * redistribute data from partitions promoted in pre action to the root
6142  * table and drop the promoted partitions
6143  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
6144  * to understand the nature of post/pre actions
6145  */
6146 static int
6148 {
6149  int error = NO_ERROR, i = 0;
6150  const char *root_name = NULL;
6151  MOP subclass_mop = NULL;
6152  OID *partitions = NULL;
6153  SM_CLASS *smclass = NULL;
6154  MOP class_ = NULL;
6155 
6156  /* sanity checks */
6157  assert (parser && alter && pinfo);
6158  CHECK_3ARGS_ERROR (parser, alter, pinfo);
6159 
6160  /* At this point, the root class of the partitioned table has been modified and contains only the final partitions.
6161  * The promoted partition names are stored in pinfo->promoted_names. step 1: redistribute data step 2: drop promoted
6162  * classes; */
6163  root_name = alter->info.alter.entity_name->info.name.original;
6164 
6165  class_ = sm_find_class (root_name);
6166  if (class_ == NULL)
6167  {
6168  assert (er_errid () != NO_ERROR);
6169  error = er_errid ();
6170  goto exit;
6171  }
6172 
6173  error = au_fetch_class (class_, &smclass, AU_FETCH_READ, AU_SELECT);
6174  if (error != NO_ERROR)
6175  {
6176  goto exit;
6177  }
6178 
6179  error =
6180  do_redistribute_partitions_data (root_name, pinfo->keycol, pinfo->promoted_names, pinfo->promoted_count,
6181  alter->info.alter.code, true, true);
6182  if (error != NO_ERROR)
6183  {
6184  goto exit;
6185  }
6186 
6187  if (pinfo->promoted_count < 1)
6188  {
6190  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6191  goto exit;
6192  }
6193 
6194  partitions = (OID *) malloc (pinfo->promoted_count * sizeof (OID));
6195  if (partitions == NULL)
6196  {
6198  error = ER_OUT_OF_VIRTUAL_MEMORY;
6199  goto exit;
6200  }
6201 
6202  for (i = 0; i < pinfo->promoted_count; i++)
6203  {
6204  subclass_mop = sm_find_class (pinfo->promoted_names[i]);
6205  if (subclass_mop == NULL)
6206  {
6207  assert (er_errid () != NO_ERROR);
6208  error = er_errid ();
6209  goto exit;
6210  }
6211  COPY_OID (&partitions[i], &subclass_mop->oid_info.oid);
6212  }
6213 
6214  for (i = 0; i < pinfo->promoted_count; i++)
6215  {
6216  subclass_mop = sm_find_class (pinfo->promoted_names[i]);
6217  if (subclass_mop == NULL)
6218  {
6219  assert (er_errid () != NO_ERROR);
6220  error = er_errid ();
6221  goto exit;
6222  }
6223  error = sm_delete_class_mop (subclass_mop, false);
6224  if (error != NO_ERROR)
6225  {
6226  goto exit;
6227  }
6228  }
6229 
6230 exit:
6231  if (partitions != NULL)
6232  {
6233  free_and_init (partitions);
6234  }
6235  return error;
6236 }
6237 
6238 /*
6239  * do_reorganize_partition_pre () - perform schema actions for partition
6240  * reorganizing
6241  * return : error code or NO_ERROR
6242  * parser (in) : parser context
6243  * alter (in) : the alter node
6244  * pinfo (in/out) : the partition context for the alter operation
6245  *
6246  * Note: The "pre" action for reorganizing partitions from a class is to
6247  * promote the partitions that will be reorganized to alone tables and
6248  * to create the new partitions.
6249  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
6250  * to understand the nature of post/pre actions
6251  */
6252 static int
6254 {
6255  PT_NODE *old_part = NULL, *new_part = NULL;
6256  int error = NO_ERROR;
6257  char **names = NULL;
6258  int names_count = 0, allocated = 0, i;
6259  const char *old_name = NULL, *new_name = NULL, *class_name = NULL;
6260  bool found = false;
6261 
6262  /* sanity checks */
6263  assert (parser && alter && pinfo);
6264  assert (alter->node_type == PT_ALTER);
6265  CHECK_3ARGS_ERROR (parser, alter, pinfo);
6266 
6267  class_name = alter->info.alter.entity_name->info.name.original;
6268  old_part = alter->info.alter.alter_clause.partition.name_list;
6269  new_part = alter->info.alter.alter_clause.partition.parts;
6270 
6271  /* Reorganize partitions might mean that we're dropping some of the curent partitions and changing some others to
6272  * contain a new range/list We only want to promote partitions which will be deleted, not the ones which will be
6273  * changed. */
6274  while (old_part != NULL)
6275  {
6276  /* search old_part through new_part */
6277  found = false;
6278  old_name = old_part->info.name.original;
6279  while (new_part != NULL)
6280  {
6281  new_name = new_part->info.parts.name->info.name.original;
6282  if (intl_identifier_casecmp (old_name, new_name) == 0)
6283  {
6284  found = true;
6285  break;
6286  }
6287  new_part = new_part->next;
6288  }
6289  new_part = alter->info.alter.alter_clause.partition.parts;
6290  if (!found)
6291  {
6292  /* we will drop this partition so we have to promote it first */
6293  if (names == NULL)
6294  {
6295  /* allocate */
6296  names = (char **) malloc (10 * sizeof (char *));
6297  if (names == NULL)
6298  {
6299  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, 10 * sizeof (char *));
6300  error = ER_FAILED;
6301  goto error_return;
6302  }
6303  allocated = 10;
6304  }
6305  else if (names_count >= allocated - 1)
6306  {
6307  /* need to reallocate */
6308  char **new_buf = (char **) realloc (names, 10 * sizeof (char *));
6309  if (new_buf == NULL)
6310  {
6311  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, 10 * sizeof (char *));
6312  error = ER_FAILED;
6313  goto error_return;
6314  }
6315  names = new_buf;
6316  allocated += 10;
6317  }
6318  error = do_promote_partition_by_name (class_name, old_name, &names[names_count]);
6319  if (error != NO_ERROR)
6320  {
6321  goto error_return;
6322  }
6323  names_count++;
6324  }
6325 
6326  old_part = old_part->next;
6327  }
6328 
6329  /* create new partitions */
6330  error = do_create_partition (parser, alter, pinfo);
6331  if (error != NO_ERROR)
6332  {
6333  goto error_return;
6334  }
6335 
6336  pinfo->promoted_names = names;
6337  pinfo->promoted_count = names_count;
6338  return NO_ERROR;
6339 
6340 error_return:
6341  if (names != NULL)
6342  {
6343  for (i = 0; i < names_count; i++)
6344  {
6345  free_and_init (names[i]);
6346  }
6347  free_and_init (names);
6348  }
6349  return error;
6350 }
6351 
6352 /*
6353  * do_reorganize_partition_post () - redistribute data from removed partitions
6354  * return : error code or NO_ERROR
6355  * parser (in) : parser context
6356  * alter (in) : the alter node
6357  * pinfo (in/out) : the partition context for the alter operation
6358  *
6359  * Note: The "post" action for reorganizing partitions from a class is to
6360  * redistribute data from promoted partitions in pre action to the new
6361  * partitions and drop the promoted ones.
6362  * See notes for do_alter_partitioning_pre, do_alter_partitioning_post
6363  * to understand the nature of post/pre actions
6364  */
6365 static int
6367 {
6368  int error = NO_ERROR, i = 0;
6369  const char *root_name = NULL;
6370  MOP subclass_mop = NULL;
6371  PT_NODE *name = NULL;
6372  bool insert = false, update = false;
6373 
6374  /* sanity checks */
6375  assert (parser && alter && pinfo);
6376  CHECK_3ARGS_ERROR (parser, alter, pinfo);
6377 
6378  /* At this point, the root class of the partitioned table has been modified to the new partitioning schema. We might
6379  * have promoted some partitions and also changed other partitions to a new range or list. We have to run an INSERT
6380  * ... SELECT for the promoted partitions and an UPDATE for the ones that we only changed the schema (in order to
6381  * redistribute the data) */
6382  root_name = alter->info.alter.entity_name->info.name.original;
6383 
6384  if (pinfo->promoted_names != NULL)
6385  {
6386  /* we have at least one promoted partition */
6387  insert = true;
6388  }
6389 
6390  name = alter->info.alter.alter_clause.partition.parts;
6391  while (name)
6392  {
6393  if (name->flag.partition_pruned != 0)
6394  {
6395  /* at least one partitions has been changed */
6396  update = true;
6397  break;
6398  }
6399  name = name->next;
6400  }
6401 
6402  error =
6403  do_redistribute_partitions_data (root_name, pinfo->keycol, pinfo->promoted_names, pinfo->promoted_count,
6404  alter->info.alter.code, update, insert);
6405  if (error != NO_ERROR)
6406  {
6407  return error;
6408  }
6409 
6410  for (i = 0; i < pinfo->promoted_count; i++)
6411  {
6412  subclass_mop = sm_find_class (pinfo->promoted_names[i]);
6413  if (subclass_mop == NULL)
6414  {
6415  assert (er_errid () != NO_ERROR);
6416  error = er_errid ();
6417  return error;
6418  }
6419  error = sm_delete_class_mop (subclass_mop, false);
6420  if (error != NO_ERROR)
6421  {
6422  return error;
6423  }
6424  }
6425 
6426  return NO_ERROR;
6427 }
6428 
6429 #if defined (ENABLE_UNUSED_FUNCTION)
6430 /*
6431  * do_analyze_partition () - update statistics on partitions
6432  * return : error code or NO_ERROR
6433  * parser (in) : parser context
6434  * alter (in) : alter node
6435  */
6436 static int
6437 do_analyze_partition (PARSER_CONTEXT * parser, PT_NODE * alter, SM_PARTITION_ALTER_INFO * pinfo)
6438 {
6439  PT_NODE *name = NULL;
6440  int error = NO_ERROR;
6441 
6442  /* sanity check */
6443  assert (parser != NULL && alter != NULL);
6444  CHECK_2ARGS_ERROR (parser, alter);
6445 
6446  name = alter->info.alter.alter_clause.partition.name_list;
6447  if (name != NULL)
6448  {
6449  /* update statistics for given names */
6450  while (name)
6451  {
6452  assert (name->info.name.db_object != NULL);
6454  if (error != NO_ERROR)
6455  {
6456  return error;
6457  }
6458  name = name->next;
6459  }
6460  }
6461  else
6462  {
6463  /* update statistics on all partitions */
6464  SM_CLASS *class_ = NULL, *subclass = NULL;
6465  DB_OBJLIST *obj = NULL;
6466  error = au_fetch_class (pinfo->root_op, &class_, AU_FETCH_READ, AU_SELECT);
6467  if (error != NO_ERROR)
6468  {
6469  return error;
6470  }
6472  if (error != NO_ERROR)
6473  {
6474  return error;
6475  }
6476 
6477  for (obj = class_->users; obj != NULL; obj = obj->next)
6478  {
6479  error = au_fetch_class (obj->op, &subclass, AU_FETCH_READ, AU_SELECT);
6480  if (error != NO_ERROR)
6481  {
6482  return error;
6483  }
6484 
6485  if (subclass->partition == NULL)
6486  {
6487  /* not partitioned */
6488  continue;
6489  }
6490 
6492  if (error != NO_ERROR)
6493  {
6494  return error;
6495  }
6496  }
6497  }
6498 
6499  return error;
6500 }
6501 #endif
6502 
6503 /*
6504  * do_promote_partition_list () -
6505  * return: error code or NO_ERROR
6506  * class_(in) : root class mop
6507  * name_list(in): partition names
6508  *
6509  * Note: Currently, only the "local" indexes are promoted. After this
6510  * operation, global indexes (like unique indexes and primary keys)
6511  * will not be automatically created on the promoted table
6512  */
6513 static int
6515 {
6516  int error = NO_ERROR;
6517  char subclass_name[DB_MAX_IDENTIFIER_LENGTH];
6518  SM_CLASS *smclass = NULL, *smsubclass = NULL;
6519  MOP subclass = NULL;
6520  PT_NODE *name = NULL;
6521  PT_NODE *name_list = NULL;
6522  DB_OBJLIST *obj = NULL;
6523  int promoted_count = 0, partitions_count = 0;
6524  OID *partitions = NULL;
6525 
6526  /* sanity check */
6527  assert (parser != NULL && alter != NULL && pinfo != NULL);
6528  CHECK_3ARGS_ERROR (parser, alter, pinfo);
6529 
6530  name_list = alter->info.alter.alter_clause.partition.name_list;
6531  if (name_list == NULL)
6532  {
6533  /* nothing to do */
6534  return NO_ERROR;
6535  }
6536 
6537  if (pinfo->root_op == NULL)
6538  {
6539  assert (false);
6540  return ER_FAILED;
6541  }
6542 
6543  error = au_fetch_class (pinfo->root_op, &smclass, AU_FETCH_READ, AU_SELECT);
6544  if (error != NO_ERROR)
6545  {
6546  return error;
6547  }
6548 
6549  if (!smclass->partition)
6550  {
6552  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
6553  return error;
6554  }
6555 
6556  /* count the total number of partitions */
6557  partitions_count = 0;
6558  for (obj = smclass->users; obj != NULL; obj = obj->next)
6559  {
6560  error = au_fetch_class (obj->op, &smsubclass, AU_FETCH_READ, AU_SELECT);
6561  if (error != NO_ERROR)
6562  {
6563  return error;
6564  }
6565  if (!smsubclass->partition)
6566  {
6567  continue;
6568  }
6569  partitions_count++;
6570  }
6571 
6572  partitions = (OID *) malloc (partitions_count * sizeof (OID));
6573  if (partitions == NULL)
6574  {
6575  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, partitions_count * sizeof (OID));
6576  return ER_OUT_OF_VIRTUAL_MEMORY;
6577  }
6578 
6579  promoted_count = 0;
6580  for (name = name_list; name != NULL; name = name->next)
6581  {
6582  sprintf (subclass_name, "%s" PARTITIONED_SUB_CLASS_TAG "%s", sm_ch_name ((MOBJ) smclass),
6583  name->info.name.original);
6584 
6585  /* Before promoting, make sure to recreate filter and function indexes because the expression used in these
6586  * indexes depends on the partitioned class name, not on the partition name */
6587  error = do_recreate_renamed_class_indexes (parser, sm_ch_name ((MOBJ) smclass), subclass_name);
6588  if (error != NO_ERROR)
6589  {
6590  goto exit;
6591  }
6592 
6593  subclass = sm_find_class (subclass_name);
6594  if (subclass == NULL)
6595  {
6596  assert (er_errid () != NO_ERROR);
6597  error = er_errid ();
6598  goto exit;
6599  }
6600  error = au_fetch_class (subclass, &smsubclass, AU_FETCH_READ, AU_SELECT);
6601  if (error != NO_ERROR)
6602  {
6603  goto exit;
6604  }
6605 
6606  error = do_promote_partition (smsubclass);
6607  if (error != NO_ERROR)
6608  {
6609  goto exit;
6610  }
6611  COPY_OID (&partitions[promoted_count], &subclass->oid_info.oid);
6612  promoted_count++;
6613  }
6614  assert (partitions_count >= promoted_count);
6615 
6616  if (partitions_count - promoted_count == 0)
6617  {
6618  /* All partitions were promoted so mark this class as not being partitioned. Through the pinfo object, we have
6619  * access to the root class template on which an edit operation was started. We can use it to perform the update. */
6620  assert (pinfo->root_tmpl != NULL);
6622  pinfo->root_tmpl->partition = NULL;
6623  }
6624  else
6625  {
6626  /* smclass might not be valid here, we need to re fetch it */
6627  error = au_fetch_class (pinfo->root_op, &smclass, AU_FETCH_READ, AU_SELECT);
6628  if (error != NO_ERROR)
6629  {
6630  goto exit;
6631  }
6632 
6633  error = adjust_partition_range (smclass->users);
6634  if (error != NO_ERROR)
6635  {
6636  goto exit;
6637  }
6638 
6639  error = adjust_partition_size (pinfo->root_op, pinfo->root_tmpl);
6640  if (error != NO_ERROR)
6641  {
6642  goto exit;
6643  }
6644  }
6645 
6646 exit:
6647  if (partitions != NULL)
6648  {
6649  free_and_init (partitions);
6650  }
6651 
6652  return error;
6653 }
6654 
6655 /*
6656  * do_promote_partition_by_name () - promote a partition
6657  * return : error code or NO_ERROR
6658  * class_name (in) : root class name
6659  * part_num (in) : partition number/indicator
6660  * partition_name (in/out) : full partition name
6661  */
6662 static int
6663 do_promote_partition_by_name (const char *class_name, const char *part_num, char **partition_name)
6664 {
6665  int error = NO_ERROR;
6666  MOP subclass = NULL;
6667  SM_CLASS *smsmclass = NULL;
6668  char name[DB_MAX_IDENTIFIER_LENGTH];
6669 
6670  assert (class_name != NULL && part_num != NULL);
6671  CHECK_2ARGS_ERROR (class_name, part_num);
6672  sprintf (name, "%s" PARTITIONED_SUB_CLASS_TAG "%s", class_name, part_num);
6673  subclass = sm_find_class (name);
6674  if (subclass == NULL)
6675  {
6676  assert (er_errid () != NO_ERROR);
6677  return er_errid ();
6678  }
6679  error = au_fetch_class (subclass, &smsmclass, AU_FETCH_READ, AU_SELECT);
6680  if (error != NO_ERROR)
6681  {
6682  return error;
6683  }
6684  error = do_promote_partition (smsmclass);
6685  if (error != NO_ERROR)
6686  {
6687  return error;
6688  }
6689 
6690  if (partition_name != NULL)
6691  {
6692  *partition_name = strdup (name);
6693  if (*partition_name == NULL)
6694  {
6695  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (strlen (name) + 1) * sizeof (char));
6696  return ER_FAILED;
6697  }
6698  }
6699 
6700  return NO_ERROR;
6701 }
6702 
6703 /*
6704  * do_promote_partition () - promote a partition
6705  * return : error code or NO_ERROR
6706  * class_ (in) : class to promote
6707  */
6708 static int
6710 {
6711  MOP subclass_mop = NULL;
6712  int error = NO_ERROR;
6713  SM_CLASS *current = NULL;
6714  DB_CTMPL *ctemplate = NULL;
6715  SM_ATTRIBUTE *smattr = NULL;
6716  bool has_pk = false;
6717 
6718  CHECK_1ARG_ERROR (class_);
6719 
6720  if (class_->partition == NULL)
6721  {
6723  return ER_PARTITION_NOT_EXIST;
6724  }
6725 
6726  subclass_mop = sm_find_class (sm_ch_name ((MOBJ) class_));
6727  if (subclass_mop == NULL)
6728  {
6729  assert (er_errid () != NO_ERROR);
6730  return er_errid ();
6731  }
6732 
6733  ctemplate = dbt_edit_class (subclass_mop);
6734  if (ctemplate == NULL)
6735  {
6736  return ER_FAILED;
6737  }
6738 
6739  current = ctemplate->current;
6740  assert (current != NULL);
6741 
6742  /* Copy attributes in the order in which they were defined in order to preserve the order from the root class */
6743  error = classobj_copy_attlist (current->ordered_attributes, NULL, 1, &ctemplate->attributes);
6744  if (error != NO_ERROR)
6745  {
6746  dbt_abort_class (ctemplate);
6747  return error;
6748  }
6749  for (smattr = ctemplate->attributes; smattr != NULL; smattr = (SM_ATTRIBUTE *) smattr->header.next)
6750  {
6751  /* make attributes point to the subclass, not the parent */
6752  smattr->class_mop = subclass_mop;
6753  }
6754 
6755  error = classobj_copy_attlist (current->class_attributes, NULL, 0, &ctemplate->class_attributes);
6756  if (error != NO_ERROR)
6757  {
6758  dbt_abort_class (ctemplate);
6759  return error;
6760  }
6761  for (smattr = ctemplate->class_attributes; smattr != NULL; smattr = (SM_ATTRIBUTE *) smattr->header.next)
6762  {
6763  /* make attributes point to the subclass, not the parent */
6764  smattr->class_mop = subclass_mop;
6765  }
6766 
6767  /* Make sure we do not copy anything that actually belongs to the root class (the class to which this partition
6768  * belongs to). This includes: auto_increment flags, unique indexes, primary keys, and foreign keys */
6769  for (smattr = ctemplate->attributes; smattr != NULL; smattr = (SM_ATTRIBUTE *) smattr->header.next)
6770  {
6771  /* reset flags that belong to the root partitioned table */
6772  smattr->auto_increment = NULL;
6773  smattr->flags &= ~(SM_ATTFLAG_AUTO_INCREMENT);
6774  if ((smattr->flags & SM_ATTFLAG_PRIMARY_KEY) != 0)
6775  {
6776  smattr->flags &= ~(SM_ATTFLAG_PRIMARY_KEY);
6777  smattr->flags &= ~(SM_ATTFLAG_NON_NULL);
6778  has_pk = true;
6779  }
6780  smattr->flags &= ~(SM_ATTFLAG_UNIQUE);
6781  smattr->flags &= ~(SM_ATTFLAG_REVERSE_UNIQUE);
6782  smattr->flags &= ~(SM_ATTFLAG_FOREIGN_KEY);
6783  smattr->flags &= ~(SM_ATTFLAG_PARTITION_KEY);
6784  }
6785 
6786  ctemplate->inheritance = NULL;
6787  ctemplate->methods = NULL;
6788  ctemplate->resolutions = NULL;
6789  ctemplate->class_methods = NULL;
6790  ctemplate->class_resolutions = NULL;
6791  ctemplate->method_files = NULL;
6792  ctemplate->loader_commands = NULL;
6793  ctemplate->query_spec = NULL;
6794  ctemplate->instance_attributes = NULL;
6795  ctemplate->shared_attributes = NULL;
6796  ctemplate->partition_parent_atts = NULL;
6797  ctemplate->triggers = NULL;
6799  ctemplate->partition = NULL;
6800 
6801  if (ctemplate->properties != NULL)
6802  {
6803  if (has_pk)
6804  {
6807  }
6811  }
6812 
6813  if (dbt_finish_class (ctemplate) == NULL)
6814  {
6815  dbt_abort_class (ctemplate);
6816  assert (er_errid () != NO_ERROR);
6817  error = er_errid ();
6818  if (error == NO_ERROR)
6819  {
6820  error = ER_FAILED;
6821  }
6822  return error;
6823  }
6824 
6825  return error;
6826 }
6827 
6828 /*
6829  * validate_attribute_domain() - This checks an attribute to make sure
6830  * that it makes sense
6831  * return: Error code
6832  * parser(in): Parser context
6833  * attribute(in): Parse tree of an attribute or method
6834  * check_zero_precision(in): Do not permit zero precision if true
6835  *
6836  * Note: Error reporting system
6837  */
6838 static int
6839 validate_attribute_domain (PARSER_CONTEXT * parser, PT_NODE * attribute, const bool check_zero_precision)
6840 {
6841  int error = NO_ERROR;
6842 
6843  if (attribute == NULL)
6844  {
6845  pt_record_error (parser, parser->statement_number, __LINE__, 0, "system error - NULL attribute node", NULL);
6846  }
6847  else
6848  {
6849  if (attribute->type_enum == PT_TYPE_NONE)
6850  {
6851  pt_record_error (parser, parser->statement_number, attribute->line_number, attribute->column_number,
6852  "system error - attribute type not set", NULL);
6853  }
6854  else
6855  {
6856  PT_NODE *dtyp = attribute->data_type;
6857 
6858  if (dtyp)
6859  {
6860  int p = attribute->data_type->info.data_type.precision;
6861 
6862  switch (attribute->type_enum)
6863  {
6864  case PT_TYPE_FLOAT:
6865  case PT_TYPE_DOUBLE:
6866  if (p != DB_DEFAULT_PRECISION && (p < 0 || p > DB_MAX_NUMERIC_PRECISION))
6867  {
6869  DB_MAX_NUMERIC_PRECISION);
6870  }
6871  break;
6872 
6873  case PT_TYPE_NUMERIC:
6874  if (p != DB_DEFAULT_PRECISION
6875  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_NUMERIC_PRECISION))
6876  {
6878  DB_MAX_NUMERIC_PRECISION);
6879  }
6880  break;
6881 
6882  case PT_TYPE_BIT:
6883  if (p != DB_DEFAULT_PRECISION
6884  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_BIT_PRECISION))
6885  {
6888  }
6889  break;
6890 
6891  case PT_TYPE_VARBIT:
6892  if (p != DB_DEFAULT_PRECISION
6893  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_VARBIT_PRECISION))
6894  {
6897  }
6898  break;
6899 
6900  case PT_TYPE_CHAR:
6901  if (p != DB_DEFAULT_PRECISION
6902  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_CHAR_PRECISION))
6903  {
6906  }
6907  break;
6908 
6909  case PT_TYPE_NCHAR:
6910  if (p != DB_DEFAULT_PRECISION
6911  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_NCHAR_PRECISION))
6912  {
6915  }
6916  break;
6917 
6918  case PT_TYPE_VARCHAR:
6919  if (p != DB_DEFAULT_PRECISION
6920  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_VARCHAR_PRECISION))
6921  {
6924  }
6925  break;
6926 
6927  case PT_TYPE_VARNCHAR:
6928  if (p != DB_DEFAULT_PRECISION
6929  && (p < 0 || (p == 0 && check_zero_precision) || p > DB_MAX_VARNCHAR_PRECISION))
6930  {
6933  }
6934  break;
6935 
6936  case PT_TYPE_SET:
6937  case PT_TYPE_MULTISET:
6938  case PT_TYPE_SEQUENCE:
6939  {
6940  PT_NODE *elem;
6941  for (elem = dtyp; elem != NULL; elem = elem->next)
6942  {
6943  if (PT_IS_LOB_TYPE (elem->type_enum))
6944  {
6945  PT_ERRORmf2 (parser, attribute, MSGCAT_SET_PARSER_SEMANTIC,
6947  pt_show_type_enum (elem->type_enum));
6948  break;
6949  }
6950  }
6951  }
6952  break;
6953 
6954  case PT_TYPE_ENUMERATION:
6955  (void) pt_check_enum_data_type (parser, dtyp);
6956  break;
6957 
6958  default:
6959  break;
6960  }
6961  }
6962  }
6963  }
6964 
6965  if (error == NO_ERROR)
6966  {
6967  if (pt_has_error (parser))
6968  {
6969  error = ER_PT_SEMANTIC;
6970  }
6971  }
6972 
6973  return error;
6974 
6975 }
6976 
6977 static const char *
6978 get_attr_name (PT_NODE * attribute)
6979 {
6980  /* First try the derived name and then the original name. For example: create view a_view as select a av1, a av2, b
6981  * bv from a_tbl; */
6982  return (attribute->info.attr_def.attr_name->alias_print
6983  ? attribute->info.attr_def.attr_name->alias_print : attribute->info.attr_def.attr_name->info.name.original);
6984 }
6985 
6986 /*
6987  * do_add_attribute() - Adds an attribute to a class object
6988  * return: Error code
6989  * parser(in): Parser context
6990  * ctemplate(in/out): Class template
6991  * attribute(in/out): Attribute to add
6992  * constraints(in/out): the constraints of the class
6993  * error_on_not_normal(in): whether to flag an error on class and shared attributes or not
6994  *
6995  * Note : The class object is modified
6996  */
6997 static int
6998 do_add_attribute (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attribute, PT_NODE * constraints,
6999  bool error_on_not_normal)
7000 {
7001  const char *attr_name = NULL;
7002  int meta, shared;
7003  DB_VALUE stack_value;
7004  DB_VALUE *default_value = &stack_value;
7005  DB_DEFAULT_EXPR_TYPE on_update_expr = DB_DEFAULT_NONE;
7006  int error = NO_ERROR;
7007  TP_DOMAIN *attr_db_domain;
7008  MOP auto_increment_obj = NULL;
7009  SM_ATTRIBUTE *att = NULL;
7011  bool add_first = false;
7012  const char *add_after_attr = NULL;
7013  PT_NODE *cnstr, *pk_attr, *comment;
7014  DB_DEFAULT_EXPR default_expr;
7015  PARSER_VARCHAR *comment_str = NULL;
7016 
7017  db_make_null (&stack_value);
7018  attr_name = get_attr_name (attribute);
7019 
7020  meta = (attribute->info.attr_def.attr_type == PT_META_ATTR);
7021  shared = (attribute->info.attr_def.attr_type == PT_SHARED);
7022 
7023  if (error_on_not_normal && attribute->info.attr_def.attr_type != PT_NORMAL)
7024  {
7025  ERROR1 (error, ER_SM_ONLY_NORMAL_ATTRIBUTES, attr_name);
7026  goto error_exit;
7027  }
7028 
7029  /* set default codeset and collation for attribute if none is specified */
7030  if (ctemplate->current != NULL && attribute->node_type == PT_ATTR_DEF && PT_HAS_COLLATION (attribute->type_enum))
7031  {
7032  pt_attr_check_default_cs_coll (parser, attribute, -1, ctemplate->current->collation_id);
7033  }
7034 
7035  if (validate_attribute_domain (parser, attribute, smt_get_class_type (ctemplate) == SM_CLASS_CT ? true : false))
7036  {
7037  /* validate_attribute_domain() is assumed to issue whatever messages are pertinent. */
7038  error = ER_GENERIC_ERROR;
7039  goto error_exit;
7040  }
7041 
7042  assert (default_value == &stack_value);
7043  error = get_att_default_from_def (parser, attribute, &default_value, ctemplate->name);
7044  if (error != NO_ERROR)
7045  {
7046  goto error_exit;
7047  }
7048 
7049  if (default_value && DB_IS_NULL (default_value))
7050  {
7051  /* don't allow a default value of NULL for NOT NULL constrained columns */
7052  if (attribute->info.attr_def.constrain_not_null)
7053  {
7056  goto error_exit;
7057  }
7058 
7059  /* don't allow a default value of NULL in new PK constraint */
7060  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
7061  {
7063  {
7064  break;
7065  }
7066  }
7067  if (cnstr != NULL)
7068  {
7069  for (pk_attr = cnstr->info.constraint.un.primary_key.attrs; pk_attr != NULL; pk_attr = pk_attr->next)
7070  {
7071  if (intl_identifier_casecmp (pk_attr->info.name.original, attr_name) == 0)
7072  {
7075  goto error_exit;
7076  }
7077  }
7078  }
7079  }
7080 
7081  attr_db_domain = pt_node_to_db_domain (parser, attribute, ctemplate->name);
7082  if (attr_db_domain == NULL)
7083  {
7084  assert (er_errid () != NO_ERROR);
7085  error = er_errid ();
7086  goto error_exit;
7087  }
7088 
7089  error = check_default_on_update_clause (parser, attribute);
7090  if (error != NO_ERROR)
7091  {
7092  goto error_exit;
7093  }
7094 
7095  error = get_att_order_from_def (attribute, &add_first, &add_after_attr);
7096  if (error != NO_ERROR)
7097  {
7098  goto error_exit;
7099  }
7100 
7101  if (meta)
7102  {
7103  name_space = ID_CLASS_ATTRIBUTE;
7104  }
7105  else if (shared)
7106  {
7107  name_space = ID_SHARED_ATTRIBUTE;
7108  }
7109  else
7110  {
7111  name_space = ID_ATTRIBUTE;
7112  }
7113 
7114  on_update_expr = attribute->info.attr_def.on_update;
7115  pt_get_default_expression_from_data_default_node (parser, attribute->info.attr_def.data_default, &default_expr);
7116  default_value = &stack_value;
7117 
7118  error = smt_add_attribute_w_dflt_w_order (ctemplate, attr_name, NULL, attr_db_domain, default_value, name_space,
7119  add_first, add_after_attr, &default_expr, &on_update_expr, NULL);
7120 
7121  db_value_clear (&stack_value);
7122 
7123  /* Does the attribute belong to a NON_NULL constraint? */
7124  if (error == NO_ERROR)
7125  {
7126  if (attribute->info.attr_def.constrain_not_null)
7127  {
7128  error = dbt_constrain_non_null (ctemplate, attr_name, meta, 1);
7129  }
7130  }
7131 
7132  /* create & set auto_increment attribute's serial object */
7133  if (error == NO_ERROR && !meta && !shared)
7134  {
7135  if (attribute->info.attr_def.auto_increment)
7136  {
7137  error = do_create_auto_increment_serial (parser, &auto_increment_obj, ctemplate->name, attribute);
7138 
7139  if (error == NO_ERROR)
7140  {
7141  if (smt_find_attribute (ctemplate, attr_name, 0, &att) == NO_ERROR)
7142  {
7143  att->auto_increment = auto_increment_obj;
7145  }
7146  }
7147  }
7148  }
7149 
7150  comment = attribute->info.attr_def.comment;
7151  if (error == NO_ERROR && comment != NULL)
7152  {
7153  /* skip finding attribute if att is already available */
7154  if (att == NULL)
7155  {
7156  error = smt_find_attribute (ctemplate, attr_name, 0, &att);
7157  }
7158 
7159  if (error == NO_ERROR)
7160  {
7161  assert (comment->node_type == PT_VALUE);
7162  comment_str = comment->info.value.data_value.str;
7163  att->comment = ws_copy_string ((char *) pt_get_varchar_bytes (comment_str));
7164  if (att->comment == NULL)
7165  {
7166  error = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
7167  goto error_exit;
7168  }
7169  }
7170  }
7171 
7172  return error;
7173 
7174 error_exit:
7175  db_value_clear (&stack_value);
7176  return error;
7177 }
7178 
7179 /*
7180  * do_add_attribute_from_select_column() - Adds an attribute to a class object
7181  * return: Error code
7182  * ctemplate(in/out): Class template
7183  * column(in): Attribute to add, as specified by a SELECT column in a
7184  * CREATE ... AS SELECT statement. The original SELECT column's
7185  * NOT NULL and default value need to be copied.
7186  *
7187  * Note : The class object is modified
7188  */
7189 static int
7191 {
7193  int error = NO_ERROR;
7194  const char *attr_name;
7195  MOP class_obj = NULL;
7196  DB_DEFAULT_EXPR *default_expr = NULL;
7197  DB_DEFAULT_EXPR_TYPE *on_update_default_expr = NULL;
7198 
7199  db_make_null (&default_value);
7200 
7201  if (column == NULL || column->domain == NULL)
7202  {
7203  error = ER_FAILED;
7204  goto error_exit;
7205  }
7206 
7207  if (column->domain->type->id == DB_TYPE_NULL)
7208  {
7210  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
7211  goto error_exit;
7212  }
7213  else if (TP_IS_SET_TYPE (column->domain->type->id))
7214  {
7215  TP_DOMAIN *elem;
7216  for (elem = column->domain->setdomain; elem != NULL; elem = elem->next)
7217  {
7218  if (TP_DOMAIN_TYPE (elem) == DB_TYPE_BLOB || TP_DOMAIN_TYPE (elem) == DB_TYPE_CLOB)
7219  {
7220  PT_TYPE_ENUM elem_type, set_type;
7221  elem_type = pt_db_to_type_enum (TP_DOMAIN_TYPE (elem));
7222  set_type = pt_db_to_type_enum (column->domain->type->id);
7224  pt_show_type_enum (set_type), pt_show_type_enum (elem_type));
7225  error = ER_PT_SEMANTIC;
7226  goto error_exit;
7227  }
7228  }
7229  }
7230 
7231  attr_name = db_query_format_name (column);
7232 
7233  if (column->spec_name != NULL)
7234  {
7235  class_obj = sm_find_class (column->spec_name);
7236  if (class_obj == NULL)
7237  {
7238  goto error_exit;
7239  }
7240 
7241  error = sm_att_default_value (class_obj, column->attr_name, &default_value, &default_expr,
7242  &on_update_default_expr);
7243  if (error != NO_ERROR)
7244  {
7245  goto error_exit;
7246  }
7247  }
7248 
7249  error = smt_add_attribute_w_dflt (ctemplate, attr_name, NULL, column->domain, &default_value, ID_ATTRIBUTE,
7250  default_expr, on_update_default_expr, NULL);
7251  if (error != NO_ERROR)
7252  {
7253  goto error_exit;
7254  }
7255 
7256  if (class_obj != NULL)
7257  {
7258  if (sm_att_constrained (class_obj, column->attr_name, SM_ATTFLAG_NON_NULL))
7259  {
7260  error = dbt_constrain_non_null (ctemplate, attr_name, 0, 1);
7261  }
7262  }
7263 
7264  return error;
7265 
7266 error_exit:
7267  db_value_clear (&default_value);
7268  return error;
7269 }
7270 
7271 static DB_QUERY_TYPE *
7272 query_get_column_with_name (DB_QUERY_TYPE * query_columns, const char *name)
7273 {
7275  char real_name[SM_MAX_IDENTIFIER_LENGTH];
7276  char column_name[SM_MAX_IDENTIFIER_LENGTH];
7277 
7278  if (query_columns == NULL)
7279  {
7280  return NULL;
7281  }
7282 
7283  sm_downcase_name (name, real_name, SM_MAX_IDENTIFIER_LENGTH);
7284  for (column = query_columns; column != NULL; column = db_query_format_next (column))
7285  {
7287  if (intl_identifier_casecmp (real_name, column_name) == 0)
7288  {
7289  return column;
7290  }
7291  }
7292  return NULL;
7293 }
7294 
7295 static PT_NODE *
7296 get_attribute_with_name (PT_NODE * atts, const char *name)
7297 {
7298  PT_NODE *crt_attr;
7299  char real_name[SM_MAX_IDENTIFIER_LENGTH];
7301 
7302  if (atts == NULL)
7303  {
7304  return NULL;
7305  }
7306 
7307  sm_downcase_name (name, real_name, SM_MAX_IDENTIFIER_LENGTH);
7308  for (crt_attr = atts; crt_attr != NULL; crt_attr = crt_attr->next)
7309  {
7310  sm_downcase_name (get_attr_name (crt_attr), attribute_name, SM_MAX_IDENTIFIER_LENGTH);
7311  if (intl_identifier_casecmp (real_name, attribute_name) == 0)
7312  {
7313  return crt_attr;
7314  }
7315  }
7316  return NULL;
7317 }
7318 
7319 /*
7320  * do_add_attributes() - Adds attributes to a class object
7321  * return: Error code
7322  * parser(in): Parser context
7323  * ctemplate(in/out): Class template
7324  * atts(in/out): Attributes to add
7325  * constraints(in/out): the constraints of the class
7326  * create_select_columns(in): the column list of a select for
7327  * CREATE ... AS SELECT statements
7328  *
7329  * Note : The class object is modified
7330  */
7331 int
7332 do_add_attributes (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * atts, PT_NODE * constraints,
7333  DB_QUERY_TYPE * create_select_columns)
7334 {
7335  PT_NODE *crt_attr;
7337  int error = NO_ERROR;
7338 
7339  crt_attr = atts;
7340  while (crt_attr)
7341  {
7342  const char *const attr_name = get_attr_name (crt_attr);
7343  if (query_get_column_with_name (create_select_columns, attr_name) == NULL)
7344  {
7345  error = do_add_attribute (parser, ctemplate, crt_attr, constraints, false);
7346  if (error != NO_ERROR)
7347  {
7348  return error;
7349  }
7350  }
7351  crt_attr = crt_attr->next;
7352  }
7353 
7354  for (column = create_select_columns; column != NULL; column = db_query_format_next (column))
7355  {
7356  const char *const col_name = db_query_format_name (column);
7357  crt_attr = get_attribute_with_name (atts, col_name);
7358  if (crt_attr != NULL)
7359  {
7360  error = do_add_attribute (parser, ctemplate, crt_attr, constraints, true);
7361  if (error != NO_ERROR)
7362  {
7363  return error;
7364  }
7365  }
7366  else
7367  {
7368  error = do_add_attribute_from_select_column (parser, ctemplate, column);
7369  if (error != NO_ERROR)
7370  {
7371  return error;
7372  }
7373  }
7374  }
7375 
7376  return error;
7377 }
7378 
7379 
7380 /*
7381  * map_pt_to_sm_action() -
7382  * return: SM_FOREIGN_KEY_ACTION
7383  * action(in): Action to map
7384  *
7385  * Note:
7386  */
7387 static SM_FOREIGN_KEY_ACTION
7389 {
7390  switch (action)
7391  {
7392  case PT_RULE_CASCADE:
7393  return SM_FOREIGN_KEY_CASCADE;
7394 
7395  case PT_RULE_RESTRICT:
7396  return SM_FOREIGN_KEY_RESTRICT;
7397 
7398  case PT_RULE_NO_ACTION:
7399  return SM_FOREIGN_KEY_NO_ACTION;
7400 
7401  case PT_RULE_SET_NULL:
7402  return SM_FOREIGN_KEY_SET_NULL;
7403 
7404  default:
7405  break;
7406  }
7407 
7408  return SM_FOREIGN_KEY_NO_ACTION;
7409 }
7410 
7411 /*
7412  * add_foreign_key() -
7413  * return: Error code
7414  * ctemplate(in/out): Class template
7415  * cnstr(in): Constraint name
7416  * att_names(in): Key attribute names
7417  *
7418  * Note:
7419  */
7420 static int
7421 add_foreign_key (DB_CTMPL * ctemplate, const PT_NODE * cnstr, const char **att_names)
7422 {
7423  PT_FOREIGN_KEY_INFO *fk_info;
7424  const char *constraint_name = NULL;
7425  char **ref_attrs = NULL;
7426  int i, n_atts, n_ref_atts;
7427  PT_NODE *p;
7428  int error = NO_ERROR;
7429  const char *comment = NULL;
7430  size_t buf_size;
7431 
7432  fk_info = (PT_FOREIGN_KEY_INFO *) (&cnstr->info.constraint.un.foreign_key);
7433 
7434  n_atts = pt_length_of_list (fk_info->attrs);
7435  i = 0;
7436  for (p = fk_info->attrs; p; p = p->next)
7437  {
7438  att_names[i++] = p->info.name.original;
7439  }
7440  att_names[i] = NULL;
7441 
7442  if (fk_info->referenced_attrs != NULL)
7443  {
7444  n_ref_atts = pt_length_of_list (fk_info->referenced_attrs);
7445 
7446  buf_size = (n_ref_atts + 1) * sizeof (char *);
7447  ref_attrs = (char **) malloc (buf_size);
7448  if (ref_attrs == NULL)
7449  {
7450  error = ER_OUT_OF_VIRTUAL_MEMORY;
7452  return error;
7453  }
7454 
7455  i = 0;
7456  for (p = fk_info->referenced_attrs; p; p = p->next)
7457  {
7458  ref_attrs[i++] = (char *) p->info.name.original;
7459  }
7460  ref_attrs[i] = NULL;
7461  }
7462 
7463  /* Get the constraint name (if supplied) */
7464  if (cnstr->info.constraint.name)
7465  {
7466  constraint_name = cnstr->info.constraint.name->info.name.original;
7467  }
7468 
7469  if (cnstr->info.constraint.comment != NULL)
7470  {
7472  comment = (char *) PT_VALUE_GET_BYTES (cnstr->info.constraint.comment);
7473  }
7474 
7475  error =
7476  dbt_add_foreign_key (ctemplate, constraint_name, att_names, fk_info->referenced_class->info.name.original,
7477  (const char **) ref_attrs, map_pt_to_sm_action (fk_info->delete_action),
7478  map_pt_to_sm_action (fk_info->update_action), comment);
7479  free_and_init (ref_attrs);
7480  return error;
7481 }
7482 
7483 
7484 /*
7485  * do_add_constraints() - This extern routine adds constraints
7486  * to a class object.
7487  * return: Error code
7488  * ctemplate(in/out): Class template
7489  * constraints(in): Constraints to add
7490  *
7491  * Note : Class object is modified
7492  */
7493 int
7494 do_add_constraints (DB_CTMPL * ctemplate, PT_NODE * constraints)
7495 {
7496  int error = NO_ERROR;
7497  PT_NODE *cnstr;
7498  int max_attrs = 0;
7499  char **att_names = NULL;
7500  size_t buf_size;
7501 
7502  /* Find the size of the largest UNIQUE constraint list and allocate a character array large enough to contain it. */
7503  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
7504  {
7505  if (cnstr->info.constraint.type == PT_CONSTRAIN_UNIQUE)
7506  {
7507  max_attrs = MAX (max_attrs, pt_length_of_list (cnstr->info.constraint.un.unique.attrs));
7508  }
7510  {
7511  max_attrs = MAX (max_attrs, pt_length_of_list (cnstr->info.constraint.un.primary_key.attrs));
7512  }
7514  {
7515  max_attrs = MAX (max_attrs, pt_length_of_list (cnstr->info.constraint.un.foreign_key.attrs));
7516  }
7517  }
7518 
7519  if (max_attrs > 0)
7520  {
7521  buf_size = (max_attrs + 1) * sizeof (char *);
7522  att_names = (char **) malloc (buf_size);
7523 
7524  if (att_names == NULL)
7525  {
7527  error = ER_OUT_OF_VIRTUAL_MEMORY;
7528  }
7529  else
7530  {
7531  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
7532  {
7533  if (cnstr->info.constraint.type == PT_CONSTRAIN_UNIQUE)
7534  {
7535  PT_NODE *p;
7536  int i, n_atts;
7537  int class_attributes = 0;
7538  char *constraint_name = NULL;
7539  DB_CONSTRAINT_TYPE constraint_type = DB_CONSTRAINT_UNIQUE;
7540  int *asc_desc = NULL;
7541  char *comment = NULL;
7542 
7543  n_atts = pt_length_of_list (cnstr->info.constraint.un.unique.attrs);
7544 
7545  asc_desc = (int *) malloc (n_atts * sizeof (int));
7546  if (asc_desc == NULL)
7547  {
7548  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (n_atts * sizeof (int)));
7549  error = ER_OUT_OF_VIRTUAL_MEMORY;
7550  goto constraint_error;
7551  }
7552 
7554  {
7555  constraint_type = DB_CONSTRAINT_REVERSE_UNIQUE;
7556  }
7557 
7558  i = 0;
7559  for (p = cnstr->info.constraint.un.unique.attrs; p; p = p->next)
7560  {
7561  asc_desc[i] = PT_NAME_INFO_IS_FLAGED (p, PT_NAME_INFO_DESC) ? 1 : 0;
7562  att_names[i++] = (char *) p->info.name.original;
7563 
7564  /* Determine if the unique constraint is being applied to class or normal attributes. The way
7565  * the parser currently works, all multi-column constraints will be on normal attributes and it's
7566  * therefore impossible for a constraint to contain both class and normal attributes. */
7568  {
7569  class_attributes = 1;
7570  }
7571 
7572  /* We keep DB_CONSTRAINT_REVERSE_UNIQUE only if all columns are marked as DESC. */
7574  {
7575  constraint_type = DB_CONSTRAINT_UNIQUE;
7576  }
7577  }
7578  att_names[i] = NULL;
7579 
7580  /* Get the constraint name (if supplied) */
7581  if (cnstr->info.constraint.name)
7582  {
7583  constraint_name = (char *) cnstr->info.constraint.name->info.name.original;
7584  }
7585 
7586  constraint_name =
7587  sm_produce_constraint_name_tmpl (ctemplate, constraint_type, (const char **) att_names, asc_desc,
7588  constraint_name);
7589  if (constraint_name == NULL)
7590  {
7591  assert (er_errid () != NO_ERROR);
7592  error = er_errid ();
7593  free_and_init (asc_desc);
7594  goto constraint_error;
7595  }
7596 
7597  if (cnstr->info.constraint.comment != NULL)
7598  {
7600  comment = (char *) PT_VALUE_GET_BYTES (cnstr->info.constraint.comment);
7601  }
7602 
7603  error = smt_add_constraint (ctemplate, constraint_type, constraint_name, (const char **) att_names,
7604  asc_desc, NULL, class_attributes, NULL, NULL, NULL, comment,
7605  SM_NORMAL_INDEX);
7606 
7607  free_and_init (constraint_name);
7608  free_and_init (asc_desc);
7609  if (error != NO_ERROR)
7610  {
7611  goto constraint_error;
7612  }
7613  }
7614  else if (cnstr->info.constraint.type == PT_CONSTRAIN_PRIMARY_KEY)
7615  {
7616  PT_NODE *p;
7617  int i, n_atts;
7618  int class_attributes = 0;
7619  char *constraint_name = NULL;
7620  int *asc_desc = NULL;
7621  char *comment = NULL;
7622 
7623  n_atts = pt_length_of_list (cnstr->info.constraint.un.primary_key.attrs);
7624 
7625  asc_desc = (int *) malloc (n_atts * sizeof (int));
7626  if (asc_desc == NULL)
7627  {
7628  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (n_atts * sizeof (int)));
7629  error = ER_OUT_OF_VIRTUAL_MEMORY;
7630  goto constraint_error;
7631  }
7632 
7633  i = 0;
7634  for (p = cnstr->info.constraint.un.primary_key.attrs; p; p = p->next)
7635  {
7636  asc_desc[i] = PT_NAME_INFO_IS_FLAGED (p, PT_NAME_INFO_DESC) ? 1 : 0;
7637  att_names[i++] = (char *) p->info.name.original;
7638 
7639  /* Determine if the unique constraint is being applied to class or normal attributes. The way
7640  * the parser currently works, all multi-column constraints will be on normal attributes and it's
7641  * therefore impossible for a constraint to contain both class and normal attributes. */
7643  {
7644  class_attributes = 1;
7645  }
7646  }
7647  att_names[i] = NULL;
7648 
7649  /* Get the constraint name (if supplied) */
7650  if (cnstr->info.constraint.name)
7651  {
7652  constraint_name = (char *) cnstr->info.constraint.name->info.name.original;
7653  }
7654 
7655  constraint_name =
7656  sm_produce_constraint_name_tmpl (ctemplate, DB_CONSTRAINT_PRIMARY_KEY, (const char **) att_names,
7657  asc_desc, constraint_name);
7658  if (constraint_name == NULL)
7659  {
7660  free_and_init (asc_desc);
7661  assert (er_errid () != NO_ERROR);
7662  error = er_errid ();
7663  goto constraint_error;
7664  }
7665 
7666  if (cnstr->info.constraint.comment != NULL)
7667  {
7669  comment = (char *) PT_VALUE_GET_BYTES (cnstr->info.constraint.comment);
7670  }
7671 
7672  error = smt_add_constraint (ctemplate, DB_CONSTRAINT_PRIMARY_KEY, constraint_name,
7673  (const char **) att_names, asc_desc, NULL, class_attributes, NULL, NULL,
7674  NULL, comment, SM_NORMAL_INDEX);
7675 
7676  free_and_init (constraint_name);
7677  free_and_init (asc_desc);
7678 
7679  if (error != NO_ERROR)
7680  {
7681  goto constraint_error;
7682  }
7683  }
7684  else if (cnstr->info.constraint.type == PT_CONSTRAIN_FOREIGN_KEY)
7685  {
7686  error = add_foreign_key (ctemplate, cnstr, (const char **) att_names);
7687  if (error != NO_ERROR)
7688  {
7689  goto constraint_error;
7690  }
7691  }
7692  }
7693 
7694  free_and_init (att_names);
7695  }
7696  }
7697 
7698  return (error);
7699 
7700 /* error handler */
7701 constraint_error:
7702  if (att_names)
7703  {
7704  free_and_init (att_names);
7705  }
7706  return (error);
7707 }
7708 
7709 /*
7710  * do_check_fk_constraints_internal () - Checks that foreign key constraints
7711  * are consistent with the schema.
7712  * The routine only works when a new class is created or when it is altered
7713  * with a single change; it might not work in the future if a class will be
7714  * altered with multiple changes in a single call.
7715  *
7716  * Currently the following checks are performed:
7717  * SET NULL referential actions must not contradict the attributes' domains
7718  * (the attributes cannot have a NOT NULL constraint as they cannot be
7719  * NULL).
7720  *
7721  * SET NULL actions are not yet supported on partitioned tables.
7722  *
7723  * In the future the function should also check for foreign keys that have
7724  * cascading referential actions and either represent cycles in the schema or
7725  * represent "race" updates (the same attribute can be affected on two
7726  * separate cascading action paths; the results are undefined).
7727  *
7728  * return: Error code
7729  * ctemplate(in/out): Class template
7730  * constraints(in): List of all the class constraints that have been added.
7731  * Currently the function does not support checking for
7732  * consistency when NOT NULL constraints are added.
7733  *
7734  * Note : The class object is not modified
7735  */
7736 static int
7737 do_check_fk_constraints_internal (DB_CTMPL * ctemplate, PT_NODE * constraints, bool is_partitioned)
7738 {
7739  int error = NO_ERROR;
7740  PT_NODE *cnstr;
7741 
7742  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
7743  {
7744  PT_NODE *attr;
7745  PT_FOREIGN_KEY_INFO *fk_info;
7746 
7748  {
7749  continue;
7750  }
7751 
7752  fk_info = (PT_FOREIGN_KEY_INFO *) (&cnstr->info.constraint.un.foreign_key);
7753  if (is_partitioned && (fk_info->delete_action == PT_RULE_SET_NULL || fk_info->update_action == PT_RULE_SET_NULL))
7754  {
7755  PT_NODE *const constr_name = cnstr->info.constraint.name;
7756  ERROR2 (error, ER_FK_CANT_ON_PARTITION, constr_name ? constr_name->info.name.original : "", ctemplate->name);
7757  goto error_exit;
7758  }
7759 
7760  for (attr = fk_info->attrs; attr; attr = attr->next)
7761  {
7762  const char *const att_name = attr->info.name.original;
7763  SM_ATTRIBUTE *attp = NULL;
7764 
7765  error = smt_find_attribute (ctemplate, att_name, 0, &attp);
7766  if (error != NO_ERROR)
7767  {
7768  goto error_exit;
7769  }
7770 
7771  /* FK cannot be defined on shared attribute. */
7772  if (db_attribute_is_shared (attp))
7773  {
7774  PT_NODE *const constr_name = cnstr->info.constraint.name;
7775  ERROR2 (error, ER_FK_CANT_ON_SHARED_ATTRIBUTE, constr_name ? constr_name->info.name.original : "",
7776  att_name);
7777  goto error_exit;
7778  }
7779  if ((fk_info->delete_action == PT_RULE_SET_NULL || fk_info->update_action == PT_RULE_SET_NULL)
7780  && db_attribute_is_non_null (attp))
7781  {
7782  PT_NODE *const constr_name = cnstr->info.constraint.name;
7783  ERROR2 (error, ER_FK_MUST_NOT_BE_NOT_NULL, constr_name ? constr_name->info.name.original : "", att_name);
7784  goto error_exit;
7785  }
7786  }
7787  }
7788 
7789  if (ctemplate->current != NULL)
7790  {
7792 
7793  for (c = ctemplate->current->constraints; c != NULL; c = c->next)
7794  {
7795  SM_ATTRIBUTE **attribute_p = NULL;
7796 
7797  if (c->type != SM_CONSTRAINT_FOREIGN_KEY)
7798  {
7799  continue;
7800  }
7801  if (is_partitioned
7804  {
7805  ERROR2 (error, ER_FK_CANT_ON_PARTITION, c->name ? c->name : "", ctemplate->name);
7806  goto error_exit;
7807  }
7810  {
7811  continue;
7812  }
7813  for (attribute_p = c->attributes; *attribute_p; ++attribute_p)
7814  {
7815  const char *const att_name = (*attribute_p)->header.name;
7816  SM_ATTRIBUTE *attp = NULL;
7817 
7818  smt_find_attribute (ctemplate, att_name, 0, &attp);
7819  if (db_attribute_is_non_null (attp))
7820  {
7821  ERROR2 (error, ER_FK_MUST_NOT_BE_NOT_NULL, c->name ? c->name : "", att_name);
7822  goto error_exit;
7823  }
7824  }
7825  }
7826  }
7827  return error;
7828 
7829 error_exit:
7830  return error;
7831 }
7832 
7833 /*
7834 * do_check_fk_constraints() - Checks that foreign key constraints are
7835 * consistent with the schema.
7836 * return: Error code
7837 * ctemplate(in/out): Class template
7838 * constraints(in): List of all the class constraints that have been added.
7839 * Currently the function does not support checking for
7840 * consistency when NOT NULL constraints are added.
7841 * Note : The class object is not modified
7842 */
7843 int
7844 do_check_fk_constraints (DB_CTMPL * ctemplate, PT_NODE * constraints)
7845 {
7846  bool is_partitioned = false;
7847  if (ctemplate == NULL)
7848  {
7849  assert_release (ctemplate != NULL);
7850  return ER_FAILED;
7851  }
7852 
7853  if (ctemplate->partition != NULL)
7854  {
7855  is_partitioned = true;
7856  }
7857 
7858  return do_check_fk_constraints_internal (ctemplate, constraints, is_partitioned);
7859 }
7860 
7861 
7862 /*
7863  * do_add_methods() - Adds methods to a class object
7864  * return: Error code
7865  * parser(in): Parser context
7866  * ctemplate(in/out): Class template
7867  * methods(in): Methods to add
7868  *
7869  * Note : Class object is modified
7870  */
7871 int
7872 do_add_methods (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * methods)
7873 {
7874  const char *method_name, *method_impl;
7875  PT_NODE *args_list, *type, *type_list;
7876  PT_NODE *data_type;
7877  int arg_num;
7878  int is_meta;
7879  int error = NO_ERROR;
7880  TP_DOMAIN *arg_db_domain;
7881 
7882  /* add each method listed in the class definition */
7883 
7884  while (methods && (error == NO_ERROR))
7885  {
7886  method_name = methods->info.method_def.method_name->info.name.original;
7887 
7888  if (methods->info.method_def.function_name != NULL)
7889  {
7890  method_impl = methods->info.method_def.function_name->info.name.original;
7891  }
7892  else
7893  {
7894  method_impl = NULL;
7895  }
7896 
7897  if (methods->info.method_def.mthd_type == PT_META_ATTR)
7898  {
7899  error = dbt_add_class_method (ctemplate, method_name, method_impl);
7900  }
7901  else
7902  {
7903  error = dbt_add_method (ctemplate, method_name, method_impl);
7904  }
7905  if (error != NO_ERROR)
7906  {
7907  return error;
7908  }
7909 
7910  /* if the result of the method is declared, then add it! */
7911 
7912  arg_num = 0;
7913  is_meta = methods->info.method_def.mthd_type == PT_META_ATTR;
7914 
7915  if (methods->type_enum != PT_TYPE_NONE)
7916  {
7917  if (PT_IS_COLLECTION_TYPE (methods->type_enum))
7918  {
7919  arg_db_domain = pt_node_to_db_domain (parser, methods, ctemplate->name);
7920  if (arg_db_domain == NULL)
7921  {
7922  assert (er_errid () != NO_ERROR);
7923  return (er_errid ());
7924  }
7925 
7926  error = smt_assign_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
7927  if (error != NO_ERROR)
7928  {
7929  return error;
7930  }
7931 
7932  type_list = methods->data_type;
7933  for (type = type_list; type != NULL; type = type->next)
7934  {
7935  arg_db_domain = pt_data_type_to_db_domain (parser, type, ctemplate->name);
7936  if (arg_db_domain == NULL)
7937  {
7938  assert (er_errid () != NO_ERROR);
7939  return (er_errid ());
7940  }
7941 
7942  error =
7943  smt_add_set_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
7944  if (error != NO_ERROR)
7945  {
7946  return error;
7947  }
7948  }
7949  }
7950  else
7951  {
7952  if (validate_attribute_domain (parser, methods, false))
7953  {
7954  return ER_GENERIC_ERROR;
7955  }
7956  arg_db_domain = pt_node_to_db_domain (parser, methods, ctemplate->name);
7957  if (arg_db_domain == NULL)
7958  {
7959  assert (er_errid () != NO_ERROR);
7960  return (er_errid ());
7961  }
7962 
7963  error = smt_assign_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
7964  if (error != NO_ERROR)
7965  {
7966  return error;
7967  }
7968  }
7969  }
7970 
7971  /* add each argument of the method that is declared. */
7972 
7973  args_list = methods->info.method_def.method_args_list;
7974  for (data_type = args_list; data_type != NULL; data_type = data_type->next)
7975  {
7976  arg_num++;
7977 
7978  if (PT_IS_COLLECTION_TYPE (data_type->type_enum))
7979  {
7980  arg_db_domain = pt_data_type_to_db_domain (parser, data_type, ctemplate->name);
7981  if (arg_db_domain == NULL)
7982  {
7983  assert (er_errid () != NO_ERROR);
7984  return (er_errid ());
7985  }
7986 
7987  error = smt_assign_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
7988  if (error != NO_ERROR)
7989  {
7990  return error;
7991  }
7992 
7993  type_list = data_type->data_type;
7994  for (type = type_list; type != NULL; type = type->next)
7995  {
7996  arg_db_domain = pt_data_type_to_db_domain (parser, type, ctemplate->name);
7997  if (arg_db_domain == NULL)
7998  {
7999  assert (er_errid () != NO_ERROR);
8000  return (er_errid ());
8001  }
8002 
8003  error =
8004  smt_add_set_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
8005  if (error != NO_ERROR)
8006  {
8007  return error;
8008  }
8009  }
8010  }
8011  else
8012  {
8013  if (validate_attribute_domain (parser, data_type, false))
8014  {
8015  return ER_GENERIC_ERROR;
8016  }
8017  arg_db_domain = pt_node_to_db_domain (parser, data_type, ctemplate->name);
8018  if (arg_db_domain == NULL)
8019  {
8020  assert (er_errid () != NO_ERROR);
8021  return (er_errid ());
8022  }
8023 
8024  error = smt_assign_argument_domain (ctemplate, method_name, is_meta, NULL, arg_num, NULL, arg_db_domain);
8025  if (error != NO_ERROR)
8026  {
8027  return error;
8028  }
8029  }
8030  }
8031 
8032  methods = methods->next;
8033  }
8034  return (error);
8035 }
8036 
8037 /*
8038  * do_add_method_files() - Adds method files to a class object
8039  * return: Error code
8040  * parser(in): Parser context
8041  * ctemplate(in/out): Class template
8042  * method_files(in): Method files to add
8043  *
8044  * Note : Class object is modified
8045  */
8046 int
8047 do_add_method_files (const PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * method_files)
8048 {
8049  const char *method_file_name;
8050  int error = NO_ERROR;
8051  PT_NODE *path, *mf;
8052 
8053  /* add each method_file listed in the class definition */
8054 
8055  for (mf = method_files; mf && error == NO_ERROR; mf = mf->next)
8056  {
8057  if (mf->node_type == PT_FILE_PATH && (path = mf->info.file_path.string) != NULL && path->node_type == PT_VALUE
8058  && (path->type_enum == PT_TYPE_VARCHAR || path->type_enum == PT_TYPE_CHAR || path->type_enum == PT_TYPE_NCHAR
8059  || path->type_enum == PT_TYPE_VARNCHAR))
8060  {
8061  method_file_name = (char *) path->info.value.data_value.str->bytes;
8062  error = dbt_add_method_file (ctemplate, method_file_name);
8063  }
8064  else
8065  {
8066  break;
8067  }
8068  }
8069 
8070  return (error);
8071 }
8072 
8073 /*
8074  * do_add_supers() - Adds super-classes to a class object
8075  * return: Error code
8076  * parser(in): Parser context
8077  * ctemplate(in/out): Class template
8078  * supers(in): Superclasses to add
8079  *
8080  * Note : Class object is modified
8081  */
8082 int
8083 do_add_supers (const PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * supers)
8084 {
8085  MOP super_class;
8086  int error = NO_ERROR;
8087 
8088 
8089  /* Add each superclass listed in the class definition. Each superclass must already exist inthe database before it
8090  * can be added. */
8091 
8092  while (supers && (error == NO_ERROR))
8093  {
8094  super_class = db_find_class (supers->info.name.original);
8095  if (super_class == NULL)
8096  {
8097  assert (er_errid () != NO_ERROR);
8098  error = er_errid ();
8099  }
8100  else
8101  {
8102  error = dbt_add_super (ctemplate, super_class);
8103  }
8104 
8105  supers = supers->next;
8106  }
8107 
8108  return (error);
8109 }
8110 
8111 /*
8112  * do_add_resolutions() - Adds resolutions to a class object
8113  * return: Error code
8114  * parser(in): Parser context
8115  * ctemplate(in/out): Class template
8116  * supers(in): Resolution to add
8117  *
8118  * Note : Class object is modified
8119  */
8120 int
8121 do_add_resolutions (const PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * resolution)
8122 {
8123  int error = NO_ERROR;
8124  DB_OBJECT *resolution_super_mop;
8125  const char *resolution_attr_mthd_name, *resolution_as_attr_mthd_name;
8126 
8127  /* add each conflict resolution listed in the class definition */
8128 
8129  while (resolution && (error == NO_ERROR))
8130  {
8131  resolution_super_mop = db_find_class (resolution->info.resolution.of_sup_class_name->info.name.original);
8132 
8133  if (resolution_super_mop == NULL)
8134  {
8135  assert (er_errid () != NO_ERROR);
8136  error = er_errid ();
8137  break;
8138  }
8139 
8140  resolution_attr_mthd_name = resolution->info.resolution.attr_mthd_name->info.name.original;
8141  if (resolution->info.resolution.as_attr_mthd_name == NULL)
8142  {
8143  resolution_as_attr_mthd_name = NULL;
8144  }
8145  else
8146  {
8147  resolution_as_attr_mthd_name = resolution->info.resolution.as_attr_mthd_name->info.name.original;
8148  }
8149 
8150  if (resolution->info.resolution.attr_type == PT_META_ATTR)
8151  {
8152  error =
8153  dbt_add_class_resolution (ctemplate, resolution_super_mop, resolution_attr_mthd_name,
8154  resolution_as_attr_mthd_name);
8155  }
8156  else
8157  {
8158  error =
8159  dbt_add_resolution (ctemplate, resolution_super_mop, resolution_attr_mthd_name,
8160  resolution_as_attr_mthd_name);
8161  }
8162 
8163  resolution = resolution->next;
8164  }
8165 
8166  return (error);
8167 }
8168 
8169 /*
8170  * add_query_to_virtual_class() - Adds a query to a virtual class object
8171  * return: Error code
8172  * parser(in): Parser context
8173  * ctemplate(in/out): Class template
8174  * supers(in): Queries to add
8175  *
8176  * Note : Class object is modified
8177  */
8178 static int
8179 add_query_to_virtual_class (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * queries)
8180 {
8181  const char *query;
8182  int error = NO_ERROR;
8183  unsigned int save_custom;
8184 
8185  save_custom = parser->custom_print;
8187 
8188  query = parser_print_tree_with_quotes (parser, queries);
8189  parser->custom_print = save_custom;
8190  error = dbt_add_query_spec (ctemplate, query);
8191 
8192  return (error);
8193 }
8194 
8195 /*
8196  * add_union_query() - Adds a query to a virtual class object.
8197  * If the query is a union all query
8198  * without limit and order_by, it is
8199  * divided into its component queries
8200  * return: Error code
8201  * parser(in): Parser context
8202  * ctemplate(in/out): Class template
8203  * supers(in): Union queries to add
8204  *
8205  * Note : class object modified
8206  */
8207 static int
8208 add_union_query (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * query)
8209 {
8210  int error = NO_ERROR;
8211 
8212  /* Add each query listed in the virtual class definition. */
8213 
8214  if (query->node_type == PT_UNION && query->info.query.all_distinct == PT_ALL && query->info.query.limit == NULL
8215  && query->info.query.order_by == NULL)
8216  {
8217  error = add_union_query (parser, ctemplate, query->info.query.q.union_.arg1);
8218 
8219  if (error == NO_ERROR)
8220  {
8221  error = add_union_query (parser, ctemplate, query->info.query.q.union_.arg2);
8222  }
8223  }
8224  else
8225  {
8226  error = add_query_to_virtual_class (parser, ctemplate, query);
8227  }
8228 
8229  return (error);
8230 }
8231 
8232 /*
8233  * do_add_queries() - Adds a list of queries to a virtual class object
8234  * return: Error code
8235  * parser(in): Parser context
8236  * ctemplate(in/out): Class template
8237  * queries(in): Queries to add
8238  *
8239  * Note : Class object is modified
8240  */
8241 int
8242 do_add_queries (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, const PT_NODE * queries)
8243 {
8244  int error = NO_ERROR;
8245 
8246  while (queries && (error == NO_ERROR))
8247  {
8248  error = add_union_query (parser, ctemplate, queries);
8249 
8250  queries = queries->next;
8251  }
8252 
8253  return (error);
8254 }
8255 
8256 /*
8257  * do_set_object_id() - Sets the object_id for a class object
8258  * return: Error code
8259  * parser(in): Parser context
8260  * ctemplate(in/out): Class template
8261  * queries(in): Object ids to set
8262  *
8263  * Note : Class object is modified
8264  */
8265 int
8266 do_set_object_id (const PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * object_id_list)
8267 {
8268  int error = NO_ERROR;
8269  PT_NODE *object_id;
8270  int total_ids = 0;
8271  DB_NAMELIST *id_list = NULL;
8272  const char *att_name;
8273 
8274  object_id = object_id_list;
8275  while (object_id)
8276  {
8277  att_name = object_id->info.name.original;
8278  if (att_name)
8279  {
8280  (void) db_namelist_append (&id_list, att_name);
8281  }
8282  ++total_ids;
8283  object_id = object_id->next;
8284  }
8285  if (total_ids == 0)
8286  {
8287  if (id_list)
8288  {
8289  db_namelist_free (id_list);
8290  }
8291  return (error);
8292  }
8293 
8294  error = dbt_set_object_id (ctemplate, id_list);
8295  db_namelist_free (id_list);
8296 
8297  return (error);
8298 }
8299 
8300 /*
8301  * do_create_local() - Creates a new class or vclass
8302  * return: Error code if the class/vclass is not created
8303  * parser(in): Parser context
8304  * ctemplate(in/out): Class template
8305  * pt_node(in): Parse tree of a create class/vclass
8306  */
8307 int
8308 do_create_local (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * pt_node,
8309  DB_QUERY_TYPE * create_select_columns)
8310 {
8311  int error = NO_ERROR;
8312 
8313  /* create a MOP for the ctemplate, extracting its name from the parse tree. */
8314 
8315  error =
8316  do_add_attributes (parser, ctemplate, pt_node->info.create_entity.attr_def_list,
8317  pt_node->info.create_entity.constraint_list, create_select_columns);
8318  if (error != NO_ERROR)
8319  {
8320  return error;
8321  }
8322 
8323  error = do_add_attributes (parser, ctemplate, pt_node->info.create_entity.class_attr_def_list, NULL, NULL);
8324  if (error != NO_ERROR)
8325  {
8326  return error;
8327  }
8328 
8329  error = do_add_constraints (ctemplate, pt_node->info.create_entity.constraint_list);
8330  if (error != NO_ERROR)
8331  {
8332  return error;
8333  }
8334 
8335  error = do_check_fk_constraints (ctemplate, pt_node->info.create_entity.constraint_list);
8336  if (error != NO_ERROR)
8337  {
8338  return error;
8339  }
8340 
8341  error = do_add_methods (parser, ctemplate, pt_node->info.create_entity.method_def_list);
8342  if (error != NO_ERROR)
8343  {
8344  return error;
8345  }
8346 
8347  error = do_add_method_files (parser, ctemplate, pt_node->info.create_entity.method_file_list);
8348  if (error != NO_ERROR)
8349  {
8350  return error;
8351  }
8352 
8353  error = do_add_resolutions (parser, ctemplate, pt_node->info.create_entity.resolution_list);
8354  if (error != NO_ERROR)
8355  {
8356  return error;
8357  }
8358 
8359  error = do_add_supers (parser, ctemplate, pt_node->info.create_entity.supclass_list);
8360  if (error != NO_ERROR)
8361  {
8362  return error;
8363  }
8364 
8365  error = do_add_queries (parser, ctemplate, pt_node->info.create_entity.as_query_list);
8366  if (error != NO_ERROR)
8367  {
8368  return error;
8369  }
8370 
8371  error = do_set_object_id (parser, ctemplate, pt_node->info.create_entity.object_id_list);
8372  if (error != NO_ERROR)
8373  {
8374  return error;
8375  }
8376 
8377  if (pt_node->info.create_entity.partition_info)
8378  {
8379  /* set partitioning key flag on the attribute */
8380  PT_NODE *pt_key_col = pt_node->info.create_entity.partition_info->info.partition.keycol;
8381  const char *key_col_name = pt_key_col->info.name.original;
8382  SM_ATTRIBUTE *attr = ctemplate->attributes;
8383 
8384  while (attr != NULL)
8385  {
8386  if (SM_COMPARE_NAMES (key_col_name, attr->header.name) == 0)
8387  {
8389  break;
8390  }
8391  attr = (SM_ATTRIBUTE *) attr->header.next;
8392  }
8393  }
8394  return (error);
8395 }
8396 
8397 /*
8398  * create_select_to_insert_into() - An "INSERT INTO ... SELECT" statement is
8399  * built from a simple SELECT statement to be
8400  * used for "CREATE ... AS SELECT" execution
8401  * return: The INSERT statement or NULL on error
8402  * parser(in): Parser context
8403  * class_name(in): the name of the table created by the CREATE statement
8404  * create_select(in): the select statement parse tree
8405  * query_columns(in): the columns of the select statement
8406  */
8407 static PT_NODE *
8408 create_select_to_insert_into (PARSER_CONTEXT * parser, const char *class_name, PT_NODE * create_select,
8409  PT_CREATE_SELECT_ACTION create_select_action, DB_QUERY_TYPE * query_columns)
8410 {
8411  PT_NODE *ins = NULL;
8412  PT_NODE *ocs = NULL;
8413  PT_NODE *nls = NULL;
8415  char real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
8416  PT_NODE *name = NULL;
8417 
8418  /* TODO The generated nodes have incorrect line and column information. */
8419  ins = parser_new_node (parser, PT_INSERT);
8420  if (ins == NULL)
8421  {
8422  goto error_exit;
8423  }
8424 
8425  if (create_select_action == PT_CREATE_SELECT_REPLACE)
8426  {
8427  ins->info.insert.do_replace = true;
8428  }
8429  else
8430  {
8431  /* PT_CREATE_SELECT_IGNORE is not yet implemented */
8432  assert (create_select_action == PT_CREATE_SELECT_NO_ACTION);
8433  }
8434 
8435  ins->info.insert.spec = ocs = parser_new_node (parser, PT_SPEC);
8436  if (ocs == NULL)
8437  {
8438  goto error_exit;
8439  }
8440 
8441  ocs->info.spec.only_all = PT_ONLY;
8442  ocs->info.spec.meta_class = PT_CLASS;
8443  ocs->info.spec.entity_name = pt_name (parser, class_name);
8444  if (ocs->info.spec.entity_name == NULL)
8445  {
8446  goto error_exit;
8447  }
8448 
8449  for (column = query_columns; column != NULL; column = db_query_format_next (column))
8450  {
8452 
8453  name = pt_name (parser, real_name);
8454  if (name == NULL)
8455  {
8456  goto error_exit;
8457  }
8459  }
8460 
8461  ins->info.insert.value_clauses = nls = pt_node_list (parser, PT_IS_SUBQUERY, create_select);
8462  if (nls == NULL)
8463  {
8464  goto error_exit;
8465  }
8466 
8467  return ins;
8468 
8469 error_exit:
8470  parser_free_tree (parser, ins);
8471  return NULL;
8472 }
8473 
8474 /*
8475  * execute_create_select_query() - Executes an "INSERT INTO ... SELECT"
8476  * statement built from a SELECT statement to
8477  * be used for "CREATE ... AS SELECT"
8478  * execution
8479  * return: NO_ERROR on success, non-zero for ERROR
8480  * parser(in): Parser context
8481  * class_name(in): the name of the table created by the CREATE statement
8482  * create_select(in): the select statement parse tree
8483  * query_columns(in): the columns of the select statement
8484  * flagged_statement(in): a node to copy the special statement flags from;
8485  * flags such as recompile will be used for the
8486  * INSERT statement
8487  */
8488 static int
8489 execute_create_select_query (PARSER_CONTEXT * parser, const char *const class_name, PT_NODE * create_select,
8490  PT_CREATE_SELECT_ACTION create_select_action, DB_QUERY_TYPE * query_columns,
8491  PT_NODE * flagged_statement)
8492 {
8493  PT_NODE *insert_into = NULL;
8494  PT_NODE *create_select_copy = parser_copy_tree (parser, create_select);
8495  int error = NO_ERROR;
8496 
8497  if (create_select_copy == NULL)
8498  {
8499  error = ER_FAILED;
8500  goto error_exit;
8501  }
8502  insert_into =
8503  create_select_to_insert_into (parser, class_name, create_select_copy, create_select_action, query_columns);
8504  if (insert_into == NULL)
8505  {
8506  assert (er_errid () != NO_ERROR);
8507  error = er_errid ();
8508  goto error_exit;
8509  }
8510  pt_copy_statement_flags (flagged_statement, insert_into);
8511  create_select_copy = NULL;
8512 
8513  insert_into = pt_compile (parser, insert_into);
8514  if (!insert_into || pt_has_error (parser))
8515  {
8516  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, insert_into);
8517  error = er_errid ();
8518  goto error_exit;
8519  }
8520 
8521  insert_into = mq_translate (parser, insert_into);
8522  if (!insert_into || pt_has_error (parser))
8523  {
8524  pt_report_to_ersys_with_statement (parser, PT_SEMANTIC, insert_into);
8525  error = er_errid ();
8526  goto error_exit;
8527  }
8528 
8529  error = do_statement (parser, insert_into);
8530  pt_free_statement_xasl_id (insert_into);
8531  if (error < 0)
8532  {
8533  goto error_exit;
8534  }
8535  else
8536  {
8537  error = 0;
8538  }
8539 
8540  parser_free_tree (parser, insert_into);
8541  insert_into = NULL;
8542 
8543  return error;
8544 
8545 error_exit:
8546  if (create_select_copy != NULL)
8547  {
8548  parser_free_tree (parser, create_select_copy);
8549  create_select_copy = NULL;
8550  }
8551  if (insert_into != NULL)
8552  {
8553  parser_free_tree (parser, insert_into);
8554  insert_into = NULL;
8555  }
8556  return error;
8557 }
8558 
8559 /*
8560  * do_create_entity() - Creates a new class/vclass
8561  * return: Error code if the class/vclass is not created
8562  * parser(in): Parser context
8563  * node(in/out): Parse tree of a create class/vclass
8564  */
8565 int
8567 {
8568  int error = NO_ERROR;
8569  DB_CTMPL *ctemplate = NULL;
8571  const char *class_name = NULL;
8572  const char *create_like = NULL;
8573  SM_CLASS *source_class = NULL;
8574  PT_NODE *create_select = NULL;
8575  PT_NODE *create_index = NULL;
8576  DB_QUERY_TYPE *query_columns = NULL;
8577  PT_NODE *tbl_opt = NULL;
8578  bool found_reuse_oid_option = false, reuse_oid = false;
8579  bool do_rollback_on_error = false;
8580  bool do_abort_class_on_error = false;
8581  bool do_flush_class_mop = false;
8582  int charset = LANG_SYS_CODESET;
8583  int collation_id = LANG_SYS_COLLATION;
8584  PARSER_VARCHAR *comment = NULL;
8585  PT_NODE *tbl_opt_charset, *tbl_opt_coll, *cs_node, *coll_node;
8586  PT_NODE *tbl_opt_comment, *comment_node, *super_node;
8587  PT_NODE *tbl_opt_encrypt, *encrypt_node;
8588  const char *comment_str = NULL;
8589  MOP super_class = NULL;
8590  int tde_algo_opt = -1;
8591  TDE_ALGORITHM tde_algo = TDE_ALGORITHM_NONE;
8592 
8594 
8595  tbl_opt_charset = tbl_opt_coll = cs_node = coll_node = NULL;
8596  tbl_opt_comment = comment_node = NULL;
8597  tbl_opt_encrypt = encrypt_node = NULL;
8598 
8599  class_name = node->info.create_entity.entity_name->info.name.original;
8600 
8601  if (node->info.create_entity.create_like != NULL)
8602  {
8603  create_like = node->info.create_entity.create_like->info.name.original;
8604  }
8605 
8606  create_select = node->info.create_entity.create_select;
8607  if (create_select != NULL)
8608  {
8610 
8611  error = pt_get_select_query_columns (parser, create_select, &query_columns);
8612  if (error != NO_ERROR)
8613  {
8614  goto error_exit;
8615  }
8616 
8617  /* check for mis-creating string type with -1 precision */
8618  for (column = query_columns; column != NULL; column = db_query_format_next (column))
8619  {
8620  switch (column->domain->type->id)
8621  {
8622  case DB_TYPE_VARCHAR:
8623  if (column->domain->precision == DB_DEFAULT_PRECISION)
8624  {
8626  }
8627  break;
8628  case DB_TYPE_VARNCHAR:
8629  if (column->domain->precision == DB_DEFAULT_PRECISION)
8630  {
8632  }
8633  else if (column->domain->precision > DB_MAX_VARNCHAR_PRECISION)
8634  {
8636  }
8637  default:
8638  break;
8639  }
8640  }
8641  }
8642  assert (!(create_like != NULL && create_select != NULL));
8643 
8644  switch (node->info.create_entity.entity_type)
8645  {
8646  case PT_CLASS:
8647 
8648  if (node->info.create_entity.if_not_exists == 1 && db_find_class (class_name))
8649  {
8650  goto error_exit;
8651  }
8652 
8653  /* here we need to check if the super classes are partitioned, as it is not allowed to inherit from partition
8654  * tables. */
8655  super_node = node->info.create_entity.supclass_list;
8656 
8657  while (super_node)
8658  {
8659  super_class = db_find_class (super_node->info.name.original);
8660 
8661  if (super_class == NULL)
8662  {
8663  assert (er_errid () != NO_ERROR);
8664  error = er_errid ();
8665  goto error_exit;
8666  }
8667  else
8668  {
8669  error = sm_is_partitioned_class (super_class);
8670  if (error < 0)
8671  {
8672  goto error_exit;
8673  }
8674  if (error > 0)
8675  {
8677  error = er_errid ();
8678  goto error_exit;
8679  }
8680  }
8681 
8682  super_node = super_node->next;
8683  }
8684 
8685  for (tbl_opt = node->info.create_entity.table_option_list; tbl_opt != NULL; tbl_opt = tbl_opt->next)
8686  {
8687  assert (tbl_opt->node_type == PT_TABLE_OPTION);
8688  switch (tbl_opt->info.table_option.option)
8689  {
8691  found_reuse_oid_option = true;
8692  reuse_oid = true;
8693  break;
8695  tbl_opt_encrypt = tbl_opt;
8696  break;
8698  found_reuse_oid_option = true;
8699  reuse_oid = false;
8700  break;
8702  tbl_opt_charset = tbl_opt;
8703  break;
8705  tbl_opt_coll = tbl_opt;
8706  break;
8708  tbl_opt_comment = tbl_opt;
8709  break;
8710  default:
8711  break;
8712  }
8713  }
8714 
8715  /* get default value of reuse_oid from system parameter, if don't use table option related reuse_oid */
8716  if (!found_reuse_oid_option)
8717  {
8719  }
8720 
8721  /* validate charset and collation options, if any */
8722  cs_node = (tbl_opt_charset) ? tbl_opt_charset->info.table_option.val : NULL;
8723  coll_node = (tbl_opt_coll) ? tbl_opt_coll->info.table_option.val : NULL;
8724  charset = LANG_SYS_CODESET;
8725  collation_id = LANG_SYS_COLLATION;
8726  if (cs_node != NULL || coll_node != NULL)
8727  {
8728  error = pt_check_grammar_charset_collation (parser, cs_node, coll_node, &charset, &collation_id);
8729  if (error != NO_ERROR)
8730  {
8731  goto error_exit;
8732  }
8733  }
8734 
8736  if (error != NO_ERROR)
8737  {
8738  goto error_exit;
8739  }
8740  do_rollback_on_error = true;
8741 
8742  if (create_like)
8743  {
8744  ctemplate = dbt_copy_class (class_name, create_like, &source_class);
8745  }
8746  else
8747  {
8748  ctemplate = dbt_create_class (class_name);
8749  }
8750  break;
8751 
8752  case PT_VCLASS:
8754  if (error != NO_ERROR)
8755  {
8756  goto error_exit;
8757  }
8758  do_rollback_on_error = true;
8759 
8760  if (node->info.create_entity.or_replace && db_find_class (class_name))
8761  {
8762  /* drop existing view */
8763  if (do_is_partitioned_subclass (NULL, class_name, NULL))
8764  {
8766  error = er_errid ();
8767  goto error_exit;
8768  }
8769 
8770  error = drop_class_name (class_name, false);
8771  if (error != NO_ERROR)
8772  {
8773  goto error_exit;
8774  }
8775 
8776  /* Quick fix: create a savepoint to mark deleted transient state. */
8777  /* NOTE: Without this savepoint, creating view will completely replace deleted classname. */
8779  if (error != NO_ERROR)
8780  {
8781  goto error_exit;
8782  }
8783  }
8784 
8785  ctemplate = dbt_create_vclass (class_name);
8786  break;
8787 
8788  default:
8789  error = ER_GENERIC_ERROR; /* a system error */
8790  break;
8791  }
8792 
8793  if (ctemplate == NULL)
8794  {
8795  if (error == NO_ERROR)
8796  {
8797  error = er_errid ();
8798  }
8799  assert (error != NO_ERROR);
8800  goto error_exit;
8801  }
8802  do_abort_class_on_error = true;
8803 
8804  if (create_like != NULL)
8805  {
8806  /* Nothing left to do, but get the collation from the source class. */
8807  collation_id = source_class->collation_id;
8808  }
8809  else
8810  {
8811  error = do_create_local (parser, ctemplate, node, query_columns);
8812  }
8813 
8814  if (error != NO_ERROR)
8815  {
8816  goto error_exit;
8817  }
8818 
8819  class_obj = dbt_finish_class (ctemplate);
8820 
8821  if (class_obj == NULL)
8822  {
8823  assert (er_errid () != NO_ERROR);
8824  error = er_errid ();
8825  goto error_exit;
8826  }
8827 
8829  {
8830  /* Because the class is still inexistent, normally, here we will have to encounter some errors/warnings like
8831  * ER_LC_UNKNOWN_CLASSNAME which is unuseful for current context indeed and may disturb other subsequent
8832  * routines. Thus, we can/should clear the errors safely. */
8833  er_clear ();
8834  }
8835 
8836  do_abort_class_on_error = false;
8837  ctemplate = NULL;
8838 
8839  switch (node->info.create_entity.entity_type)
8840  {
8841  case PT_VCLASS:
8843  {
8844  error = sm_set_class_flag (class_obj, SM_CLASSFLAG_WITHCHECKOPTION, 1);
8845  }
8846  else if (node->info.create_entity.with_check_option == PT_LOCAL)
8847  {
8848  error = sm_set_class_flag (class_obj, SM_CLASSFLAG_LOCALCHECKOPTION, 1);
8849  }
8850 
8851  comment_node = node->info.create_entity.vclass_comment;
8852  if (comment_node != NULL)
8853  {
8854  assert (comment_node->node_type == PT_VALUE);
8855  comment_str = (char *) comment_node->info.value.data_value.str->bytes;
8856  error = sm_set_class_comment (class_obj, comment_str);
8857  if (error == NO_ERROR)
8858  {
8859  do_flush_class_mop = true;
8860  }
8861  }
8862  break;
8863 
8864  case PT_CLASS:
8865  if (create_like)
8866  {
8867  assert (source_class != NULL);
8868 
8869  if (!reuse_oid && (source_class->flags & SM_CLASSFLAG_REUSE_OID))
8870  {
8871  reuse_oid = true;
8872  }
8873 
8874  tde_algo = (TDE_ALGORITHM) source_class->tde_algorithm;
8875  if (tde_algo != TDE_ALGORITHM_NONE)
8876  {
8877  error = sm_set_class_tde_algorithm (class_obj, tde_algo);
8878  if (error != NO_ERROR)
8879  {
8880  break;
8881  }
8882  do_flush_class_mop = true;
8883  }
8884 
8885  if (source_class->comment)
8886  {
8887  error = sm_set_class_comment (class_obj, source_class->comment);
8888  if (error != NO_ERROR)
8889  {
8890  break;
8891  }
8892  }
8893  }
8894  if (locator_create_heap_if_needed (class_obj, reuse_oid) == NULL)
8895  {
8896  assert (er_errid () != NO_ERROR);
8897  error = er_errid ();
8898  break;
8899  }
8900  if (reuse_oid)
8901  {
8902  error = sm_set_class_flag (class_obj, SM_CLASSFLAG_REUSE_OID, 1);
8903  if (error == NO_ERROR)
8904  {
8905  /* Need to flush class mop in order to reflect reuse_oid flag into catalog table. Without flushing it,
8906  * catalog information is incorrect under non-autocommit mode. */
8907  do_flush_class_mop = true;
8908  }
8909  }
8910  if (tbl_opt_encrypt)
8911  {
8912  encrypt_node = tbl_opt_encrypt->info.table_option.val;
8913  assert (encrypt_node != NULL && encrypt_node->node_type == PT_VALUE
8914  && encrypt_node->type_enum == PT_TYPE_INTEGER);
8915  tde_algo_opt = encrypt_node->info.value.data_value.i;
8916  /*
8917  * -1 means using deafult encryption algorithm.
8918  * Other values but -1, TDE_ALGORITHM_AES, TDE_ALGORITHM_ARIA has been denied by parser.
8919  */
8920  if (tde_algo_opt == -1)
8921  {
8923  }
8924  else
8925  {
8926  tde_algo = (TDE_ALGORITHM) tde_algo_opt;
8927  }
8928  error = sm_set_class_tde_algorithm (class_obj, tde_algo);
8929  if (error != NO_ERROR)
8930  {
8931  break;
8932  }
8933  do_flush_class_mop = true;
8934  }
8935  error = sm_set_class_collation (class_obj, collation_id);
8936  if (error != NO_ERROR)
8937  {
8938  break;
8939  }
8940  if (tbl_opt_comment)
8941  {
8942  comment_node = tbl_opt_comment->info.table_option.val;
8943  assert (comment_node != NULL && comment_node->node_type == PT_VALUE);
8944  comment = comment_node->info.value.data_value.str;
8945  error = sm_set_class_comment (class_obj, (char *) pt_get_varchar_bytes (comment));
8946  if (error == NO_ERROR)
8947  {
8948  do_flush_class_mop = true;
8949  }
8950  }
8951  break;
8952 
8953  default:
8954  break;
8955  }
8956 
8957  if (do_flush_class_mop == true)
8958  {
8959  assert (error == NO_ERROR);
8960  assert (class_obj != NULL);
8961 
8962  error = locator_flush_class (class_obj);
8963  }
8964 
8965  if (error != NO_ERROR)
8966  {
8967  goto error_exit;
8968  }
8969 
8970  if (node->info.create_entity.partition_info != NULL)
8971  {
8973 
8974  info.keycol[0] = 0;
8975  info.promoted_count = 0;
8976  info.promoted_names = NULL;
8977  info.root_tmpl = NULL;
8978  info.root_op = class_obj;
8979 
8980  error = do_create_partition (parser, node, &info);
8981  if (error != NO_ERROR)
8982  {
8983  if (error == ER_LK_UNILATERALLY_ABORTED)
8984  {
8985  do_rollback_on_error = false;
8986  }
8987  goto error_exit;
8988  }
8989  }
8990  if (create_like)
8991  {
8992  error = do_copy_indexes (parser, class_obj, source_class);
8993  if (error != NO_ERROR)
8994  {
8995  goto error_exit;
8996  }
8997  }
8998 
8999  if (create_select)
9000  {
9001  error =
9002  execute_create_select_query (parser, class_name, create_select, node->info.create_entity.create_select_action,
9003  query_columns, node);
9004  if (error != NO_ERROR)
9005  {
9006  goto error_exit;
9007  }
9008 
9009  db_free_query_format (query_columns);
9010  query_columns = NULL;
9011  }
9012  assert (query_columns == NULL);
9013 
9014  for (create_index = node->info.create_entity.create_index; create_index != NULL; create_index = create_index->next)
9015  {
9016  PT_NODE *save_next = NULL;
9017 
9018  create_index->info.index.indexed_class = pt_entity (parser, node->info.create_entity.entity_name, NULL, NULL);
9019 
9020  if (create_index->info.index.indexed_class == NULL)
9021  {
9022  error = ER_FAILED;
9023  goto error_exit;
9024  }
9025 
9026  save_next = create_index->next;
9027  create_index->next = NULL;
9028  pt_semantic_check (parser, create_index);
9029  if (pt_has_error (parser))
9030  {
9031  pt_report_to_ersys (parser, PT_SEMANTIC);
9032  error = er_errid ();
9033  goto error_exit;
9034  }
9035  create_index->next = save_next;
9036 
9037  error = do_create_index (parser, create_index);
9038  if (error != NO_ERROR)
9039  {
9040  goto error_exit;
9041  }
9042  }
9043 
9044  if (tde_algo != TDE_ALGORITHM_NONE)
9045  {
9046  error = file_apply_tde_to_class_files (&class_obj->oid_info.oid);
9047  if (error != NO_ERROR)
9048  {
9049  goto error_exit;
9050  }
9051  }
9052 
9053  return error;
9054 
9055 error_exit:
9056  if (query_columns != NULL)
9057  {
9058  db_free_query_format (query_columns);
9059  query_columns = NULL;
9060  }
9061  if (do_abort_class_on_error)
9062  {
9063  (void) dbt_abort_class (ctemplate);
9064  }
9065  if (do_rollback_on_error && error != ER_LK_UNILATERALLY_ABORTED)
9066  {
9068  }
9069 
9070  return error;
9071 }
9072 
9073 /*
9074  * do_recreate_renamed_class_indexes() - Recreate indexes of previously
9075  * renamed class
9076  * return: NO_ERROR on success, non-zero for ERROR
9077  * parser(in): Parser context
9078  * old_class_name(in): the old name of the renamed class
9079  * class_name(in): the new name of the renamed class
9080  *
9081  * Note : This function must be called after class renaming.
9082  * Currently, only filter and function index are recreated since
9083  * their expression must be modified and recompiled.
9084  */
9085 static int
9086 do_recreate_renamed_class_indexes (const PARSER_CONTEXT * parser, const char *const old_class_name,
9087  const char *const class_name)
9088 {
9089  int error = NO_ERROR;
9091  SM_CONSTRAINT_INFO *index_save_info = NULL, *saved = NULL;
9092  SM_CLASS *class_ = NULL;
9093  DB_OBJECT *classmop = NULL;
9094 
9095  assert (parser != NULL && old_class_name != NULL && class_name != NULL);
9096 
9097  classmop = db_find_class (class_name);
9098  if (classmop == NULL)
9099  {
9100  assert (er_errid () != NO_ERROR);
9101  return er_errid ();
9102  }
9103 
9104  if (au_fetch_class (classmop, &class_, AU_FETCH_READ, DB_AUTH_SELECT) != NO_ERROR)
9105  {
9106  assert (er_errid () != NO_ERROR);
9107  return er_errid ();
9108  }
9109 
9110  if (class_->constraints == NULL)
9111  {
9112  /* no constraints, nothing to do */
9113  return NO_ERROR;
9114  }
9115 
9116  if (class_->class_type != SM_CLASS_CT)
9117  {
9118  return ER_OBJ_NOT_A_CLASS;
9119  }
9120 
9121  for (c = class_->constraints; c; c = c->next)
9122  {
9125  {
9126  continue;
9127  }
9128 
9129  if (c->func_index_info || c->filter_predicate)
9130  {
9131  /* save constraints */
9132  error = sm_save_constraint_info (&index_save_info, c);
9133  if (error == NO_ERROR)
9134  {
9135  assert (index_save_info != NULL);
9136  saved = index_save_info;
9137  while (saved->next)
9138  {
9139  saved = saved->next;
9140  }
9141  if (c->func_index_info)
9142  {
9143  /* recompile function index expression */
9144  error =
9145  do_recreate_func_index_constr ((PARSER_CONTEXT *) parser, saved, NULL, NULL, old_class_name,
9146  sm_ch_name ((MOBJ) class_));
9147  if (error != NO_ERROR)
9148  {
9149  goto error_exit;
9150  }
9151  }
9152  else
9153  {
9154  /* recompile filter index expression */
9155  error =
9156  do_recreate_filter_index_constr ((PARSER_CONTEXT *) parser, saved->filter_predicate, NULL,
9157  old_class_name, sm_ch_name ((MOBJ) class_));
9158  if (error != NO_ERROR)
9159  {
9160  goto error_exit;
9161  }
9162  }
9163  }
9164  }
9165  }
9166 
9167  /* drop indexes */
9168  for (saved = index_save_info; saved != NULL; saved = saved->next)
9169  {
9170  if (SM_IS_CONSTRAINT_UNIQUE_FAMILY ((SM_CONSTRAINT_TYPE) saved->constraint_type))
9171  {
9172  error =
9173  sm_drop_constraint (classmop, saved->constraint_type, saved->name, (const char **) saved->att_names, false,
9174  false);
9175  if (error != NO_ERROR)
9176  {
9177  goto error_exit;
9178  }
9179  }
9180  else
9181  {
9182  error = sm_drop_index (classmop, saved->name);
9183  if (error != NO_ERROR)
9184  {
9185  goto error_exit;
9186  }
9187  }
9188  }
9189 
9190  /* add indexes */
9191  for (saved = index_save_info; saved != NULL; saved = saved->next)
9192  {
9193  error = sm_add_constraint (classmop, saved->constraint_type, saved->name, (const char **) saved->att_names,
9194  saved->asc_desc, saved->prefix_length, false, saved->filter_predicate,
9195  saved->func_index_info, saved->comment, saved->index_status);
9196 
9197  if (error != NO_ERROR)
9198  {
9199  goto error_exit;
9200  }
9201  }
9202 
9203  if (index_save_info != NULL)
9204  {
9205  sm_free_constraint_info (&index_save_info);
9206  }
9207 
9208  return NO_ERROR;
9209 
9210 error_exit:
9211 
9212  if (index_save_info != NULL)
9213  {
9214  sm_free_constraint_info (&index_save_info);
9215  }
9216 
9217  return error;
9218 }
9219 
9220 /*
9221  * do_copy_indexes() - Copies all the indexes of a given class to another
9222  * class.
9223  * return: NO_ERROR on success, non-zero for ERROR
9224  * parser(in): Parser context
9225  * classmop(in): the class to copy the indexes to
9226  * class_(in): the class to copy the indexes from
9227  */
9228 static int
9229 do_copy_indexes (PARSER_CONTEXT * parser, MOP classmop, SM_CLASS * src_class)
9230 {
9231  int error = NO_ERROR;
9232  const char **att_names = NULL;
9234  char *new_cons_name = NULL;
9235  SM_CONSTRAINT_INFO *index_save_info = NULL;
9236  DB_CONSTRAINT_TYPE constraint_type;
9237  int free_constraint = 0;
9238  const char *class_name = NULL;
9239 
9240  assert (src_class != NULL);
9241 
9242  if (src_class->constraints == NULL)
9243  {
9244  return NO_ERROR;
9245  }
9246 
9247  for (c = src_class->constraints; c; c = c->next)
9248  {
9250  {
9251  /* These should have been copied already. */
9252  continue;
9253  }
9254 
9255  att_names = classobj_point_at_att_names (c, NULL);
9256  if (att_names == NULL)
9257  {
9258  assert (er_errid () != NO_ERROR);
9259  return er_errid ();
9260  }
9261 
9262  constraint_type = db_constraint_type (c);
9263  new_cons_name = (char *) c->name;
9264 
9266  {
9267  /* we need to recompile the expression need for function index */
9268  error = sm_save_constraint_info (&index_save_info, c);
9269  if (error != NO_ERROR)
9270  {
9271  goto exit_on_error;
9272  }
9273 
9274  free_constraint = 1;
9275  class_name = sm_get_ch_name (classmop);
9276  if (class_name == NULL)
9277  {
9278  assert (er_errid () != NO_ERROR);
9279  error = er_errid ();
9280  goto exit_on_error;
9281  }
9282 
9283  if (c->func_index_info)
9284  {
9285  error =
9286  do_recreate_func_index_constr (parser, index_save_info, NULL, NULL, sm_ch_name ((MOBJ) src_class),
9287  class_name);
9288  }
9289  else
9290  {
9291  /* filter index predicate available */
9292  error =
9293  do_recreate_filter_index_constr (parser, index_save_info->filter_predicate, NULL,
9294  sm_ch_name ((MOBJ) src_class), class_name);
9295  }
9296 
9297  if (error != NO_ERROR)
9298  {
9299  goto exit_on_error;
9300  }
9301  }
9302 
9303  if (c->func_index_info || c->filter_predicate)
9304  {
9305  error = sm_add_constraint (classmop, constraint_type, new_cons_name, att_names, index_save_info->asc_desc,
9306  index_save_info->prefix_length, false, index_save_info->filter_predicate,
9307  index_save_info->func_index_info, index_save_info->comment,
9308  index_save_info->index_status);
9309  }
9310  else
9311  {
9312  error =
9313  sm_add_constraint (classmop, constraint_type, new_cons_name, att_names, c->asc_desc, c->attrs_prefix_length,
9314  false, c->filter_predicate, c->func_index_info, c->comment, c->index_status);
9315  }
9316  if (error != NO_ERROR)
9317  {
9318  goto exit_on_error;
9319  }
9320 
9321  free_and_init (att_names);
9322 
9323  if (new_cons_name != NULL && new_cons_name != c->name)
9324  {
9325  free_and_init (new_cons_name);
9326  }
9327 
9328  if (free_constraint)
9329  {
9330  sm_free_constraint_info (&index_save_info);
9331  }
9332  free_constraint = 0;
9333  }
9334 
9335  return error;
9336 
9337 exit_on_error:
9338 
9339  free_and_init (att_names);
9340 
9341  if (new_cons_name != NULL && new_cons_name != c->name)
9342  {
9343  free_and_init (new_cons_name);
9344  }
9345 
9346  if (free_constraint)
9347  {
9348  sm_free_constraint_info (&index_save_info);
9349  }
9350 
9351  return error;
9352 }
9353 
9354 
9355 
9356 
9357 
9358 /*
9359  * Function Group :
9360  * Code for truncating Classes by Parse Tree descriptions.
9361  *
9362  */
9363 
9364 static int truncate_class_name (const char *name);
9365 
9366 /*
9367  * truncate_class_name() - This static routine truncates a class by name.
9368  * return: Error code
9369  * name(in): Class name to truncate
9370  */
9371 static int
9372 truncate_class_name (const char *name)
9373 {
9374  DB_OBJECT *class_mop;
9375 
9376  class_mop = db_find_class (name);
9377 
9378  if (class_mop)
9379  {
9380  return db_truncate_class (class_mop);
9381  }
9382  else
9383  {
9384  /* if class is null, return the global error. */
9385  assert (er_errid () != NO_ERROR);
9386  return er_errid ();
9387  }
9388 }
9389 
9390 /*
9391  * do_truncate() - Truncates a class
9392  * return: Error code if truncation fails.
9393  * parser(in): Parser context
9394  * statement(in/out): Parse tree of the statement
9395  */
9396 int
9397 do_truncate (PARSER_CONTEXT * parser, PT_NODE * statement)
9398 {
9399  int error = NO_ERROR;
9400  PT_NODE *entity_spec = NULL;
9401  PT_NODE *entity = NULL;
9402  PT_NODE *entity_list = NULL;
9403 
9405 
9406  entity_spec = statement->info.truncate.spec;
9407  if (entity_spec == NULL)
9408  {
9409  return NO_ERROR;
9410  }
9411 
9412  entity_list = entity_spec->info.spec.flat_entity_list;
9413  for (entity = entity_list; entity != NULL; entity = entity->next)
9414  {
9415  /* partitioned sub-class check */
9417  {
9419  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
9420  return error;
9421  }
9422  }
9423 
9425  if (error != NO_ERROR)
9426  {
9427  return error;
9428  }
9429 
9430  for (entity = entity_list; entity != NULL; entity = entity->next)
9431  {
9432  error = truncate_class_name (entity->info.name.original);
9433  if (error != NO_ERROR)
9434  {
9435  if (error != ER_LK_UNILATERALLY_ABORTED)
9436  {
9438  }
9439 
9440  return error;
9441  }
9442  }
9443 
9444  return error;
9445 }
9446 
9447 /*
9448  * do_alter_clause_change_attribute() - Executes an ALTER CHANGE or
9449  * ALTER MODIFY clause
9450  * return: Error code
9451  * parser(in): Parser context
9452  * alter(in/out): Parse tree of a PT_RENAME_ENTITY clause potentially
9453  * followed by the rest of the clauses in the ALTER
9454  * statement.
9455  */
9456 static int
9458 {
9459  int error = NO_ERROR;
9460  const PT_ALTER_CODE alter_code = alter->info.alter.code;
9461  const char *entity_name = NULL;
9463  DB_CTMPL *ctemplate = NULL;
9465  SM_ATTR_PROP_CHG attr_chg_prop;
9466  bool tran_saved = false;
9467  MOP class_mop = NULL;
9468  OID *usr_oid_array = NULL;
9469  int user_count = 0;
9470  int i;
9471  bool has_partitions = false;
9472  bool is_srv_update_needed = false;
9473  OID class_oid;
9474  int att_id = -1;
9475 
9476  assert (alter_code == PT_CHANGE_ATTR);
9477  assert (alter->info.alter.super.resolution_list == NULL);
9478 
9479  OID_SET_NULL (&class_oid);
9480  reset_att_property_structure (&attr_chg_prop);
9481 
9482  entity_name = alter->info.alter.entity_name->info.name.original;
9483  if (entity_name == NULL)
9484  {
9485  error = ER_UNEXPECTED;
9486  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Expecting a class or virtual class name.");
9487  goto exit;
9488  }
9489 
9490  class_obj = db_find_class (entity_name);
9491  if (class_obj == NULL)
9492  {
9493  assert (er_errid () != NO_ERROR);
9494  error = er_errid ();
9495  goto exit;
9496  }
9497 
9498  error = locator_flush_class (class_obj);
9499  if (error != NO_ERROR)
9500  {
9501  /* don't overwrite error */
9502  goto exit;
9503  }
9504 
9505  /* force exclusive lock on class, even though it should have been already acquired */
9506  if (locator_fetch_class (class_obj, DB_FETCH_WRITE) == NULL)
9507  {
9508  error = ER_FAILED;
9509  goto exit;
9510  }
9511 
9512  ctemplate = dbt_edit_class (class_obj);
9513  if (ctemplate == NULL)
9514  {
9515  /* when dbt_edit_class fails (e.g. because the server unilaterally aborts us), we must record the associated
9516  * error message into the parser. Otherwise, we may get a confusing error msg of the form: "so_and_so is not a
9517  * class". */
9518  pt_record_error (parser, parser->statement_number - 1, alter->line_number, alter->column_number, er_msg (), NULL);
9519  error = er_errid ();
9520  goto exit;
9521  }
9522 
9523  /* this ALTER CHANGE syntax supports only one attribute change per ALTER clause */
9524  assert (alter->info.alter.alter_clause.attr_mthd.mthd_def_list == NULL);
9525  assert (alter->info.alter.alter_clause.attr_mthd.attr_def_list->next == NULL);
9526 
9527  error =
9528  check_change_attribute (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.attr_def_list,
9529  alter->info.alter.alter_clause.attr_mthd.attr_old_name,
9530  &(alter->info.alter.constraint_list), &attr_chg_prop, &change_mode);
9531  if (error != NO_ERROR)
9532  {
9533  goto exit;
9534  }
9535 
9536  if (change_mode == SM_ATTR_CHG_NOT_NEEDED)
9537  {
9538  /* nothing to do */
9539  goto exit;
9540  }
9541 
9542  if (ctemplate->current->users != NULL && ctemplate->partition != NULL)
9543  {
9544  DB_OBJLIST *user_list = NULL;
9545 
9546  user_count = ws_list_length ((DB_LIST *) ctemplate->current->users);
9547 
9548  usr_oid_array = (OID *) calloc (user_count, sizeof (OID));
9549  if (usr_oid_array == NULL)
9550  {
9551  error = ER_OUT_OF_VIRTUAL_MEMORY;
9552  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, user_count * sizeof (OID));
9553  goto exit;
9554  }
9555 
9556  for (i = 0, user_list = ctemplate->current->users; i < user_count && user_list != NULL;
9557  i++, user_list = user_list->next)
9558  {
9559  /* copy partition class OID for later use */
9560  COPY_OID (&(usr_oid_array[i]), &(user_list->op->oid_info.oid));
9561 
9562  /* force exclusive lock on class, even though it should have been already acquired */
9563  if (locator_fetch_class (user_list->op, DB_FETCH_WRITE) == NULL)
9564  {
9565  error = ER_FAILED;
9566  goto exit;
9567  }
9568  }
9569  has_partitions = true;
9570  }
9571 
9573  if (error != NO_ERROR)
9574  {
9575  goto exit;
9576  }
9577  tran_saved = true;
9578 
9579  error =
9580  do_change_att_schema_only (parser, ctemplate, alter->info.alter.alter_clause.attr_mthd.attr_def_list,
9581  alter->info.alter.alter_clause.attr_mthd.attr_old_name,
9582  alter->info.alter.constraint_list, &attr_chg_prop, &change_mode);
9583 
9584  if (error != NO_ERROR)
9585  {
9586  goto exit;
9587  }
9588 
9589  /* save class MOP */
9590  class_mop = ctemplate->op;
9591 
9592  /* check foreign key constraints */
9593  error = do_check_fk_constraints (ctemplate, alter->info.alter.constraint_list);
9594  if (error != NO_ERROR)
9595  {
9596  goto exit;
9597  }
9598 
9599  is_srv_update_needed = ((change_mode == SM_ATTR_CHG_WITH_ROW_UPDATE || change_mode == SM_ATTR_CHG_BEST_EFFORT)
9600  && attr_chg_prop.name_space == ID_ATTRIBUTE) ? true : false;
9601  if (is_srv_update_needed)
9602  {
9603  COPY_OID (&class_oid, &(ctemplate->op->oid_info.oid));
9604  att_id = attr_chg_prop.att_id;
9605  }
9606 
9607  /* force schema update to server */
9608  class_obj = dbt_finish_class (ctemplate);
9609  if (class_obj == NULL)
9610  {
9611  assert (er_errid () != NO_ERROR);
9612  error = er_errid ();
9613  goto exit;
9614  }
9615  /* set NULL, avoid 'abort_class' in case of error */
9616  ctemplate = NULL;
9617 
9618  if (attr_chg_prop.constr_info != NULL)
9619  {
9620  SM_CONSTRAINT_INFO *saved_constr = NULL;
9621 
9622  for (saved_constr = attr_chg_prop.constr_info; saved_constr != NULL; saved_constr = saved_constr->next)
9623  {
9624  if (saved_constr->func_index_info || saved_constr->filter_predicate)
9625  {
9626  if (saved_constr->func_index_info)
9627  {
9628  error = do_recreate_func_index_constr (parser, saved_constr, NULL, alter, NULL, NULL);
9629  if (error != NO_ERROR)
9630  {
9631  goto exit;
9632  }
9633  }
9634  if (saved_constr->filter_predicate)
9635  {
9636  error = do_recreate_filter_index_constr (parser, saved_constr->filter_predicate, alter, NULL, NULL);
9637  if (error != NO_ERROR)
9638  {
9639  goto exit;
9640  }
9641  }
9642 
9643  if (!is_srv_update_needed)
9644  {
9645  const char *att_names[2];
9646  PT_NODE *att_old_name = alter->info.alter.alter_clause.attr_mthd.attr_old_name;
9647 
9648  if (att_old_name != NULL)
9649  {
9650  assert (att_old_name->node_type == PT_NAME);
9651  att_names[0] = att_old_name->info.name.original;
9652  att_names[1] = NULL;
9653 
9654  assert (alter->info.alter.alter_clause.attr_mthd.attr_old_name->node_type == PT_NAME);
9655  error =
9656  sm_drop_constraint (class_mop, saved_constr->constraint_type, saved_constr->name, att_names,
9657  false, false);
9658 
9659  if (error != NO_ERROR)
9660  {
9661  goto exit;
9662  }
9663 
9664  error = sm_add_constraint (class_mop, saved_constr->constraint_type, saved_constr->name,
9665  (const char **) saved_constr->att_names, saved_constr->asc_desc,
9666  saved_constr->prefix_length, false, saved_constr->filter_predicate,
9667  saved_constr->func_index_info, saved_constr->comment,
9668  saved_constr->index_status);
9669  if (error != NO_ERROR)
9670  {
9671  goto exit;
9672  }
9673  }
9674  }
9675  }
9676  }
9677  }
9678 
9679  if (is_srv_update_needed || is_att_prop_set (attr_chg_prop.p[P_TYPE], ATT_CHG_TYPE_PREC_INCR))
9680  {
9681  error = do_drop_att_constraints (class_mop, attr_chg_prop.constr_info);
9682  if (error != NO_ERROR)
9683  {
9684  goto exit;
9685  }
9686 
9687  /* perform UPDATE or each row */
9688  if (is_srv_update_needed)
9689  {
9690  assert (att_id >= 0);
9691  assert (!OID_ISNULL (&class_oid));
9692 
9693  if (has_partitions)
9694  {
9695  assert (user_count > 0);
9696  assert (usr_oid_array != NULL);
9697 
9698  for (i = 0; i < user_count; i++)
9699  {
9700  error = do_run_upgrade_instances_domain (parser, &(usr_oid_array[i]), att_id);
9701  if (error != NO_ERROR)
9702  {
9703  goto exit;
9704  }
9705  }
9706  }
9707  else
9708  {
9709  error = do_run_upgrade_instances_domain (parser, &class_oid, att_id);
9710  if (error != NO_ERROR)
9711  {
9712  goto exit;
9713  }
9714  }
9715  }
9716 
9717  error = sort_constr_info_list (&(attr_chg_prop.constr_info));
9718  if (error != NO_ERROR)
9719  {
9720  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "Sorting constraints failed.");
9721  goto exit;
9722  }
9723 
9724  error = do_recreate_att_constraints (class_mop, attr_chg_prop.constr_info);
9725  if (error != NO_ERROR)
9726  {
9727  goto exit;
9728  }
9729  }
9730  else
9731  {
9732  assert (change_mode == SM_ATTR_CHG_ONLY_SCHEMA);
9733  }
9734 
9735  /* create any new constraints: */
9736  if (attr_chg_prop.new_constr_info != NULL)
9737  {
9738  SM_CONSTRAINT_INFO *ci = NULL;
9739 
9740  error = sort_constr_info_list (&(attr_chg_prop.new_constr_info));
9741  if (error != NO_ERROR)
9742  {
9743  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UNEXPECTED, 1, "Sorting constraints failed.");
9744  goto exit;
9745  }
9746 
9747  /* add new constraints */
9748  for (ci = attr_chg_prop.new_constr_info; ci != NULL; ci = ci->next)
9749  {
9751  {
9752  const char *att_name = *(ci->att_names);
9753 
9754  if (alter->info.alter.hint & PT_HINT_SKIP_UPDATE_NULL)
9755  {
9756  error = db_add_constraint (class_mop, ci->constraint_type, NULL, (const char **) ci->att_names, 0);
9757  }
9759  {
9760  char query[SM_MAX_IDENTIFIER_LENGTH * 4 + 36] = { 0 };
9761  const char *class_name = NULL;
9762  const char *hard_default =
9763  get_hard_default_for_type (alter->info.alter.alter_clause.attr_mthd.attr_def_list->type_enum);
9764  int update_rows_count = 0;
9765 
9766  class_name = db_get_class_name (class_mop);
9767  if (class_name == NULL)
9768  {
9769  error = ER_UNEXPECTED;
9770  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Cannot get class name of mop.");
9771  goto exit;
9772  }
9773 
9774  assert (class_name != NULL && att_name != NULL && hard_default != NULL);
9775 
9776  snprintf (query, SM_MAX_IDENTIFIER_LENGTH * 4 + 30, "UPDATE [%s] SET [%s]=%s WHERE [%s] IS NULL",
9777  class_name, att_name, hard_default, att_name);
9778  error = do_run_update_query_for_class (query, class_mop, &update_rows_count);
9779  if (error != NO_ERROR)
9780  {
9781  goto exit;
9782  }
9783 
9784  if (update_rows_count > 0)
9785  {
9787  }
9788  error = db_add_constraint (class_mop, ci->constraint_type, NULL, (const char **) ci->att_names, 0);
9789  }
9790  else
9791  {
9792  error = db_constrain_non_null (class_mop, *(ci->att_names), 0, 1);
9793  }
9794  if (error != NO_ERROR)
9795  {
9796  goto exit;
9797  }
9798  }
9799  else
9800  {
9802 
9803  error = db_add_constraint (class_mop, ci->constraint_type, NULL, (const char **) ci->att_names, 0);
9804  }
9805 
9806  if (error != NO_ERROR)
9807  {
9808  goto exit;
9809  }
9810  }
9811  }
9812 
9813 exit:
9814 
9815  if (ctemplate != NULL)
9816  {
9817  dbt_abort_class (ctemplate);
9818  ctemplate = NULL;
9819  }
9820 
9821  if (error != NO_ERROR && tran_saved && error != ER_LK_UNILATERALLY_ABORTED)
9822  {
9824  }
9825 
9826  if (attr_chg_prop.constr_info != NULL)
9827  {
9828  sm_free_constraint_info (&(attr_chg_prop.constr_info));
9829  }
9830 
9831  if (attr_chg_prop.new_constr_info != NULL)
9832  {
9833  sm_free_constraint_info (&(attr_chg_prop.new_constr_info));
9834  }
9835 
9836  if (usr_oid_array != NULL)
9837  {
9838  free_and_init (usr_oid_array);
9839  }
9840 
9841  return error;
9842 }
9843 
9844 /*
9845  * do_alter_change_owner() - change the owner of a class/vclass
9846  * return: Error code
9847  * parser(in): Parser context
9848  * alter(in/out): Parse tree of a PT_CHANGE_OWNER claus
9849  */
9850 static int
9851 do_alter_change_owner (PARSER_CONTEXT * const parser, PT_NODE * const alter)
9852 {
9853  int error = NO_ERROR;
9854  DB_OBJECT *obj = NULL;
9855  DB_VALUE returnval, class_val, user_val;
9856  PT_NODE *class_, *user;
9857 
9858  assert (alter != NULL);
9859 
9860  class_ = alter->info.alter.entity_name;
9861  assert (class_ != NULL);
9862 
9863  user = alter->info.alter.alter_clause.user.user_name;
9864  assert (user != NULL);
9865 
9866  db_make_null (&returnval);
9867 
9868  db_make_string (&class_val, class_->info.name.original);
9869  db_make_string (&user_val, user->info.name.original);
9870 
9871  au_change_owner_method (obj, &returnval, &class_val, &user_val);
9872 
9873  pr_clear_value (&class_val);
9874  pr_clear_value (&user_val);
9875 
9876  if (DB_VALUE_TYPE (&returnval) == DB_TYPE_ERROR)
9877  {
9878  error = db_get_error (&returnval);
9879  }
9880 
9881  return error;
9882 }
9883 
9884 /*
9885  * do_alter_change_default_cs_coll() - change the default collation of a
9886  * class/vclass
9887  * return: Error code
9888  * parser(in): Parser context
9889  * alter(in/out): Parse tree of a PT_CHANGE_OWNER claus
9890  */
9891 static int
9893 {
9894  int error = NO_ERROR;
9895  const char *entity_name = NULL;
9897  DB_CTMPL *ctemplate = NULL;
9898  PT_ALTER_INFO *alter_info;
9899  bool tran_saved = false;
9900  MOP class_mop = NULL;
9901  OID class_oid;
9902  bool is_chg_needed = false;
9903  int i, collation_id = -1, is_partition = -1;
9904  MOP *sub_partitions = NULL;
9905 
9906  alter_info = &(alter->info.alter);
9907  assert (alter_info->code == PT_CHANGE_COLLATION);
9908 
9909  OID_SET_NULL (&class_oid);
9910 
9911  entity_name = alter_info->entity_name->info.name.original;
9912  if (entity_name == NULL)
9913  {
9914  error = ER_UNEXPECTED;
9915  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Expecting a class or virtual class name.");
9916  goto exit;
9917  }
9918 
9920  if (error != NO_ERROR)
9921  {
9922  goto exit;
9923  }
9924  tran_saved = true;
9925 
9926  class_obj = db_find_class (entity_name);
9927  if (class_obj == NULL)
9928  {
9929  assert (er_errid () != NO_ERROR);
9930  error = er_errid ();
9931  goto exit;
9932  }
9933 
9934  error = locator_flush_class (class_obj);
9935  if (error != NO_ERROR)
9936  {
9937  /* don't overwrite error */
9938  goto exit;
9939  }
9940 
9941  /* get exclusive lock on class */
9942  if (locator_fetch_class (class_obj, DB_FETCH_WRITE) == NULL)
9943  {
9944  error = ER_FAILED;
9945  goto exit;
9946  }
9947 
9948  ctemplate = dbt_edit_class (class_obj);
9949  if (ctemplate == NULL)
9950  {
9951  /* when dbt_edit_class fails (e.g. because the server unilaterally aborts us), we must record the associated
9952  * error message into the parser. Otherwise, we may get a confusing error msg of the form: "so_and_so is not a
9953  * class". */
9954  pt_record_error (parser, parser->statement_number - 1, alter->line_number, alter->column_number, er_msg (), NULL);
9955  error = er_errid ();
9956  goto exit;
9957  }
9958 
9959  error = check_change_class_collation (parser, ctemplate, alter_info, &is_chg_needed, &collation_id);
9960  if (error != NO_ERROR)
9961  {
9962  goto exit;
9963  }
9964 
9965  if (!is_chg_needed)
9966  {
9967  /* nothing to do */
9968  goto exit;
9969  }
9970 
9971  class_mop = ctemplate->op;
9972 
9973  error = sm_set_class_collation (class_mop, collation_id);
9974 
9975  if (error != NO_ERROR)
9976  {
9977  goto exit;
9978  }
9979 
9980  error = sm_partitioned_class_type (class_mop, &is_partition, NULL, &sub_partitions);
9981  if (error != NO_ERROR)
9982  {
9983  goto exit;
9984  }
9985 
9986  if (is_partition == DB_PARTITIONED_CLASS)
9987  {
9988  for (i = 0; sub_partitions[i]; i++)
9989  {
9990  error = sm_set_class_collation (sub_partitions[i], collation_id);
9991  if (error != NO_ERROR)
9992  {
9993  break;
9994  }
9995  }
9996 
9997  if (error != NO_ERROR)
9998  {
9999  goto exit;
10000  }
10001  }
10002 
10003  /* force schema update to server */
10004  class_obj = dbt_finish_class (ctemplate);
10005  if (class_obj == NULL)
10006  {
10007  assert (er_errid () != NO_ERROR);
10008  error = er_errid ();
10009  goto exit;
10010  }
10011  /* set NULL, avoid 'abort_class' in case of error */
10012  ctemplate = NULL;
10013 
10014 exit:
10015 
10016  if (ctemplate != NULL)
10017  {
10018  dbt_abort_class (ctemplate);
10019  ctemplate = NULL;
10020  }
10021 
10022  if (sub_partitions)
10023  {
10024  free_and_init (sub_partitions);
10025  }
10026 
10027  if (error != NO_ERROR && tran_saved && error != ER_LK_UNILATERALLY_ABORTED)
10028  {
10030  }
10031 
10032  return error;
10033 }
10034 
10035 /*
10036  * do_alter_change_tbl_comment() - change the table comment
10037  * return: Error code
10038  * parser(in): Parser context
10039  * alter(in/out): Parse tree of a PT_CHANGE_TABLE_COMMENT clause
10040  */
10041 static int
10042 do_alter_change_tbl_comment (PARSER_CONTEXT * const parser, PT_NODE * const alter)
10043 {
10044  int error = NO_ERROR;
10045  const char *entity_name = NULL;
10047  DB_CTMPL *ctemplate = NULL;
10048  PT_ALTER_INFO *alter_info;
10049  bool tran_saved = false;
10050  MOP class_mop = NULL;
10051  PT_NODE *comment_node = NULL;
10052  PARSER_VARCHAR *comment = NULL;
10053 
10054  alter_info = &(alter->info.alter);
10055  if (alter_info->code == PT_CHANGE_TABLE_COMMENT)
10056  {
10057  comment_node = alter_info->alter_clause.comment.tbl_comment;
10058  }
10059  else if (alter_info->code == PT_RESET_QUERY || alter_info->code == PT_ADD_QUERY
10060  || alter_info->code == PT_MODIFY_QUERY)
10061  {
10062  comment_node = alter_info->alter_clause.query.view_comment;
10063  }
10064  else
10065  {
10066  /*
10067  * code shall be one of the above 4 types, otherwise it's an error.
10068  */
10069  assert (0);
10070  }
10071 
10072  assert (comment_node != NULL && comment_node->node_type == PT_VALUE);
10073 
10074  entity_name = alter_info->entity_name->info.name.original;
10075  if (entity_name == NULL)
10076  {
10077  error = ER_UNEXPECTED;
10078  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Expecting a class or virtual class name.");
10079  goto exit;
10080  }
10081 
10083  if (error != NO_ERROR)
10084  {
10085  goto exit;
10086  }
10087  tran_saved = true;
10088 
10089  class_obj = db_find_class (entity_name);
10090  if (class_obj == NULL)
10091  {
10092  error = er_errid ();
10093  goto exit;
10094  }
10095 
10096  error = locator_flush_class (class_obj);
10097  if (error != NO_ERROR)
10098  {
10099  /* don't overwrite error */
10100  goto exit;
10101  }
10102 
10103  /* get exclusive lock on class */
10104  if (locator_fetch_class (class_obj, DB_FETCH_WRITE) == NULL)
10105  {
10106  error = ER_FAILED;
10107  goto exit;
10108  }
10109 
10110  ctemplate = dbt_edit_class (class_obj);
10111  if (ctemplate == NULL)
10112  {
10113  /* when dbt_edit_class fails (e.g. because the server unilaterally aborts us), we must record the associated
10114  * error message into the parser. Otherwise, we may get a confusing error msg of the form: "so_and_so is not a
10115  * class". */
10116  pt_record_error (parser, parser->statement_number - 1, alter->line_number, alter->column_number, er_msg (), NULL);
10117  error = er_errid ();
10118  goto exit;
10119  }
10120 
10121  class_mop = ctemplate->op;
10122  comment = comment_node->info.value.data_value.str;
10123  error = sm_set_class_comment (class_mop, (char *) pt_get_varchar_bytes (comment));
10124  if (error != NO_ERROR)
10125  {
10126  goto exit;
10127  }
10128 
10129  /* force schema update to server */
10130  class_obj = dbt_finish_class (ctemplate);
10131  if (class_obj == NULL)
10132  {
10133  error = er_errid ();
10134  goto exit;
10135  }
10136  /* set NULL, avoid 'abort_class' in case of error */
10137  ctemplate = NULL;
10138 
10139 exit:
10140  if (ctemplate != NULL)
10141  {
10142  dbt_abort_class (ctemplate);
10143  ctemplate = NULL;
10144  }
10145 
10146  if (error != NO_ERROR && tran_saved && error != ER_LK_UNILATERALLY_ABORTED)
10147  {
10149  }
10150  return error;
10151 }
10152 
10153 /*
10154  * do_alter_change_col_comment() - change the column comment
10155  * return: Error code
10156  * parser(in): Parser context
10157  * alter(in/out): Parse tree of a PT_CHANGE_COLUMN_COMMENT clause
10158  */
10159 static int
10160 do_alter_change_col_comment (PARSER_CONTEXT * const parser, PT_NODE * const alter_node)
10161 {
10162  int error = NO_ERROR;
10163  int meta = 0, shared = 0;
10164  SM_ATTRIBUTE *found_attr = NULL;
10166  const PT_ALTER_CODE alter_code = alter_node->info.alter.code;
10167  const char *entity_name = NULL;
10168  PT_NODE *attr_node = NULL;
10169  const char *attr_name = NULL;
10170  PT_NODE *comment_node = NULL;
10171  PARSER_VARCHAR *comment_str = NULL;
10173  DB_CTMPL *ctemplate = NULL;
10174  MOP class_mop = NULL;
10175  OID class_oid;
10176  bool tran_saved = false;
10177 
10178  assert (alter_code == PT_CHANGE_COLUMN_COMMENT);
10179 
10180  OID_SET_NULL (&class_oid);
10181 
10182  entity_name = alter_node->info.alter.entity_name->info.name.original;
10183  if (entity_name == NULL)
10184  {
10185  error = ER_UNEXPECTED;
10186  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Expecting a class or virtual class name.");
10187  goto exit;
10188  }
10189 
10190  class_obj = db_find_class (entity_name);
10191  if (class_obj == NULL)
10192  {
10193  assert (er_errid () != NO_ERROR);
10194  error = er_errid ();
10195  goto exit;
10196  }
10197 
10198  error = locator_flush_class (class_obj);
10199  if (error != NO_ERROR)
10200  {
10201  /* don't overwrite error */
10202  goto exit;
10203  }
10204 
10205  /* force exclusive lock on class, even though it should have been already acquired */
10206  if (locator_fetch_class (class_obj, DB_FETCH_WRITE) == NULL)
10207  {
10208  error = ER_FAILED;
10209  goto exit;
10210  }
10211 
10212  ctemplate = dbt_edit_class (class_obj);
10213  if (ctemplate == NULL)
10214  {
10215  /* when dbt_edit_class fails (e.g. because the server unilaterally aborts us), we must record the associated
10216  * error message into the parser. Otherwise, we may get a confusing error msg of the form: "so_and_so is not a
10217  * class". */
10218  pt_record_error (parser, parser->statement_number - 1, alter_node->line_number, alter_node->column_number,
10219  er_msg (), NULL);
10220  error = er_errid ();
10221  goto exit;
10222  }
10223 
10225  if (error != NO_ERROR)
10226  {
10227  goto exit;
10228  }
10229  tran_saved = true;
10230 
10231  attr_node = alter_node->info.alter.alter_clause.attr_mthd.attr_def_list;
10232  while (attr_node != NULL)
10233  {
10234  attr_name = get_attr_name (attr_node);
10235 
10236  comment_node = attr_node->info.attr_def.comment;
10237 
10238  assert (comment_node != NULL);
10239  assert (comment_node->node_type == PT_VALUE);
10240 
10241  meta = (attr_node->info.attr_def.attr_type == PT_META_ATTR);
10242  shared = (attr_node->info.attr_def.attr_type == PT_SHARED);
10243  name_space = (meta) ? ID_CLASS_ATTRIBUTE : ((shared) ? ID_SHARED_ATTRIBUTE : ID_ATTRIBUTE);
10244 
10245  /* get the attribute structure */
10246  error = smt_find_attribute (ctemplate, attr_name, (name_space == ID_CLASS_ATTRIBUTE) ? 1 : 0, &found_attr);
10247  if (error != NO_ERROR)
10248  {
10249  goto exit;
10250  }
10251 
10252  assert (found_attr != NULL);
10253 
10254  /* comment */
10255  comment_str = comment_node->info.value.data_value.str;
10256 
10257  ws_free_string_and_init (found_attr->comment);
10258  found_attr->comment = ws_copy_string ((char *) pt_get_varchar_bytes (comment_str));
10259  if (found_attr->comment == NULL && comment_str != NULL)
10260  {
10261  error = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
10262  goto exit;
10263  }
10264 
10265  attr_node = attr_node->next;
10266  }
10267 
10268  /* save class MOP */
10269  class_mop = ctemplate->op;
10270 
10271  /* force schema update to server */
10272  class_obj = dbt_finish_class (ctemplate);
10273  if (class_obj == NULL)
10274  {
10275  assert (er_errid () != NO_ERROR);
10276  error = er_errid ();
10277  goto exit;
10278  }
10279 
10280  /* set NULL, avoid 'abort_class' in case of error */
10281  ctemplate = NULL;
10282 
10283 exit:
10284  if (ctemplate != NULL)
10285  {
10286  dbt_abort_class (ctemplate);
10287  }
10288 
10289  if (error != NO_ERROR && tran_saved && error != ER_LK_UNILATERALLY_ABORTED)
10290  {
10292  }
10293 
10294  return error;
10295 }
10296 
10297 /*
10298  * do_change_att_schema_only() - Change an attribute of a class object
10299  * return: Error code
10300  * parser(in): Parser context
10301  * ctemplate(in/out): Class template
10302  * attribute(in/out): Attribute to add
10303  */
10304 static int
10305 do_change_att_schema_only (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attribute, PT_NODE * old_name_node,
10306  PT_NODE * constraints, SM_ATTR_PROP_CHG * attr_chg_prop, SM_ATTR_CHG_SOL * change_mode)
10307 {
10308  DB_VALUE stack_value;
10309  TP_DOMAIN *attr_db_domain = NULL;
10310  DB_VALUE *new_default = NULL;
10311  DB_VALUE *default_value = &stack_value;
10312  SM_ATTRIBUTE *found_att = NULL;
10313  int error = NO_ERROR;
10314  bool change_first = false;
10315  const char *change_after_attr = NULL;
10316  const char *old_name = NULL;
10317  const char *new_name = NULL;
10318  const char *attr_name = NULL;
10319  PARSER_VARCHAR *comment_str = NULL;
10320  DB_DEFAULT_EXPR new_default_expr;
10321  PT_NODE *comment = NULL;
10322 
10323  assert (attr_chg_prop != NULL);
10324  assert (change_mode != NULL);
10325 
10326  assert (attribute->node_type == PT_ATTR_DEF);
10327 
10328  db_make_null (&stack_value);
10329 
10330  attr_name = get_attr_name (attribute);
10331 
10332  /* get new name */
10333  if (old_name_node != NULL)
10334  {
10335  assert (old_name_node->node_type == PT_NAME);
10336  old_name = old_name_node->info.name.original;
10337  assert (old_name != NULL);
10338 
10339  /* attr_name is supplied using the ATTR_DEF node and it means: for MODIFY syntax : current and unchanged name
10340  * (attr_name) for CHANGE syntax : new name of the attribute (new_name) */
10341  if (is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_DIFF))
10342  {
10343  new_name = attr_name;
10344  attr_name = old_name;
10345  }
10346  else
10347  {
10348  attr_name = old_name;
10349  new_name = NULL;
10350  }
10351  }
10352 
10353  if (validate_attribute_domain (parser, attribute, smt_get_class_type (ctemplate) == SM_CLASS_CT ? true : false))
10354  {
10355  /* validate_attribute_domain() is assumed to issue whatever messages are pertinent. */
10356  error = ER_FAILED;
10357  goto exit;
10358  }
10359 
10360  if (*change_mode == SM_ATTR_CHG_ONLY_SCHEMA)
10361  {
10362  if (attr_chg_prop->name_space == ID_ATTRIBUTE)
10363  {
10365  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_SET_CLS_COMPAT)
10366  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PREC_INCR));
10367  }
10368  else
10369  {
10370  assert (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE || attr_chg_prop->name_space == ID_SHARED_ATTRIBUTE);
10372  && !is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NOT_SUPPORTED));
10373  }
10374 
10375  }
10376  else if (*change_mode == SM_ATTR_CHG_WITH_ROW_UPDATE)
10377  {
10378  assert (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_UPGRADE));
10379  }
10380  else
10381  {
10382  assert (*change_mode == SM_ATTR_CHG_BEST_EFFORT);
10383  /* this mode is needed when: - a type change other than UPGRADE */
10385  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PSEUDO_UPGRADE));
10386  }
10387 
10388  error = check_default_on_update_clause (parser, attribute);
10389  if (error != NO_ERROR)
10390  {
10391  goto exit;
10392  }
10393 
10394  /* default value: for CLASS and SHARED attributes this changes the value itself of the atribute */
10395  error = get_att_default_from_def (parser, attribute, &default_value, NULL);
10396  if (error != NO_ERROR)
10397  {
10398  goto exit;
10399  }
10400  /* default_value is either NULL or pointing to address of stack_value */
10401  assert (default_value == NULL || default_value == &stack_value);
10402  new_default = default_value;
10403  pt_get_default_expression_from_data_default_node (parser, attribute->info.attr_def.data_default, &new_default_expr);
10404 
10405  attr_db_domain = pt_node_to_db_domain (parser, attribute, ctemplate->name);
10406  if (attr_db_domain == NULL)
10407  {
10408  assert (er_errid () != NO_ERROR);
10409  error = er_errid ();
10410  goto exit;
10411  }
10412 
10413  error = get_att_order_from_def (attribute, &change_first, &change_after_attr);
10414  if (error != NO_ERROR)
10415  {
10416  goto exit;
10417  }
10418 
10419  error = smt_change_attribute_w_dflt_w_order (ctemplate, attr_name, new_name, NULL, attr_db_domain,
10420  attr_chg_prop->name_space, new_default, &new_default_expr,
10421  attribute->info.attr_def.on_update, change_first, change_after_attr,
10422  &found_att);
10423  if (error != NO_ERROR)
10424  {
10425  goto exit;
10426  }
10427  if (found_att == NULL)
10428  {
10429  error = ER_UNEXPECTED;
10430  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Attribute not found.");
10431  goto exit;
10432  }
10433 
10434  if (is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_DIFF))
10435  {
10436  assert (new_name != NULL);
10437  attr_name = new_name;
10438  }
10439 
10440  /* save attribute id */
10441  attr_chg_prop->att_id = found_att->id;
10442 
10443  if (attr_chg_prop->name_space != ID_ATTRIBUTE)
10444  {
10445  assert (error == NO_ERROR);
10446  goto exit;
10447  }
10448 
10449  /* processing only for normal attributes */
10450 
10451  /* DEFAULT value */
10452  if (is_att_prop_set (attr_chg_prop->p[P_DEFAULT_VALUE], ATT_CHG_PROPERTY_LOST))
10453  {
10454  pr_clear_value (&(found_att->default_value.value));
10456 
10457  if (found_att->properties != NULL)
10458  {
10459  classobj_drop_prop (found_att->properties, "default_expr");
10460  }
10461  }
10462 
10463  /* on update expression */
10465  {
10467 
10468  if (found_att->properties != NULL)
10469  {
10470  classobj_drop_prop (found_att->properties, "update_default");
10471  }
10472  }
10473 
10474  /* add or drop NOT NULL constraint */
10475  if (is_att_prop_set (attr_chg_prop->p[P_NOT_NULL], ATT_CHG_PROPERTY_GAINED))
10476  {
10477  assert (attribute->info.attr_def.constrain_not_null != 0);
10478  /* constraint is added later when new constraints are created */
10479  }
10480  else if (is_att_prop_set (attr_chg_prop->p[P_NOT_NULL], ATT_CHG_PROPERTY_LOST))
10481  {
10482  error =
10483  dbt_constrain_non_null (ctemplate, attr_name, (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE) ? 1 : 0, 0);
10484  }
10485 
10486 
10487  /* delete or (re-)create auto_increment attribute's serial object */
10488  if (is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_DIFF)
10489  || is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_LOST))
10490  {
10491  /* delete current serial */
10492  int save;
10493  OID *oidp, serial_obj_id;
10494  const char *name = found_att->header.name;
10495 
10496  if (is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_DIFF))
10497  {
10498  name = old_name;
10499  assert (name != NULL);
10500  }
10501 
10502  OID_SET_NULL (&serial_obj_id);
10503 
10504  if (found_att->auto_increment == NULL)
10505  {
10506  char auto_increment_name[AUTO_INCREMENT_SERIAL_NAME_MAX_LENGTH];
10507  MOP serial_class_mop, serial_mop;
10508 
10509  serial_class_mop = sm_find_class (CT_SERIAL_NAME);
10510 
10511  SET_AUTO_INCREMENT_SERIAL_NAME (auto_increment_name, ctemplate->name, name);
10512  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, auto_increment_name);
10513  found_att->auto_increment = serial_mop;
10514  }
10515 
10516  assert_release (found_att->auto_increment);
10517 
10518  error = au_check_serial_authorization (found_att->auto_increment);
10519  if (error != NO_ERROR)
10520  {
10521  goto exit;
10522  }
10523 
10524  if (OID_ISNULL (&serial_obj_id))
10525  {
10526  oidp = ws_identifier (found_att->auto_increment);
10527  COPY_OID (&serial_obj_id, oidp);
10528  }
10529 
10530  AU_DISABLE (save);
10531 
10532  error = obj_delete (found_att->auto_increment);
10533 
10534  AU_ENABLE (save);
10535 
10536  if (error != NO_ERROR)
10537  {
10538  goto exit;
10539  }
10540 
10541  (void) serial_decache (&serial_obj_id);
10542 
10543  found_att->flags &= ~(SM_ATTFLAG_AUTO_INCREMENT);
10544  found_att->auto_increment = NULL;
10545  }
10546 
10547  /* create or re-create serial with new properties */
10548  if (is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_DIFF)
10549  || is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_GAINED))
10550  {
10551  MOP auto_increment_obj = NULL;
10552 
10553  assert (attribute->info.attr_def.auto_increment != NULL);
10554 
10555  error = do_create_auto_increment_serial (parser, &auto_increment_obj, ctemplate->name, attribute);
10556  if (error == NO_ERROR)
10557  {
10558  if (found_att != NULL)
10559  {
10560  found_att->auto_increment = auto_increment_obj;
10561  found_att->flags |= SM_ATTFLAG_AUTO_INCREMENT;
10562  }
10563  }
10564  else
10565  {
10566  goto exit;
10567  }
10568  }
10569 
10570  /* the serial property has not changed, we are only dealing with renaming */
10571  if (is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_DIFF)
10572  && attribute->info.attr_def.auto_increment != NULL
10573  && !is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_DIFF)
10574  && !is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_LOST)
10575  && !is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_GAINED))
10576  {
10577  OID serial_obj_id;
10578 
10579  OID_SET_NULL (&serial_obj_id);
10580 
10581  if (found_att->auto_increment == NULL)
10582  {
10583  char auto_increment_name[AUTO_INCREMENT_SERIAL_NAME_MAX_LENGTH];
10584  MOP serial_class_mop, serial_mop;
10585 
10586  serial_class_mop = sm_find_class (CT_SERIAL_NAME);
10587 
10588  SET_AUTO_INCREMENT_SERIAL_NAME (auto_increment_name, ctemplate->name, old_name);
10589  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, auto_increment_name);
10590  found_att->auto_increment = serial_mop;
10591  }
10592 
10593  assert_release (found_att->auto_increment);
10594 
10595  error = do_update_auto_increment_serial_on_rename (found_att->auto_increment, ctemplate->name, new_name);
10596 
10597  if (error != NO_ERROR)
10598  {
10599  goto exit;
10600  }
10601  }
10602 
10603  /* attribute type changed, and auto_increment is set to use(unchanged), update max_val in db_serial according to new
10604  * type */
10606  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
10607  {
10608  MOP auto_increment_obj = NULL;
10609 
10610  assert (attribute->info.attr_def.auto_increment != NULL);
10611  assert_release (found_att->auto_increment != NULL);
10612 
10613  error = do_update_maxvalue_of_auto_increment_serial (parser, &auto_increment_obj, ctemplate->name, attribute);
10614 
10615  if (error == NO_ERROR)
10616  {
10617  assert_release (auto_increment_obj != NULL);
10618  if (found_att != NULL)
10619  {
10620  found_att->auto_increment = auto_increment_obj;
10621  found_att->flags |= SM_ATTFLAG_AUTO_INCREMENT;
10622  }
10623  }
10624  else
10625  {
10626  goto exit;
10627  }
10628  }
10629 
10630  if (is_att_prop_set (attr_chg_prop->p[P_COMMENT], ATT_CHG_PROPERTY_DIFF))
10631  {
10632  comment = attribute->info.attr_def.comment;
10633  assert (comment != NULL && comment->node_type == PT_VALUE);
10634  comment_str = comment->info.value.data_value.str;
10635  found_att->comment = ws_copy_string ((char *) pt_get_varchar_bytes (comment_str));
10636  if (found_att->comment == NULL)
10637  {
10638  error = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
10639  goto exit;
10640  }
10641  }
10642  else if (is_att_prop_set (attr_chg_prop->p[P_COMMENT], ATT_CHG_PROPERTY_LOST))
10643  {
10644  if (found_att->comment != NULL)
10645  {
10646  ws_free_string (found_att->comment);
10647  found_att->comment = NULL;
10648  }
10649  }
10650 
10651  assert (attr_chg_prop->name_space == ID_ATTRIBUTE);
10652 
10653 exit:
10654  db_value_clear (&stack_value);
10655  return error;
10656 }
10657 
10658 /*
10659  * build_attr_change_map() - This builds a map of changes on the attribute
10660  * return: Error code
10661  * parser(in): Parser context
10662  * ctemplate(in): Class template
10663  * attr_def(in): New attribute definition (PT_NODE : PT_ATTR_DEF)
10664  * attr_old_name(in): Old name of attribute (PT_NODE : PT_NAME)
10665  * constraints(in): New constraints for class template
10666  * (PT_NODE : PT_CONSTRAINT)
10667  * attr_chg_properties(out): map of attribute changes to build
10668  *
10669  */
10670 static int
10671 build_attr_change_map (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attr_def, PT_NODE * attr_old_name,
10672  PT_NODE * constraints, SM_ATTR_PROP_CHG * attr_chg_properties)
10673 {
10674  TP_DOMAIN *attr_db_domain = NULL;
10675  SM_ATTRIBUTE *att = NULL;
10676  SM_CLASS_CONSTRAINT *sm_cls_constr = NULL;
10677  PT_NODE *cnstr = NULL;
10678  const char *attr_name = NULL;
10679  const char *old_name = NULL;
10680  const char *new_name = NULL;
10681  int error = NO_ERROR;
10682  PT_NODE *comment;
10683 
10684  attr_name = get_attr_name (attr_def);
10685 
10686  /* attribute name */
10687  attr_chg_properties->p[P_NAME] = 0;
10688  attr_chg_properties->p[P_NAME] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10689  if (attr_old_name != NULL)
10690  {
10691  assert (attr_old_name->node_type == PT_NAME);
10692  old_name = attr_old_name->info.name.original;
10693  assert (old_name != NULL);
10694 
10695  /* attr_name is supplied using the ATTR_DEF node and it means: for MODIFY syntax : current and unchanged node
10696  * (attr_name) for CHANGE syntax : new name of the attribute (new_name) */
10697  new_name = attr_name;
10698  attr_name = old_name;
10699 
10700  attr_chg_properties->p[P_NAME] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10701  if (intl_identifier_casecmp (attr_name, new_name) == 0)
10702  {
10703  attr_chg_properties->p[P_NAME] |= ATT_CHG_PROPERTY_UNCHANGED;
10704  }
10705  else
10706  {
10707  attr_chg_properties->p[P_NAME] |= ATT_CHG_PROPERTY_DIFF;
10708  }
10709  }
10710  else
10711  {
10712  attr_chg_properties->p[P_NAME] |= ATT_CHG_PROPERTY_UNCHANGED;
10713  }
10714 
10715  /* at this point, attr_name is the current name of the attribute, new_name is either the desired new name or NULL, if
10716  * name change is not requested */
10717 
10718  /* get the attribute structure */
10719  error =
10720  smt_find_attribute (ctemplate, attr_name, (attr_chg_properties->name_space == ID_CLASS_ATTRIBUTE) ? 1 : 0, &att);
10721  if (error != NO_ERROR)
10722  {
10723  return error;
10724  }
10725 
10726  assert (att != NULL);
10727 
10728  attr_chg_properties->name_space = att->header.name_space;
10729 
10730  if (attr_def->info.attr_def.attr_type == PT_NORMAL)
10731  {
10732  attr_chg_properties->new_name_space = ID_ATTRIBUTE;
10733  }
10734  else if (attr_def->info.attr_def.attr_type == PT_SHARED)
10735  {
10736  attr_chg_properties->new_name_space = ID_SHARED_ATTRIBUTE;
10737  }
10738 
10739  if (attr_def->info.attr_def.data_default != NULL)
10740  {
10742  {
10743  attr_chg_properties->new_name_space = ID_SHARED_ATTRIBUTE;
10744  }
10745  }
10746 
10747  /* DEFAULT value */
10748  attr_chg_properties->p[P_DEFAULT_VALUE] = 0;
10749  if (attr_def->info.attr_def.data_default != NULL)
10750  {
10751  attr_chg_properties->p[P_DEFAULT_VALUE] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10752  }
10755  {
10756  attr_chg_properties->p[P_DEFAULT_VALUE] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10757  }
10758 
10759  /* ON UPDATE expr */
10760  attr_chg_properties->p[P_ON_UPDATE_EXPR] = 0;
10761  if (attr_def->info.attr_def.on_update != DB_DEFAULT_NONE)
10762  {
10763  attr_chg_properties->p[P_ON_UPDATE_EXPR] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10764  }
10766  {
10767  attr_chg_properties->p[P_ON_UPDATE_EXPR] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10768  }
10769 
10770  /* DEFFERABLE : not supported, just mark as checked */
10771  attr_chg_properties->p[P_DEFFERABLE] = 0;
10772 
10773  /* ORDERING */
10774  attr_chg_properties->p[P_ORDER] = 0;
10775  if (attr_def->info.attr_def.ordering_info != NULL)
10776  {
10777  attr_chg_properties->p[P_ORDER] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10778  }
10779 
10780  /* AUTO INCREMENT */
10781  attr_chg_properties->p[P_AUTO_INCR] = 0;
10782  if (attr_def->info.attr_def.auto_increment != NULL)
10783  {
10784  attr_chg_properties->p[P_AUTO_INCR] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10785  }
10786  if (att->flags & SM_ATTFLAG_AUTO_INCREMENT)
10787  {
10788  attr_chg_properties->p[P_AUTO_INCR] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10789  }
10790 
10791  /* existing FOREIGN KEY (referencing) */
10792  attr_chg_properties->p[P_CONSTR_FK] = 0;
10793  if (att->flags & SM_ATTFLAG_FOREIGN_KEY)
10794  {
10795  attr_chg_properties->p[P_CONSTR_FK] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10796  }
10797 
10798  /* existing PRIMARY KEY: mark as checked */
10799  attr_chg_properties->p[P_S_CONSTR_PK] = 0;
10800  attr_chg_properties->p[P_M_CONSTR_PK] = 0;
10801 
10802  /* existing non-unique INDEX ? */
10803  attr_chg_properties->p[P_CONSTR_NON_UNI] = 0;
10804  if (att->flags & SM_ATTFLAG_INDEX)
10805  {
10806  attr_chg_properties->p[P_CONSTR_NON_UNI] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10807  }
10808 
10809  /* prefix index */
10810  attr_chg_properties->p[P_PREFIX_INDEX] = 0;
10811 
10812  /* constraint : NOT NULL */
10813  attr_chg_properties->p[P_NOT_NULL] = 0;
10814  if (att->flags & SM_ATTFLAG_NON_NULL)
10815  {
10816  attr_chg_properties->p[P_NOT_NULL] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10817  }
10818 
10819  /* constraint CHECK : not supported, just mark as checked */
10820  attr_chg_properties->p[P_CONSTR_CHECK] = 0;
10821 
10822  /* check for existing constraints: FK referenced, unique, non-unique idx */
10823  if (ctemplate->current != NULL)
10824  {
10825  const char *attr_name_to_check = attr_name;
10826 
10827  attr_chg_properties->p[P_S_CONSTR_UNI] = 0;
10828  attr_chg_properties->p[P_M_CONSTR_UNI] = 0;
10829 
10830  for (sm_cls_constr = ctemplate->current->constraints; sm_cls_constr != NULL; sm_cls_constr = sm_cls_constr->next)
10831  {
10832  /* check if attribute is contained in this constraint */
10833  SM_ATTRIBUTE **sm_constr_attr = sm_cls_constr->attributes;
10834  int nb_att_in_constr = 0;
10835  int attr_name_found_at = -1;
10836 
10837  while (*sm_constr_attr != NULL)
10838  {
10839  if ((*sm_constr_attr)->header.name != NULL
10840  && (*sm_constr_attr)->header.name_space == att->header.name_space
10841  && !intl_identifier_casecmp ((*sm_constr_attr)->header.name, attr_name_to_check))
10842  {
10843  attr_name_found_at = nb_att_in_constr;
10844  }
10845  sm_constr_attr++;
10846  nb_att_in_constr++;
10847  }
10848 
10849  if (attr_name_found_at != -1)
10850  {
10851  bool save_constr = false;
10852 
10853  /* referenced FK */
10854  if (sm_cls_constr->fk_info != NULL)
10855  {
10856  assert (sm_cls_constr->fk_info->name != NULL);
10857  attr_chg_properties->p[P_CONSTR_FK] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10858  }
10859 
10860  /* PRIMARY KEY */
10861  if (sm_cls_constr->type == SM_CONSTRAINT_PRIMARY_KEY)
10862  {
10863  assert (nb_att_in_constr >= 1);
10864  if (nb_att_in_constr >= 2)
10865  {
10866  attr_chg_properties->p[P_M_CONSTR_PK] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10867  }
10868  else
10869  {
10870  attr_chg_properties->p[P_S_CONSTR_PK] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10871  }
10872  attr_chg_properties->p[P_NOT_NULL] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10873  save_constr = true;
10874  }
10875  /* non-unique index */
10876  else if (sm_cls_constr->type == SM_CONSTRAINT_INDEX || sm_cls_constr->type == SM_CONSTRAINT_REVERSE_INDEX)
10877  {
10878  assert (nb_att_in_constr >= 1);
10879  attr_chg_properties->p[P_CONSTR_NON_UNI] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10880  save_constr = true;
10881 
10882  if (sm_cls_constr->attrs_prefix_length != NULL
10883  && sm_cls_constr->attrs_prefix_length[attr_name_found_at] != -1)
10884  {
10885  attr_chg_properties->p[P_PREFIX_INDEX] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10886  }
10887  }
10888  /* UNIQUE */
10889  else if (sm_cls_constr->type == SM_CONSTRAINT_UNIQUE
10890  || sm_cls_constr->type == SM_CONSTRAINT_REVERSE_UNIQUE)
10891  {
10892  assert (nb_att_in_constr >= 1);
10893  if (nb_att_in_constr >= 2)
10894  {
10895  attr_chg_properties->p[P_M_CONSTR_UNI] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10896  }
10897  else
10898  {
10899  attr_chg_properties->p[P_S_CONSTR_UNI] |= ATT_CHG_PROPERTY_PRESENT_OLD;
10900  }
10901  save_constr = true;
10902  }
10903 
10904  if (save_constr)
10905  {
10906  assert (attr_chg_properties->name_space == ID_ATTRIBUTE);
10907 
10908  error = sm_save_constraint_info (&(attr_chg_properties->constr_info), sm_cls_constr);
10909  if (error != NO_ERROR)
10910  {
10911  return error;
10912  }
10913  }
10914  }
10915  }
10916  }
10917  else
10918  {
10919  error = ER_OBJ_TEMPLATE_INTERNAL;
10920  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
10921  return error;
10922  }
10923 
10924  /* attribute is saved in constraints info with the old name; replace all occurences with the new name; constraints
10925  * names are not adjusted to reflect new attribute name, but are kept with the old name, reason: MySQL compatibility */
10926  if ((new_name != NULL) && (attr_name != NULL) && (attr_chg_properties->constr_info != NULL)
10927  && (intl_identifier_casecmp (new_name, attr_name) != 0))
10928  {
10929  SM_CONSTRAINT_INFO *saved_constr = NULL;
10930 
10931  for (saved_constr = attr_chg_properties->constr_info; saved_constr != NULL; saved_constr = saved_constr->next)
10932  {
10933  char **c_name = NULL;
10934  for (c_name = saved_constr->att_names; *c_name != NULL; ++c_name)
10935  {
10936  if (intl_identifier_casecmp (attr_name, *c_name) == 0)
10937  {
10938  free_and_init (*c_name);
10939  *c_name = strdup (new_name);
10940  if (*c_name == NULL)
10941  {
10943  (strlen (new_name) + 1) * sizeof (char));
10944  return ER_OUT_OF_VIRTUAL_MEMORY;
10945  }
10946  }
10947  }
10948  }
10949  }
10950 
10951  /* check for constraints in the new attribute definition */
10952  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
10953  {
10954  PT_NODE *constr_att = NULL;
10955  PT_NODE *constr_att_list = NULL;
10956  bool save_pt_costraint = false;
10957  int chg_prop_idx = NUM_ATT_CHG_PROP;
10958  const char *attr_name_to_check = attr_name;
10959 
10960  if (is_att_prop_set (attr_chg_properties->p[P_NAME], ATT_CHG_PROPERTY_DIFF))
10961  {
10962  attr_name_to_check = new_name;
10963  }
10964 
10965  assert (cnstr->node_type == PT_CONSTRAINT);
10966  switch (cnstr->info.constraint.type)
10967  {
10969  constr_att_list = cnstr->info.constraint.un.foreign_key.attrs;
10970  chg_prop_idx = P_CONSTR_FK;
10971  break;
10973  constr_att_list = cnstr->info.constraint.un.primary_key.attrs;
10974  chg_prop_idx = P_S_CONSTR_PK;
10975  save_pt_costraint = true;
10976  break;
10977  case PT_CONSTRAIN_UNIQUE:
10978  constr_att_list = cnstr->info.constraint.un.unique.attrs;
10979  chg_prop_idx = P_S_CONSTR_UNI;
10980  save_pt_costraint = true;
10981  break;
10982  case PT_CONSTRAIN_NOT_NULL:
10983  constr_att_list = cnstr->info.constraint.un.not_null.attr;
10984  chg_prop_idx = P_NOT_NULL;
10985  save_pt_costraint = true;
10986  break;
10987  case PT_CONSTRAIN_CHECK:
10988  /* not supported, just mark as 'PRESENT' */
10989  assert (false);
10990  attr_chg_properties->p[P_CONSTR_CHECK] |= ATT_CHG_PROPERTY_PRESENT_NEW;
10991  continue;
10992  default:
10993  assert (false);
10994  }
10995 
10996  for (constr_att = constr_att_list; constr_att != NULL; constr_att = constr_att->next)
10997  {
10998  assert (constr_att->node_type == PT_NAME);
10999  if (intl_identifier_casecmp (attr_name_to_check, constr_att->info.name.original) == 0)
11000  {
11001  if (chg_prop_idx >= NUM_ATT_CHG_PROP)
11002  {
11003  continue;
11004  }
11005 
11006  assert (chg_prop_idx < NUM_ATT_CHG_PROP);
11007  assert (chg_prop_idx >= 0);
11008 
11009  /* save new constraint only if it is not already present in current template */
11010  if (save_pt_costraint
11011  && !is_att_prop_set (attr_chg_properties->p[chg_prop_idx], ATT_CHG_PROPERTY_PRESENT_OLD))
11012  {
11013  error = save_constraint_info_from_pt_node (&(attr_chg_properties->new_constr_info), cnstr);
11014  if (error != NO_ERROR)
11015  {
11016  return error;
11017  }
11018  }
11019 
11020  attr_chg_properties->p[chg_prop_idx] |= ATT_CHG_PROPERTY_PRESENT_NEW;
11021  break;
11022  }
11023  }
11024  }
11025 
11026  /* partitions: */
11027  attr_chg_properties->p[P_IS_PARTITION_COL] = 0;
11028  if (ctemplate->partition)
11029  {
11030  char keycol[DB_MAX_IDENTIFIER_LENGTH] = { 0 };
11031 
11032  assert (attr_chg_properties->name_space == ID_ATTRIBUTE);
11033 
11034  error = do_get_partition_keycol (keycol, ctemplate->op);
11035  if (error != NO_ERROR)
11036  {
11037  return error;
11038  }
11039  if (intl_identifier_casecmp (keycol, attr_name) == 0)
11040  {
11041  attr_chg_properties->p[P_IS_PARTITION_COL] |= ATT_CHG_PROPERTY_PRESENT_OLD;
11042  }
11043  }
11044 
11045  /* DOMAIN */
11046  attr_db_domain = pt_node_to_db_domain (parser, attr_def, ctemplate->name);
11047  if (attr_db_domain == NULL)
11048  {
11049  assert (er_errid () != NO_ERROR);
11050  return (er_errid ());
11051  }
11052  attr_chg_properties->p[P_TYPE] = 0;
11053  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_PRESENT_NEW;
11054  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_PRESENT_OLD;
11055 
11056  /* consolidate properties : */
11057  {
11058  int i = 0;
11059 
11060  for (i = 0; i < NUM_ATT_CHG_PROP; i++)
11061  {
11062  int *const p = &(attr_chg_properties->p[i]);
11063 
11065  {
11067  {
11069  }
11070  else
11071  {
11072  *p |= ATT_CHG_PROPERTY_LOST;
11073  }
11074  }
11075  else
11076  {
11078  {
11080  }
11081  else
11082  {
11084  }
11085  }
11086 
11088  {
11089  /* remove UNCHANGED flag if DIFF flag was already set */
11091  }
11092  }
11093 
11094  }
11095 
11096  /* special case : TYPE */
11097  if (tp_domain_match (attr_db_domain, att->domain, TP_EXACT_MATCH) != 0)
11098  {
11099  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_UNCHANGED;
11100  }
11101  else
11102  {
11103  assert (attr_db_domain->type != NULL);
11104 
11105  /* remove "UNCHANGED" flag */
11106  attr_chg_properties->p[P_TYPE] &= ~ATT_CHG_PROPERTY_UNCHANGED;
11107 
11108  if (TP_DOMAIN_TYPE (attr_db_domain) == TP_DOMAIN_TYPE (att->domain)
11109  && TP_IS_CHAR_BIT_TYPE (TP_DOMAIN_TYPE (attr_db_domain)))
11110  {
11111  if (tp_domain_match (attr_db_domain, att->domain, TP_STR_MATCH) != 0)
11112  {
11113  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PREC_INCR;
11114  }
11115  else
11116  {
11117  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_DIFF;
11118  if (attr_db_domain->precision >= att->domain->precision)
11119  {
11120  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11121 
11122  (void) build_att_coll_change_map (att->domain, attr_db_domain, attr_chg_properties);
11123  }
11124  else
11125  {
11126  assert (attr_db_domain->precision < att->domain->precision
11127  || (TP_DOMAIN_COLLATION (attr_db_domain) != TP_DOMAIN_COLLATION (att->domain)));
11128 
11129  if (QSTR_IS_FIXED_LENGTH (TP_DOMAIN_TYPE (attr_db_domain))
11131  {
11132  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED_WITH_CFG;
11133  }
11134  else
11135  {
11136  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11137 
11138  (void) build_att_coll_change_map (att->domain, attr_db_domain, attr_chg_properties);
11139  }
11140  }
11141  }
11142  }
11143  else if (TP_DOMAIN_TYPE (attr_db_domain) == TP_DOMAIN_TYPE (att->domain)
11144  && TP_DOMAIN_TYPE (attr_db_domain) == DB_TYPE_NUMERIC)
11145  {
11146  if (attr_db_domain->scale == att->domain->scale && attr_db_domain->precision > att->domain->precision)
11147  {
11148  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PREC_INCR;
11149  }
11150  else
11151  {
11152  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11153  }
11154  }
11155  else if (TP_IS_SET_TYPE (TP_DOMAIN_TYPE (attr_db_domain)) && TP_IS_SET_TYPE (TP_DOMAIN_TYPE (att->domain)))
11156  {
11157  if (tp_domain_compatible (att->domain, attr_db_domain) != 0)
11158  {
11159  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_SET_CLS_COMPAT;
11160  }
11161  else
11162  {
11163  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11164  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_DIFF;
11165  }
11166  }
11167  else
11168  {
11169  attr_chg_properties->p[P_TYPE] |= ATT_CHG_PROPERTY_DIFF;
11170  error = build_att_type_change_map (att->domain, attr_db_domain, attr_chg_properties);
11171  if (error != NO_ERROR)
11172  {
11173  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11174  return error;
11175  }
11176  }
11177  }
11178 
11179  tp_domain_free (attr_db_domain);
11180 
11181  /* special case : AUTO INCREMENT if start value specified, we create a new serial or keep the old one Be mysql
11182  * compatible, see CUBRIDSUS-6441 */
11185  {
11186  attr_chg_properties->p[P_AUTO_INCR] |= ATT_CHG_PROPERTY_DIFF;
11187  /* remove "UNCHANGED" flag */
11188  attr_chg_properties->p[P_AUTO_INCR] &= ~ATT_CHG_PROPERTY_UNCHANGED;
11189  }
11190 
11191  /* special case : DEFAULT */
11192  if (is_att_prop_set (attr_chg_properties->p[P_DEFAULT_VALUE],
11194  {
11195  attr_chg_properties->p[P_DEFAULT_VALUE] |= ATT_CHG_PROPERTY_DIFF;
11196  /* remove "UNCHANGED" flag */
11197  attr_chg_properties->p[P_DEFAULT_VALUE] &= ~ATT_CHG_PROPERTY_UNCHANGED;
11198  }
11199 
11200  /* special case : UNIQUE on multiple columns */
11201  if (is_att_prop_set (attr_chg_properties->p[P_M_CONSTR_UNI], ATT_CHG_PROPERTY_PRESENT_OLD))
11202  {
11203  if (is_att_prop_set (attr_chg_properties->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
11204  {
11205  attr_chg_properties->p[P_M_CONSTR_UNI] |= ATT_CHG_PROPERTY_DIFF;
11206  /* remove "UNCHANGED" flag */
11207  attr_chg_properties->p[P_M_CONSTR_UNI] &= ~ATT_CHG_PROPERTY_UNCHANGED;
11208  }
11209  else
11210  {
11211  attr_chg_properties->p[P_M_CONSTR_UNI] |= ATT_CHG_PROPERTY_UNCHANGED;
11212  }
11213  }
11214 
11215  /* comment */
11216  attr_chg_properties->p[P_COMMENT] = 0;
11217  attr_chg_properties->p[P_COMMENT] |= ATT_CHG_PROPERTY_LOST;
11218  comment = attr_def->info.attr_def.comment;
11219  if (comment != NULL)
11220  {
11221  assert (comment->node_type == PT_VALUE);
11222  if (comment->info.value.data_value.str != NULL)
11223  {
11224  attr_chg_properties->p[P_COMMENT] |= ATT_CHG_PROPERTY_DIFF;
11225  /* remove "LOST" flag */
11226  attr_chg_properties->p[P_COMMENT] &= ~ATT_CHG_PROPERTY_LOST;
11227  }
11228  }
11229 
11230  return error;
11231 }
11232 
11233 /*
11234  * build_att_type_change_map() - This checks the attribute type change
11235  *
11236  * return: Error code
11237  * parser(in): Parser context
11238  * curr_domain(in): Current domain of the atribute
11239  * req_domain(in): Requested (new) domain of the attribute
11240  * attr_chg_properties(out): structure summarizing the changed properties
11241  * of attribute
11242  */
11243 static int
11244 build_att_type_change_map (TP_DOMAIN * curr_domain, TP_DOMAIN * req_domain, SM_ATTR_PROP_CHG * attr_chg_properties)
11245 {
11246  int error = NO_ERROR;
11247  const int MIN_DIGITS_FOR_INTEGER = TP_INTEGER_PRECISION;
11248  const int MIN_DIGITS_FOR_SHORT = TP_SMALLINT_PRECISION;
11249  const int MIN_DIGITS_FOR_BIGINT = TP_BIGINT_PRECISION;
11250  const int MIN_CHARS_FOR_TIME = TP_TIME_AS_CHAR_LENGTH;
11251  const int MIN_CHARS_FOR_DATE = TP_DATE_AS_CHAR_LENGTH;
11252  const int MIN_CHARS_FOR_DATETIME = TP_DATETIME_AS_CHAR_LENGTH;
11253  const int MIN_CHARS_FOR_DATETIMETZ = TP_DATETIMETZ_AS_CHAR_LENGTH;
11254  const int MIN_CHARS_FOR_TIMESTAMP = TP_TIMESTAMP_AS_CHAR_LENGTH;
11255  const int MIN_CHARS_FOR_TIMESTAMPTZ = TP_TIMESTAMPTZ_AS_CHAR_LENGTH;
11256 
11257  DB_TYPE current_type = TP_DOMAIN_TYPE (curr_domain);
11258  DB_TYPE new_type = TP_DOMAIN_TYPE (req_domain);
11259  int req_prec = req_domain->precision;
11260  int req_scale = req_domain->scale;
11261  int cur_prec = curr_domain->precision;
11262  int cur_scale = curr_domain->scale;
11263 
11264  bool is_req_max_prec = false;
11265 
11266  /* check if maximum precision was requested for new domain */
11267  if (new_type == DB_TYPE_VARCHAR)
11268  {
11269  if (req_prec == DB_MAX_VARCHAR_PRECISION)
11270  {
11271  is_req_max_prec = true;
11272  }
11273  else if (req_prec == TP_FLOATING_PRECISION_VALUE)
11274  {
11275  req_prec = DB_MAX_VARCHAR_PRECISION;
11276  is_req_max_prec = true;
11277  }
11278  else
11279  {
11280  assert (req_prec >= 0);
11281  }
11282  }
11283  else if (new_type == DB_TYPE_VARNCHAR)
11284  {
11285  if (req_prec == DB_MAX_VARNCHAR_PRECISION)
11286  {
11287  is_req_max_prec = true;
11288  }
11289  else if (req_prec == TP_FLOATING_PRECISION_VALUE)
11290  {
11291  req_prec = DB_MAX_VARNCHAR_PRECISION;
11292  is_req_max_prec = true;
11293  }
11294  else
11295  {
11296  assert (req_prec >= 0);
11297  }
11298  }
11299  else
11300  {
11301  assert (is_req_max_prec == false);
11302  }
11303 
11304  switch (current_type)
11305  {
11306  case DB_TYPE_SHORT:
11307  switch (new_type)
11308  {
11309  case DB_TYPE_INTEGER:
11310  case DB_TYPE_BIGINT:
11311  case DB_TYPE_FLOAT:
11312  case DB_TYPE_DOUBLE:
11313  case DB_TYPE_MONETARY:
11314  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11315  break;
11316  case DB_TYPE_NUMERIC:
11317  if (req_prec - req_scale >= MIN_DIGITS_FOR_SHORT)
11318  {
11319  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11320  }
11321  else
11322  {
11323  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11324  }
11325  break;
11326  case DB_TYPE_CHAR:
11327  case DB_TYPE_NCHAR:
11328  case DB_TYPE_VARCHAR:
11329  case DB_TYPE_VARNCHAR:
11330  if (req_prec >= MIN_DIGITS_FOR_SHORT + 1)
11331  {
11332  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11333  }
11334  else
11335  {
11336  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11337  }
11338  break;
11339  case DB_TYPE_ENUMERATION:
11340  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11341  break;
11342  default:
11343  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11344  break;
11345  }
11346  break;
11347 
11348  case DB_TYPE_INTEGER:
11349  switch (new_type)
11350  {
11351  case DB_TYPE_SHORT:
11352  case DB_TYPE_FLOAT:
11353  case DB_TYPE_ENUMERATION:
11354  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11355  break;
11356  case DB_TYPE_BIGINT:
11357  case DB_TYPE_DOUBLE:
11358  case DB_TYPE_MONETARY:
11359  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11360  break;
11361  case DB_TYPE_NUMERIC:
11362  if (req_prec - req_scale >= MIN_DIGITS_FOR_INTEGER)
11363  {
11364  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11365  }
11366  else
11367  {
11368  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11369  }
11370  break;
11371  case DB_TYPE_CHAR:
11372  case DB_TYPE_NCHAR:
11373  case DB_TYPE_VARCHAR:
11374  case DB_TYPE_VARNCHAR:
11375  if (req_prec >= MIN_DIGITS_FOR_INTEGER + 1)
11376  {
11377  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11378  }
11379  else
11380  {
11381  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11382  }
11383  break;
11384  default:
11385  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11386  break;
11387  }
11388  break;
11389 
11390  case DB_TYPE_BIGINT:
11391  switch (new_type)
11392  {
11393  case DB_TYPE_SHORT:
11394  case DB_TYPE_INTEGER:
11395  case DB_TYPE_FLOAT:
11396  case DB_TYPE_DOUBLE:
11397  case DB_TYPE_MONETARY:
11398  case DB_TYPE_ENUMERATION:
11399  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11400  break;
11401  case DB_TYPE_NUMERIC:
11402  if (req_prec - req_scale >= MIN_DIGITS_FOR_BIGINT)
11403  {
11404  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11405  }
11406  else
11407  {
11408  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11409  }
11410  break;
11411  case DB_TYPE_CHAR:
11412  case DB_TYPE_NCHAR:
11413  case DB_TYPE_VARCHAR:
11414  case DB_TYPE_VARNCHAR:
11415  if (req_prec >= MIN_DIGITS_FOR_BIGINT + 1)
11416  {
11417  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11418  }
11419  else
11420  {
11421  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11422  }
11423  break;
11424  default:
11425  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11426  break;
11427  }
11428  break;
11429 
11430  case DB_TYPE_NUMERIC:
11431  switch (new_type)
11432  {
11433  case DB_TYPE_SHORT:
11434  if ((cur_prec < MIN_DIGITS_FOR_SHORT) && (cur_scale == 0))
11435  {
11436  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11437  }
11438  else
11439  {
11440  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11441  }
11442  break;
11443  case DB_TYPE_INTEGER:
11444  if ((cur_prec < MIN_DIGITS_FOR_INTEGER) && (cur_scale == 0))
11445  {
11446  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11447  }
11448  else
11449  {
11450  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11451  }
11452  break;
11453  case DB_TYPE_BIGINT:
11454  if ((cur_prec < MIN_DIGITS_FOR_BIGINT) && (cur_scale == 0))
11455  {
11456  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11457  }
11458  else
11459  {
11460  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11461  }
11462  break;
11463  case DB_TYPE_FLOAT:
11464  case DB_TYPE_DOUBLE:
11465  case DB_TYPE_MONETARY:
11466  case DB_TYPE_ENUMERATION:
11467  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11468  break;
11469  case DB_TYPE_CHAR:
11470  case DB_TYPE_NCHAR:
11471  case DB_TYPE_VARCHAR:
11472  case DB_TYPE_VARNCHAR:
11473  if (req_prec >= cur_prec + 2)
11474  {
11475  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11476  }
11477  else
11478  {
11479  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11480  }
11481  break;
11482  default:
11483  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11484  break;
11485  }
11486  break;
11487 
11488  case DB_TYPE_FLOAT:
11489  switch (new_type)
11490  {
11491  case DB_TYPE_SHORT:
11492  case DB_TYPE_INTEGER:
11493  case DB_TYPE_BIGINT:
11494  case DB_TYPE_NUMERIC:
11495  case DB_TYPE_CHAR:
11496  case DB_TYPE_NCHAR:
11497  case DB_TYPE_ENUMERATION:
11498  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11499  break;
11500  case DB_TYPE_VARCHAR:
11501  case DB_TYPE_VARNCHAR:
11502  if (is_req_max_prec)
11503  {
11504  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11505  }
11506  else
11507  {
11508  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11509  }
11510  break;
11511  case DB_TYPE_DOUBLE:
11512  case DB_TYPE_MONETARY:
11513  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11514  break;
11515  default:
11516  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11517  break;
11518  }
11519  break;
11520 
11521  case DB_TYPE_DOUBLE:
11522  switch (new_type)
11523  {
11524  case DB_TYPE_SHORT:
11525  case DB_TYPE_INTEGER:
11526  case DB_TYPE_BIGINT:
11527  case DB_TYPE_NUMERIC:
11528  case DB_TYPE_FLOAT:
11529  case DB_TYPE_CHAR:
11530  case DB_TYPE_NCHAR:
11531  case DB_TYPE_ENUMERATION:
11532  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11533  break;
11534  case DB_TYPE_VARCHAR:
11535  case DB_TYPE_VARNCHAR:
11536  if (is_req_max_prec)
11537  {
11538  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11539  }
11540  else
11541  {
11542  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11543  }
11544  break;
11545  case DB_TYPE_MONETARY:
11546  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11547  break;
11548  default:
11549  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11550  break;
11551  }
11552  break;
11553 
11554  case DB_TYPE_MONETARY:
11555  switch (new_type)
11556  {
11557  case DB_TYPE_SHORT:
11558  case DB_TYPE_INTEGER:
11559  case DB_TYPE_BIGINT:
11560  case DB_TYPE_NUMERIC:
11561  case DB_TYPE_FLOAT:
11562  case DB_TYPE_CHAR:
11563  case DB_TYPE_NCHAR:
11564  case DB_TYPE_ENUMERATION:
11565  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11566  break;
11567  case DB_TYPE_VARCHAR:
11568  case DB_TYPE_VARNCHAR:
11569  if (is_req_max_prec)
11570  {
11571  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11572  }
11573  else
11574  {
11575  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11576  }
11577  break;
11578  case DB_TYPE_DOUBLE:
11579  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11580  break;
11581  default:
11582  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11583  break;
11584  }
11585  break;
11586 
11587  case DB_TYPE_TIME:
11588  switch (new_type)
11589  {
11590  case DB_TYPE_CHAR:
11591  case DB_TYPE_NCHAR:
11592  case DB_TYPE_VARCHAR:
11593  case DB_TYPE_VARNCHAR:
11594  if (req_prec >= MIN_CHARS_FOR_TIME)
11595  {
11596  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11597  }
11598  else
11599  {
11600  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11601  }
11602  break;
11603  case DB_TYPE_ENUMERATION:
11604  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11605  break;
11606  default:
11607  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11608  break;
11609  }
11610  break;
11611 
11612  case DB_TYPE_DATE:
11613  switch (new_type)
11614  {
11615  case DB_TYPE_DATETIME:
11616  case DB_TYPE_DATETIMETZ:
11617  case DB_TYPE_DATETIMELTZ:
11618  case DB_TYPE_TIMESTAMP:
11619  case DB_TYPE_TIMESTAMPTZ:
11620  case DB_TYPE_TIMESTAMPLTZ:
11621  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11622  break;
11623  case DB_TYPE_CHAR:
11624  case DB_TYPE_NCHAR:
11625  case DB_TYPE_VARCHAR:
11626  case DB_TYPE_VARNCHAR:
11627  if (req_prec >= MIN_CHARS_FOR_DATE)
11628  {
11629  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11630  }
11631  else
11632  {
11633  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11634  }
11635  break;
11636  case DB_TYPE_ENUMERATION:
11637  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11638  break;
11639  default:
11640  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11641  break;
11642  }
11643  break;
11644 
11645  case DB_TYPE_DATETIME:
11646  switch (new_type)
11647  {
11648  case DB_TYPE_TIME:
11649  case DB_TYPE_DATE:
11650  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11651  break;
11652  case DB_TYPE_DATETIMETZ:
11653  case DB_TYPE_DATETIMELTZ:
11654  case DB_TYPE_TIMESTAMP:
11655  case DB_TYPE_TIMESTAMPTZ:
11656  case DB_TYPE_TIMESTAMPLTZ:
11657  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11658  break;
11659  case DB_TYPE_CHAR:
11660  case DB_TYPE_NCHAR:
11661  case DB_TYPE_VARCHAR:
11662  case DB_TYPE_VARNCHAR:
11663  if (req_prec >= MIN_CHARS_FOR_DATETIME)
11664  {
11665  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11666  }
11667  else
11668  {
11669  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11670  }
11671  break;
11672  case DB_TYPE_ENUMERATION:
11673  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11674  break;
11675  default:
11676  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11677  break;
11678  }
11679  break;
11680 
11681  case DB_TYPE_DATETIMETZ:
11682  switch (new_type)
11683  {
11684  case DB_TYPE_TIME:
11685  case DB_TYPE_DATE:
11686  case DB_TYPE_DATETIME:
11687  case DB_TYPE_DATETIMELTZ:
11688  case DB_TYPE_TIMESTAMPLTZ:
11689  case DB_TYPE_TIMESTAMP:
11690  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11691  break;
11692  case DB_TYPE_TIMESTAMPTZ:
11693  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11694  break;
11695  case DB_TYPE_CHAR:
11696  case DB_TYPE_NCHAR:
11697  case DB_TYPE_VARCHAR:
11698  case DB_TYPE_VARNCHAR:
11699  if (req_prec >= MIN_CHARS_FOR_DATETIMETZ)
11700  {
11701  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11702  }
11703  else
11704  {
11705  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11706  }
11707  break;
11708  case DB_TYPE_ENUMERATION:
11709  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11710  break;
11711  default:
11712  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11713  break;
11714  }
11715  break;
11716 
11717  case DB_TYPE_DATETIMELTZ:
11718  switch (new_type)
11719  {
11720  case DB_TYPE_TIME:
11721  case DB_TYPE_DATE:
11722  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11723  break;
11724  case DB_TYPE_DATETIME:
11725  case DB_TYPE_DATETIMETZ:
11726  case DB_TYPE_TIMESTAMP:
11727  case DB_TYPE_TIMESTAMPTZ:
11728  case DB_TYPE_TIMESTAMPLTZ:
11729  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11730  break;
11731  case DB_TYPE_CHAR:
11732  case DB_TYPE_NCHAR:
11733  case DB_TYPE_VARCHAR:
11734  case DB_TYPE_VARNCHAR:
11735  if (req_prec >= MIN_CHARS_FOR_DATETIMETZ)
11736  {
11737  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11738  }
11739  else
11740  {
11741  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11742  }
11743  break;
11744  case DB_TYPE_ENUMERATION:
11745  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11746  break;
11747  default:
11748  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11749  break;
11750  }
11751  break;
11752 
11753  case DB_TYPE_TIMESTAMP:
11754  switch (new_type)
11755  {
11756  case DB_TYPE_TIME:
11757  case DB_TYPE_DATE:
11758  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11759  break;
11760  case DB_TYPE_TIMESTAMPTZ:
11761  case DB_TYPE_TIMESTAMPLTZ:
11762  case DB_TYPE_DATETIME:
11763  case DB_TYPE_DATETIMETZ:
11764  case DB_TYPE_DATETIMELTZ:
11765  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11766  break;
11767  case DB_TYPE_CHAR:
11768  case DB_TYPE_NCHAR:
11769  case DB_TYPE_VARCHAR:
11770  case DB_TYPE_VARNCHAR:
11771  if (req_prec >= MIN_CHARS_FOR_TIMESTAMP)
11772  {
11773  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11774  }
11775  else
11776  {
11777  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11778  }
11779  break;
11780  case DB_TYPE_ENUMERATION:
11781  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11782  break;
11783  default:
11784  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11785  break;
11786  }
11787  break;
11788 
11789  case DB_TYPE_TIMESTAMPTZ:
11790  switch (new_type)
11791  {
11792  case DB_TYPE_TIME:
11793  case DB_TYPE_DATE:
11794  case DB_TYPE_TIMESTAMP:
11795  case DB_TYPE_TIMESTAMPLTZ:
11796  case DB_TYPE_DATETIME:
11797  case DB_TYPE_DATETIMELTZ:
11798  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11799  break;
11800  case DB_TYPE_DATETIMETZ:
11801  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11802  break;
11803  case DB_TYPE_CHAR:
11804  case DB_TYPE_NCHAR:
11805  case DB_TYPE_VARCHAR:
11806  case DB_TYPE_VARNCHAR:
11807  if (req_prec >= MIN_CHARS_FOR_TIMESTAMPTZ)
11808  {
11809  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11810  }
11811  else
11812  {
11813  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11814  }
11815  break;
11816  case DB_TYPE_ENUMERATION:
11817  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11818  break;
11819  default:
11820  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11821  break;
11822  }
11823  break;
11824 
11825  case DB_TYPE_TIMESTAMPLTZ:
11826  switch (new_type)
11827  {
11828  case DB_TYPE_TIME:
11829  case DB_TYPE_DATE:
11830  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
11831  break;
11832  case DB_TYPE_TIMESTAMP:
11833  case DB_TYPE_TIMESTAMPTZ:
11834  case DB_TYPE_DATETIME:
11835  case DB_TYPE_DATETIMETZ:
11836  case DB_TYPE_DATETIMELTZ:
11837  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11838  break;
11839  case DB_TYPE_CHAR:
11840  case DB_TYPE_NCHAR:
11841  case DB_TYPE_VARCHAR:
11842  case DB_TYPE_VARNCHAR:
11843  if (req_prec >= MIN_CHARS_FOR_TIMESTAMPTZ)
11844  {
11845  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11846  }
11847  else
11848  {
11849  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11850  }
11851  break;
11852  case DB_TYPE_ENUMERATION:
11853  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11854  break;
11855  default:
11856  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11857  break;
11858  }
11859  break;
11860 
11861  case DB_TYPE_CHAR:
11862  switch (new_type)
11863  {
11864  case DB_TYPE_SHORT:
11865  case DB_TYPE_INTEGER:
11866  case DB_TYPE_BIGINT:
11867  case DB_TYPE_NUMERIC:
11868  case DB_TYPE_FLOAT:
11869  case DB_TYPE_DOUBLE:
11870  case DB_TYPE_MONETARY:
11871  case DB_TYPE_DATE:
11872  case DB_TYPE_TIME:
11873  case DB_TYPE_DATETIME:
11874  case DB_TYPE_DATETIMETZ:
11875  case DB_TYPE_DATETIMELTZ:
11876  case DB_TYPE_TIMESTAMP:
11877  case DB_TYPE_TIMESTAMPTZ:
11878  case DB_TYPE_TIMESTAMPLTZ:
11879  case DB_TYPE_ENUMERATION:
11880  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11881  break;
11882  case DB_TYPE_VARCHAR:
11883  if (req_prec >= cur_prec)
11884  {
11885  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11886  }
11887  else
11888  {
11890  {
11891  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED_WITH_CFG;
11892  }
11893  else
11894  {
11895  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11896  }
11897  }
11898  break;
11899  default:
11900  assert (new_type != DB_TYPE_CHAR);
11901  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11902  break;
11903  }
11904  break;
11905 
11906  case DB_TYPE_VARCHAR:
11907  switch (new_type)
11908  {
11909  case DB_TYPE_SHORT:
11910  case DB_TYPE_INTEGER:
11911  case DB_TYPE_BIGINT:
11912  case DB_TYPE_NUMERIC:
11913  case DB_TYPE_FLOAT:
11914  case DB_TYPE_DOUBLE:
11915  case DB_TYPE_MONETARY:
11916  case DB_TYPE_DATE:
11917  case DB_TYPE_TIME:
11918  case DB_TYPE_DATETIME:
11919  case DB_TYPE_DATETIMETZ:
11920  case DB_TYPE_DATETIMELTZ:
11921  case DB_TYPE_TIMESTAMP:
11922  case DB_TYPE_TIMESTAMPTZ:
11923  case DB_TYPE_TIMESTAMPLTZ:
11924  case DB_TYPE_ENUMERATION:
11925  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11926  break;
11927  case DB_TYPE_CHAR:
11928  if (req_prec >= cur_prec)
11929  {
11930  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11931  }
11932  else
11933  {
11934  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11935  }
11936  break;
11937  default:
11938  assert (new_type != DB_TYPE_VARCHAR);
11939  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11940  break;
11941  }
11942  break;
11943 
11944  case DB_TYPE_NCHAR:
11945  switch (new_type)
11946  {
11947  case DB_TYPE_SHORT:
11948  case DB_TYPE_INTEGER:
11949  case DB_TYPE_BIGINT:
11950  case DB_TYPE_NUMERIC:
11951  case DB_TYPE_FLOAT:
11952  case DB_TYPE_DOUBLE:
11953  case DB_TYPE_MONETARY:
11954  case DB_TYPE_DATE:
11955  case DB_TYPE_TIME:
11956  case DB_TYPE_DATETIME:
11957  case DB_TYPE_DATETIMETZ:
11958  case DB_TYPE_DATETIMELTZ:
11959  case DB_TYPE_TIMESTAMP:
11960  case DB_TYPE_TIMESTAMPTZ:
11961  case DB_TYPE_TIMESTAMPLTZ:
11962  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11963  break;
11964  case DB_TYPE_VARNCHAR:
11965  if (req_prec >= cur_prec)
11966  {
11967  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
11968  }
11969  else
11970  {
11972  {
11973  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED_WITH_CFG;
11974  }
11975  else
11976  {
11977  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
11978  }
11979  }
11980  break;
11981  default:
11982  assert (new_type != DB_TYPE_NCHAR);
11983  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
11984  break;
11985  }
11986  break;
11987 
11988  case DB_TYPE_VARNCHAR:
11989  switch (new_type)
11990  {
11991  case DB_TYPE_SHORT:
11992  case DB_TYPE_INTEGER:
11993  case DB_TYPE_BIGINT:
11994  case DB_TYPE_NUMERIC:
11995  case DB_TYPE_FLOAT:
11996  case DB_TYPE_DOUBLE:
11997  case DB_TYPE_MONETARY:
11998  case DB_TYPE_DATE:
11999  case DB_TYPE_TIME:
12000  case DB_TYPE_DATETIME:
12001  case DB_TYPE_DATETIMETZ:
12002  case DB_TYPE_DATETIMELTZ:
12003  case DB_TYPE_TIMESTAMP:
12004  case DB_TYPE_TIMESTAMPTZ:
12005  case DB_TYPE_TIMESTAMPLTZ:
12006  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
12007  break;
12008  case DB_TYPE_NCHAR:
12009  if (req_prec >= cur_prec)
12010  {
12011  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
12012  }
12013  else
12014  {
12015  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
12016  }
12017  break;
12018  default:
12019  assert (new_type != DB_TYPE_VARNCHAR);
12020  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12021  break;
12022  }
12023  break;
12024 
12025  case DB_TYPE_BIT:
12026  switch (new_type)
12027  {
12028  case DB_TYPE_VARBIT:
12029  if (req_prec >= cur_prec)
12030  {
12031  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
12032  }
12033  else
12034  {
12036  {
12037  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED_WITH_CFG;
12038  }
12039  else
12040  {
12041  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
12042  }
12043  }
12044  break;
12045  default:
12046  assert (new_type != DB_TYPE_BIT);
12047  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12048  break;
12049  }
12050  break;
12051 
12052  case DB_TYPE_VARBIT:
12053  switch (new_type)
12054  {
12055  case DB_TYPE_BIT:
12056  if (req_prec >= cur_prec)
12057  {
12058  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_UPGRADE;
12059  }
12060  else
12061  {
12062  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
12063  }
12064  break;
12065  default:
12066  assert (new_type != DB_TYPE_VARBIT);
12067  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12068  break;
12069  }
12070  break;
12071 
12072  case DB_TYPE_OBJECT:
12073  if (new_type != DB_TYPE_OBJECT)
12074  {
12075  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12076  }
12077  else
12078  {
12079  assert (db_is_class (curr_domain->class_mop) != 0);
12080  assert (db_is_class (req_domain->class_mop) != 0);
12081 
12082  if (req_domain->class_mop != curr_domain->class_mop)
12083  {
12084  if (db_is_subclass (curr_domain->class_mop, req_domain->class_mop) <= 0)
12085  {
12086  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12087  }
12088  else
12089  {
12090  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_SET_CLS_COMPAT;
12091  }
12092  }
12093  else
12094  {
12095  /* same OBJECT, should have been checked earlier */
12096  assert (false);
12097  attr_chg_properties->p[P_TYPE] &= ~ATT_CHG_PROPERTY_DIFF;
12098  }
12099  }
12100  break;
12101 
12102  case DB_TYPE_ENUMERATION:
12103  switch (new_type)
12104  {
12105  case DB_TYPE_SHORT:
12106  case DB_TYPE_INTEGER:
12107  case DB_TYPE_BIGINT:
12108  case DB_TYPE_NUMERIC:
12109  case DB_TYPE_FLOAT:
12110  case DB_TYPE_DOUBLE:
12111  case DB_TYPE_CHAR:
12112  case DB_TYPE_VARCHAR:
12113  case DB_TYPE_MONETARY:
12114  case DB_TYPE_ENUMERATION:
12115  case DB_TYPE_DATE:
12116  case DB_TYPE_DATETIME:
12117  case DB_TYPE_DATETIMETZ:
12118  case DB_TYPE_DATETIMELTZ:
12119  case DB_TYPE_TIME:
12120  case DB_TYPE_TIMESTAMP:
12121  case DB_TYPE_TIMESTAMPTZ:
12122  case DB_TYPE_TIMESTAMPLTZ:
12123  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NEED_ROW_CHECK;
12124  break;
12125  default:
12126  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12127  break;
12128  }
12129  break;
12130 
12131  default:
12132  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12133  break;
12134  }
12135 
12136  (void) build_att_coll_change_map (curr_domain, req_domain, attr_chg_properties);
12137 
12138  return error;
12139 }
12140 
12141 /*
12142  * build_att_coll_change_map() - This checks the attribute collation and
12143  * codeset change
12144  *
12145  * return: Error code
12146  * parser(in): Parser context
12147  * curr_domain(in): Current domain of the attribute
12148  * req_domain(in): Requested (new) domain of the attribute
12149  * attr_chg_properties(out): structure summarizing the changed properties
12150  * of attribute
12151  */
12152 static int
12153 build_att_coll_change_map (TP_DOMAIN * curr_domain, TP_DOMAIN * req_domain, SM_ATTR_PROP_CHG * attr_chg_properties)
12154 {
12155  /* check collation change */
12156  if (TP_TYPE_HAS_COLLATION (TP_DOMAIN_TYPE (curr_domain)) && TP_TYPE_HAS_COLLATION (TP_DOMAIN_TYPE (req_domain)))
12157  {
12158  const int curr_coll_id = TP_DOMAIN_COLLATION (curr_domain);
12159  const int req_coll_id = TP_DOMAIN_COLLATION (req_domain);
12160  const INTL_CODESET curr_cs = TP_DOMAIN_CODESET (curr_domain);
12161  const INTL_CODESET req_cs = TP_DOMAIN_CODESET (req_domain);
12162 
12163  if (curr_coll_id != req_coll_id)
12164  {
12165  if (!INTL_CAN_COERCE_CS (curr_cs, req_cs))
12166  {
12167  /* change of codeset not supported */
12168  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12169  }
12170  else
12171  {
12172  /* change of collation allowed : requires index recreation */
12173  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_PSEUDO_UPGRADE;
12174  }
12175 
12176  if (is_att_prop_set (attr_chg_properties->p[P_PREFIX_INDEX], ATT_CHG_PROPERTY_PRESENT_OLD))
12177  {
12178  /* check if new collation has expansions */
12179  LANG_COLLATION *lc = lang_get_collation (req_coll_id);
12180 
12181  assert (lc != NULL);
12182 
12183  if (!(lc->options.allow_prefix_index))
12184  {
12185  attr_chg_properties->p[P_TYPE] |= ATT_CHG_TYPE_NOT_SUPPORTED;
12186  }
12187  }
12188  }
12189  else
12190  {
12191  /* collation and codeset unchanged */
12192  assert (curr_cs == req_cs);
12193  }
12194  }
12195 
12196  return NO_ERROR;
12197 }
12198 
12199 /*
12200  * check_att_chg_allowed() - This checks if the attribute change is possible,
12201  * if not it sets an appropiate error
12202  *
12203  * return: NO_ERROR if changed allowed, an error code if change not allowed
12204  * att_name(in): name of attribute (to display in error messages)
12205  * t(in): new type (parse tree namespace)
12206  * attr_chg_properties(in): structure summarizing the changed properties of
12207  * attribute
12208  * chg_how(in): the strategy for which the check is requested
12209  * log_error_allowed(in): log the error if any
12210  * new_attempt(out): is set to false if a new attempt with different
12211  * 'chg_how' argument may produce a positive result
12212  *
12213  * Note : this function may be called several times, each time esacalating
12214  * the 'chg_how' mode parameter; the caller should ensure that only
12215  * the last call allows also to log an error, by setting the
12216  * 'log_error_allowed' argument.
12217  * The caller should also check the 'new_attempt' value before trying
12218  * a new 'chg_how' argument.
12219  * All error codes set in this function must correspond to messages
12220  * with one argument, otherwise additional processing must be done
12221  * before tracing the error.
12222  */
12223 static int
12224 check_att_chg_allowed (const char *att_name, const PT_TYPE_ENUM t, const SM_ATTR_PROP_CHG * attr_chg_prop,
12225  SM_ATTR_CHG_SOL chg_how, bool log_error_allowed, bool * new_attempt)
12226 {
12227  int error = NO_ERROR;
12228 
12229  /* these are error codes issued by ALTER CHANGE which map on other exising ALTER CHANGE error messages; they are kept
12230  * with different names for better differentiation between error contexts */
12231  const int ER_ALTER_CHANGE_TYPE_WITH_NON_UNIQUE = ER_ALTER_CHANGE_TYPE_WITH_INDEX;
12232  const int ER_ALTER_CHANGE_TYPE_WITH_M_UNIQUE = ER_ALTER_CHANGE_TYPE_WITH_INDEX;
12233  const int ER_ALTER_CHANGE_TYPE_WITH_S_UNIQUE = ER_ALTER_CHANGE_TYPE_WITH_INDEX;
12234  const int ER_ALTER_CHANGE_TYPE_WITH_PK = ER_ALTER_CHANGE_TYPE_WITH_INDEX;
12235 
12236  /* by default we advise new attempt */
12237  *new_attempt = true;
12238 
12239  /* partitions not allowed : this check (by value instead of bit) ensures that the column doesn't have partitions in
12240  * current schema and in new definition */
12241  if (attr_chg_prop->p[P_IS_PARTITION_COL] != ATT_CHG_PROPERTY_UNCHANGED)
12242  {
12244  *new_attempt = false;
12245  goto not_allowed;
12246  }
12247  /* foreign key not allowed : this check (by value instead of bit) ensures that the column doesn't have a foreign key
12248  * in current schema and in new definition */
12249  if (attr_chg_prop->p[P_CONSTR_FK] != ATT_CHG_PROPERTY_UNCHANGED)
12250  {
12251  error = ER_ALTER_CHANGE_FK;
12252  *new_attempt = false;
12253  goto not_allowed;
12254  }
12255 
12256  if ((attr_chg_prop->name_space == ID_SHARED_ATTRIBUTE && attr_chg_prop->new_name_space == ID_ATTRIBUTE)
12257  || (attr_chg_prop->name_space == ID_ATTRIBUTE && attr_chg_prop->new_name_space == ID_SHARED_ATTRIBUTE))
12258  {
12260  *new_attempt = false;
12261  goto not_allowed;
12262  }
12263 
12264  /* unique key : drop is allowed */
12265  /* unique key : gaining UK is matter of adding a new constraint */
12266 
12267  /* primary key : drop is allowed */
12268  /* primary key : gaining PK is matter of adding a new constraint */
12269 
12270  /* NOT NULL : gaining is not always allowed */
12271  if (is_att_prop_set (attr_chg_prop->p[P_NOT_NULL], ATT_CHG_PROPERTY_GAINED))
12272  {
12273  if (t == PT_TYPE_BLOB || t == PT_TYPE_CLOB)
12274  {
12276  *new_attempt = false;
12277  goto not_allowed;
12278  }
12279  if (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE)
12280  {
12281  error = ER_SM_INVALID_CONSTRAINT;
12282  *new_attempt = false;
12283  goto not_allowed;
12284  }
12286  {
12287  /* in permissive mode, we may have to convert existent NULL values to hard- defaults, so make sure the hard
12288  * default type exists */
12289  if (get_hard_default_for_type (t) == NULL)
12290  {
12292  *new_attempt = false;
12293  goto not_allowed;
12294  }
12295  }
12296  /* gaining NOT NULL is matter of adding a new constraint */
12297  }
12298 
12299  /* check type changes and ... */
12300  /* check if AUTO_INCR is gained: */
12301  if (is_att_prop_set (attr_chg_prop->p[P_AUTO_INCR], ATT_CHG_PROPERTY_GAINED))
12302  {
12303  if (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE || attr_chg_prop->name_space == ID_SHARED_ATTRIBUTE)
12304  {
12305  error = ER_SM_INVALID_CONSTRAINT;
12306  *new_attempt = false;
12307  goto not_allowed;
12308  }
12309 
12310  if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
12311  {
12312  if (chg_how == SM_ATTR_CHG_ONLY_SCHEMA)
12313  {
12315  goto not_allowed;
12316  }
12317  }
12318  }
12319 
12320  /* check type change */
12321  if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NOT_SUPPORTED))
12322  {
12324  *new_attempt = false;
12325  goto not_allowed;
12326  }
12327  else if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NOT_SUPPORTED_WITH_CFG))
12328  {
12330  *new_attempt = false;
12331  goto not_allowed;
12332  }
12333  else if (chg_how == SM_ATTR_CHG_ONLY_SCHEMA)
12334  {
12335  if (attr_chg_prop->name_space != ID_ATTRIBUTE)
12336  {
12337  /* allow any type change (except when not supported by config) for class and shared attributes */
12338 
12339  assert (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE || attr_chg_prop->name_space == ID_SHARED_ATTRIBUTE);
12340 
12342  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NEED_ROW_CHECK)
12343  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PSEUDO_UPGRADE)
12344  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_UPGRADE)
12345  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PREC_INCR)
12346  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_SET_CLS_COMPAT));
12347  }
12348  else
12349  {
12350  if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NEED_ROW_CHECK)
12351  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PSEUDO_UPGRADE))
12352  {
12354  goto not_allowed;
12355  }
12356  else if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_UPGRADE))
12357  {
12359  goto not_allowed;
12360  }
12361  else if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF)
12362  && !(is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PREC_INCR)
12363  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_SET_CLS_COMPAT)))
12364  {
12366  goto not_allowed;
12367  }
12368  }
12369  }
12370  else if (chg_how == SM_ATTR_CHG_WITH_ROW_UPDATE)
12371  {
12372  assert (attr_chg_prop->name_space == ID_ATTRIBUTE);
12373 
12374  if (is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_NEED_ROW_CHECK)
12375  || is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_TYPE_PSEUDO_UPGRADE))
12376  {
12378  goto not_allowed;
12379  }
12380  }
12381  else
12382  {
12383  assert (attr_chg_prop->name_space == ID_ATTRIBUTE);
12384 
12385  /* allow any change that is not "NOT_SUPPORTED" */
12386  assert (chg_how == SM_ATTR_CHG_BEST_EFFORT);
12387  }
12388 
12389  /* these constraints are not allowed under a "schema only" change: */
12390  if (chg_how == SM_ATTR_CHG_ONLY_SCHEMA)
12391  {
12392  /* CLASS and SHARED attribute are incompatible with UNIQUE, PK */
12393  if (attr_chg_prop->name_space == ID_CLASS_ATTRIBUTE || attr_chg_prop->name_space == ID_SHARED_ATTRIBUTE)
12394  {
12397  {
12398 
12399  error = ER_SM_INVALID_CONSTRAINT;
12400  *new_attempt = false;
12401  goto not_allowed;
12402  }
12403  }
12404 
12405  /* cannot keep UNIQUE constr if type is changed */
12406  if (is_att_prop_set (attr_chg_prop->p[P_S_CONSTR_UNI],
12408  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
12409  {
12410  error = ER_ALTER_CHANGE_TYPE_WITH_S_UNIQUE;
12411  goto not_allowed;
12412  }
12414  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
12415  {
12416  error = ER_ALTER_CHANGE_TYPE_WITH_M_UNIQUE;
12417  goto not_allowed;
12418  }
12419 
12420  /* primary key not allowed to be kept when type changes: */
12422  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
12423  {
12424  error = ER_ALTER_CHANGE_TYPE_WITH_PK;
12425  goto not_allowed;
12426  }
12427 
12428  /* non-unique index not allowed when type changes: */
12430  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_DIFF))
12431  {
12432  error = ER_ALTER_CHANGE_TYPE_WITH_NON_UNIQUE;
12433  goto not_allowed;
12434  }
12435  }
12436 
12437  /* we should not have multiple primary keys defined */
12439  ? (is_att_prop_set (attr_chg_prop->p[P_M_CONSTR_PK], ATT_CHG_PROPERTY_PRESENT_OLD) ? false : true) : true);
12440 
12441  /* ALTER .. CHANGE <attribute> syntax should not allow to define PK on multiple rows */
12443 
12444  /* check if multiple primary keys after new definition */
12449  {
12451  *new_attempt = false;
12452  goto not_allowed;
12453  }
12454 
12455  /* check if class has subclasses: */
12456  if (attr_chg_prop->class_has_subclass
12457  && !(is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_UNCHANGED)
12458  && is_att_prop_set (attr_chg_prop->p[P_ORDER], ATT_CHG_PROPERTY_UNCHANGED)
12459  && is_att_prop_set (attr_chg_prop->p[P_TYPE], ATT_CHG_PROPERTY_UNCHANGED)
12466  {
12467  /* allowed changes for class with sub-classes is for DEFAULT value */
12469  *new_attempt = false;
12470  goto not_allowed;
12471  }
12472 
12473  return NO_ERROR;
12474 
12475 not_allowed:
12476  if (log_error_allowed || !(*new_attempt))
12477  {
12478  if (error == ER_SM_NOT_NULL_NOT_ALLOWED || error == ER_SM_INVALID_CONSTRAINT)
12479  {
12481  }
12482  else
12483  {
12484  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, att_name);
12485  }
12486  }
12487  return error;
12488 }
12489 
12490 /*
12491  * is_att_property_structure_checked() - Checks all properties from the
12492  * attribute change properties structure
12493  *
12494  * return : true, if all properties are marked as checked, false otherwise
12495  * attr_chg_properties(in): structure summarizing the changed properties of
12496  * attribute
12497  *
12498  */
12499 static bool
12501 {
12502  int i = 0;
12503 
12504  for (i = 0; i < NUM_ATT_CHG_PROP; i++)
12505  {
12506  if (attr_chg_properties->p[i] >= ATT_CHG_PROPERTY_NOT_CHECKED)
12507  {
12508  return false;
12509  }
12510  }
12511  return true;
12512 }
12513 
12514 /*
12515  * is_att_change_needed() - Checks all properties from the attribute change
12516  * properties structure and decides if the schema
12517  * update is necessary
12518  *
12519  * return : true, if schema change is needed, false otherwise
12520  * attr_chg_properties(in): structure summarizing the changed properties of
12521  * attribute
12522  *
12523  */
12524 static bool
12525 is_att_change_needed (const SM_ATTR_PROP_CHG * attr_chg_properties)
12526 {
12527  int i = 0;
12528 
12529  for (i = 0; i < NUM_ATT_CHG_PROP; i++)
12530  {
12531  if (attr_chg_properties->p[i] >= ATT_CHG_PROPERTY_DIFF)
12532  {
12533  return true;
12534  }
12535 
12536  if (!is_att_prop_set (attr_chg_properties->p[i], ATT_CHG_PROPERTY_UNCHANGED))
12537  {
12538  return true;
12539  }
12540  }
12541  return false;
12542 }
12543 
12544 /*
12545  * is_att_prop_set() - Checks that the properties has the flag set
12546  *
12547  * return : true, if property has the value flag set, false otherwise
12548  * prop(in): property
12549  * value(in): value
12550  *
12551  */
12552 static bool
12553 is_att_prop_set (const int prop, const int value)
12554 {
12555  return ((prop & value) == value);
12556 }
12557 
12558 /*
12559  * reset_att_property_structure() - Resets the attribute change properties
12560  * structure, so that all properties are
12561  * marked as 'unchecked'
12562  *
12563  * attr_chg_properties(in): structure summarizing the changed properties of
12564  * attribute
12565  *
12566  */
12567 static void
12569 {
12570  int i = 0;
12571 
12572  assert (sizeof (attr_chg_properties->p) / sizeof (int) == NUM_ATT_CHG_PROP);
12573 
12574  for (i = 0; i < NUM_ATT_CHG_PROP; i++)
12575  {
12576  attr_chg_properties->p[i] = ATT_CHG_PROPERTY_NOT_CHECKED;
12577  }
12578 
12579  attr_chg_properties->constr_info = NULL;
12580  attr_chg_properties->new_constr_info = NULL;
12581  attr_chg_properties->att_id = -1;
12582  attr_chg_properties->name_space = ID_NULL;
12583  attr_chg_properties->new_name_space = ID_NULL;
12584  attr_chg_properties->class_has_subclass = false;
12585 }
12586 
12587 /*
12588  * get_att_order_from_def() - Retrieves the order properties (first,
12589  * after name) from the attribute definition node
12590  *
12591  * return : NO_ERROR, if success; error code otherwise
12592  * attribute(in): attribute definition node (PT_ATTR_DEF)
12593  * ord_first(out): true if definition contains 'FIRST' specification, false
12594  * otherwise
12595  * ord_after_name(out): name of column 'AFTER <col_name>'
12596  *
12597  */
12598 static int
12599 get_att_order_from_def (PT_NODE * attribute, bool * ord_first, const char **ord_after_name)
12600 {
12601  PT_NODE *ordering_info = NULL;
12602 
12603  assert (attribute->node_type == PT_ATTR_DEF);
12604 
12605  ordering_info = attribute->info.attr_def.ordering_info;
12606  if (ordering_info != NULL)
12607  {
12608  assert (ordering_info->node_type == PT_ATTR_ORDERING);
12609 
12610  *ord_first = ordering_info->info.attr_ordering.first;
12611 
12612  if (ordering_info->info.attr_ordering.after != NULL)
12613  {
12614  PT_NODE *const after_name = ordering_info->info.attr_ordering.after;
12615 
12616  assert (after_name->node_type == PT_NAME);
12617  *ord_after_name = after_name->info.name.original;
12618  assert (*ord_first == false);
12619  }
12620  else
12621  {
12622  *ord_after_name = NULL;
12623  /*
12624  * If we have no "AFTER name" then this must have been a "FIRST"
12625  * token
12626  */
12627  assert (*ord_first == true);
12628  }
12629  }
12630  else
12631  {
12632  *ord_first = false;
12633  *ord_after_name = NULL;
12634  }
12635 
12636  return NO_ERROR;
12637 }
12638 
12639 static int
12641 {
12642  int error = NO_ERROR;
12643  PT_TYPE_ENUM desired_type = attribute->type_enum;
12644  DB_DEFAULT_EXPR_TYPE on_update_expr_type = attribute->info.attr_def.on_update;
12645  PT_NODE *temp_ptval = NULL;
12646 
12647  if (on_update_expr_type == DB_DEFAULT_NONE)
12648  {
12649  return error;
12650  }
12651 
12652  PT_OP_TYPE op = pt_op_type_from_default_expr_type (on_update_expr_type);
12653 
12654  PT_NODE *on_update_default_expr = parser_make_expression (parser, op, NULL, NULL, NULL);
12655  if (on_update_default_expr == NULL)
12656  {
12658  return ER_FAILED;
12659  }
12660 
12661  on_update_default_expr = pt_semantic_type (parser, on_update_default_expr, NULL);
12662  if (on_update_default_expr == NULL)
12663  {
12664  return ER_FAILED;
12665  }
12666 
12667  on_update_default_expr = pt_semantic_check (parser, on_update_default_expr);
12668  if (on_update_default_expr == NULL)
12669  {
12670  return ER_FAILED;
12671  }
12672 
12673  on_update_default_expr->buffer_pos = attribute->buffer_pos;
12674  on_update_default_expr->line_number = attribute->line_number;
12675  on_update_default_expr->column_number = attribute->column_number;
12676 
12677  DB_VALUE on_update_val;
12678  db_make_null (&on_update_val);
12679 
12680  pt_evaluate_tree_having_serial (parser, on_update_default_expr, &on_update_val, 1);
12681  temp_ptval = pt_dbval_to_value (parser, &on_update_val);
12682  if (temp_ptval == NULL)
12683  {
12684  pt_report_to_ersys (parser, PT_SEMANTIC);
12685  error = er_errid ();
12686 
12687  pr_clear_value (&on_update_val);
12688  if (on_update_default_expr != NULL)
12689  {
12690  parser_free_node (parser, on_update_default_expr);
12691  }
12692  return error;
12693  }
12694 
12695  error = pt_coerce_value_for_default_value (parser, temp_ptval, temp_ptval, desired_type, attribute->data_type,
12696  on_update_expr_type);
12697 
12698  if (pt_has_error (parser))
12699  {
12700  /* forget previous one to set the better error */
12701  pt_reset_error (parser);
12702  }
12703 
12704  if (error != NO_ERROR)
12705  {
12706  const char *data_type_print;
12707  if (attribute->data_type != NULL)
12708  {
12709  data_type_print = pt_short_print (parser, attribute->data_type);
12710  }
12711  else
12712  {
12713  data_type_print = pt_show_type_enum ((PT_TYPE_ENUM) desired_type);
12714  }
12715 
12716  if (error == ER_IT_DATA_OVERFLOW)
12717  {
12719  pt_short_print (parser, on_update_default_expr), data_type_print);
12720  }
12721  else
12722  {
12724  pt_short_print (parser, on_update_default_expr), data_type_print);
12725  }
12726  }
12727 
12728  pr_clear_value (&on_update_val);
12729  if (temp_ptval != NULL)
12730  {
12731  parser_free_node (parser, temp_ptval);
12732  }
12733  if (on_update_default_expr != NULL)
12734  {
12735  parser_free_node (parser, on_update_default_expr);
12736  }
12737 
12738  return error;
12739 }
12740 
12741 /*
12742  * get_att_default_from_def() - Retrieves the default value property from the
12743  * attribute definition node
12744  *
12745  * return : NO_ERROR, if success; error code otherwise
12746  * parser(in): parser context
12747  * attribute(in): attribute definition node (PT_ATTR_DEF)
12748  * default_value(in/out): default value; this must be initially passed as
12749  * pointer to an allocated DB_VALUE; it is returned
12750  * as NULL if a DEFAULT is not specified for the
12751  * attribute, otherwise the DEFAULT value is returned
12752  * (the initially passed value is used for storage)
12753  * classname(in): If part of create class statement, this argument will be
12754  * the name of the class. We want to avoid fetching it since
12755  * it doesn't exist yet.
12756  *
12757  */
12758 static int
12760  const char *classname)
12761 {
12762  int error = NO_ERROR;
12763  PT_NODE *def_val = NULL, *initial_def_val = NULL;
12764  DB_DEFAULT_EXPR_TYPE def_expr_type;
12765  PT_TYPE_ENUM desired_type = attribute->type_enum;
12766  bool has_self_ref = false;
12767  const char *data_type_print;
12768 
12769  assert (attribute->node_type == PT_ATTR_DEF);
12770 
12771  if (attribute->info.attr_def.data_default == NULL)
12772  {
12773  *default_value = NULL;
12774  return NO_ERROR;
12775  }
12776 
12777  def_expr_type = attribute->info.attr_def.data_default->info.data_default.default_expr_type;
12778  def_val = attribute->info.attr_def.data_default->info.data_default.default_value;
12779  def_val = pt_semantic_check (parser, def_val);
12780  if (pt_has_error (parser) || def_val == NULL)
12781  {
12782  pt_report_to_ersys (parser, PT_SEMANTIC);
12783  error = er_errid ();
12784  goto exit;
12785  }
12786 
12787  if (classname != NULL && attribute->data_type != NULL)
12788  {
12789  PT_NODE *dt = NULL;
12790 
12791  for (dt = attribute->data_type; dt != NULL; dt = dt->next)
12792  {
12794  && intl_identifier_casecmp (dt->info.data_type.entity->info.name.original, classname) == 0)
12795  {
12796  has_self_ref = true;
12797  break;
12798  }
12799  }
12800  }
12801 
12802  initial_def_val = parser_copy_tree (parser, def_val);
12803  if (initial_def_val == NULL)
12804  {
12805  pt_report_to_ersys (parser, PT_SEMANTIC);
12806  error = er_errid ();
12807  goto exit;
12808  }
12809 
12810  if (has_self_ref)
12811  {
12812  /* We are creating a new class, and expected domain of default value has a self reference. Class cannot be
12813  * resolved yet, since it doesn't exist. It is only reserved and it has a temporary OID. Thus, we need to handle
12814  * it here and avoid fetching the object (which will hit assert due to temporary OID). We can only accept a NULL
12815  * default value, or if the expected type is a collection (that contains self references too), we can only accept
12816  * an empty set. */
12817  DB_VALUE *value;
12818 
12819  if (desired_type != PT_TYPE_OBJECT && !PT_IS_COLLECTION_TYPE (desired_type))
12820  {
12821  /* Should we even be here? */
12822  PT_INTERNAL_ERROR (parser, "Self referencing attribute unexpected type.");
12823  pt_report_to_ersys (parser, PT_SEMANTIC);
12824  error = er_errid ();
12825  goto exit;
12826  }
12827  /* Desired type either PT_TYPE_OBJECT or collection type. */
12828 
12829  /* We allow default value if: 1. Not a default expression. 2. Value is NULL or value is empty set and collection
12830  * type is expected. */
12831  value = &def_val->info.value.db_value;
12832  if (def_expr_type == DB_DEFAULT_NONE
12833  && (db_value_is_null (value)
12834  || (desired_type != PT_TYPE_OBJECT && TP_IS_SET_TYPE (value->domain.general_info.type)
12835  && value->data.set->set->size == 0)))
12836  {
12837  /* We can accept the default value. */
12838  pt_evaluate_tree (parser, def_val, *default_value, 1);
12839  }
12840  else
12841  {
12842  /* Cannot coerce. */
12843  if (desired_type == PT_TYPE_OBJECT)
12844  {
12846  pt_short_print (parser, initial_def_val), classname);
12847  }
12848  else
12849  {
12851  pt_short_print (parser, initial_def_val), pt_show_type_enum (desired_type));
12852  }
12853  pt_report_to_ersys (parser, PT_SEMANTIC);
12854  error = er_errid ();
12855  goto exit;
12856  }
12857  }
12858  else
12859  {
12860  /* try to coerce the default value into the attribute type */
12861  if (def_expr_type == DB_DEFAULT_NONE)
12862  {
12863  error = pt_coerce_value_for_default_value (parser, def_val, def_val, desired_type, attribute->data_type,
12864  def_expr_type);
12865  if (error != NO_ERROR)
12866  {
12867  goto exit_on_coerce_error;
12868  }
12869  }
12870  else
12871  {
12872  DB_VALUE src;
12873  PT_NODE *temp_val;
12874 
12875  db_make_null (&src);
12876 
12877  def_val = pt_semantic_type (parser, def_val, NULL);
12878  if (pt_has_error (parser) || def_val == NULL)
12879  {
12880  pt_report_to_ersys (parser, PT_SEMANTIC);
12881  error = er_errid ();
12882  goto exit;
12883  }
12884 
12885  pt_evaluate_tree_having_serial (parser, def_val, &src, 1);
12886  if (pt_has_error (parser))
12887  {
12888  pt_report_to_ersys (parser, PT_SEMANTIC);
12889  error = er_errid ();
12890  goto exit;
12891  }
12892 
12893  temp_val = pt_dbval_to_value (parser, &src);
12894  if (temp_val == NULL)
12895  {
12896  db_value_clear (&src);
12897  pt_report_to_ersys (parser, PT_SEMANTIC);
12898  error = er_errid ();
12899  goto exit;
12900  }
12901 
12902  error = pt_coerce_value_for_default_value (parser, temp_val, temp_val, desired_type, attribute->data_type,
12903  def_expr_type);
12904  db_value_clear (&src);
12905  temp_val->info.value.db_value_is_in_workspace = 0;
12906  parser_free_node (parser, temp_val);
12907  if (error != NO_ERROR)
12908  {
12909  goto exit_on_coerce_error;
12910  }
12911  }
12912 
12913  if (def_expr_type == DB_DEFAULT_NONE)
12914  {
12915  pt_evaluate_tree (parser, def_val, *default_value, 1);
12916  }
12917  else
12918  {
12919  *default_value = NULL;
12920  }
12921 
12922  if (pt_has_error (parser))
12923  {
12924  pt_report_to_ersys (parser, PT_SEMANTIC);
12925  error = er_errid ();
12926  goto exit;
12927  }
12928  }
12929 
12930 exit:
12931  if (initial_def_val != NULL)
12932  {
12933  parser_free_tree (parser, initial_def_val);
12934  }
12935  return error;
12936 
12937 exit_on_coerce_error:
12938  if (pt_has_error (parser))
12939  {
12940  /* forget previous one to set the better error */
12941  pt_reset_error (parser);
12942  }
12943 
12944  if (attribute->data_type != NULL)
12945  {
12946  data_type_print = pt_short_print (parser, attribute->data_type);
12947  }
12948  else
12949  {
12950  data_type_print = pt_show_type_enum ((PT_TYPE_ENUM) desired_type);
12951  }
12952 
12953  if (error == ER_IT_DATA_OVERFLOW)
12954  {
12956  pt_short_print (parser, initial_def_val), data_type_print);
12957  }
12958  else
12959  {
12961  pt_short_print (parser, initial_def_val), data_type_print);
12962  }
12963 
12964  if (initial_def_val != NULL)
12965  {
12966  parser_free_tree (parser, initial_def_val);
12967  }
12968 
12969  return error;
12970 }
12971 
12972 
12973 /*
12974  * get_hard_default_for_type() - Get a hard-coded default value for the given
12975  * type, or NULL if there is no such value.
12976  *
12977  * Note: the default is returned as a string, to be used in building queries.
12978  *
12979  * return : pointer to a static char array or NULL
12980  * type(in): the type, as stored in the parse tree
12981  *
12982  */
12983 static const char *
12985 {
12986  static const char *zero = "0";
12987  static const char *empty_str = "''";
12988  static const char *empty_n_str = "N''";
12989  static const char *empty_bit = "b'0'";
12990  static const char *empty_date = "DATE '01/01/0001'";
12991  static const char *empty_time = "TIME '00:00'";
12992  static const char *empty_datetime = "DATETIME '01/01/0001 00:00'";
12993  static const char *empty_dt_tz = "DATETIMETZ '01/01/0001 00:00 +00:00'";
12994  static const char *empty_dt_ltz = "DATETIMELTZ '01/01/0001 00:00 +00:00'";
12995  static const char *empty_json = "null";
12996 
12997  /* TODO : use db_value_domain_default instead, but make sure that db_value_domain_default is not using NULL DB_VALUE
12998  * as default for any type */
12999 
13000  /* Timestamp is interpreted as local and converted internally to UTC, so hard default value of Timestamp set to '1'
13001  * (Unix epoch time + 1). (0 means zero date) */
13002  static const char *empty_timestamp = "1";
13003  static const char *empty_set = "{}";
13004 
13005  switch (type)
13006  {
13007  case PT_TYPE_INTEGER:
13008  case PT_TYPE_SMALLINT:
13009  case PT_TYPE_MONETARY:
13010  case PT_TYPE_NUMERIC:
13011  case PT_TYPE_BIGINT:
13012  case PT_TYPE_FLOAT:
13013  case PT_TYPE_DOUBLE:
13014  return zero;
13015 
13016  case PT_TYPE_TIMESTAMP:
13017  case PT_TYPE_TIMESTAMPLTZ:
13018  case PT_TYPE_TIMESTAMPTZ:
13019  return empty_timestamp;
13020 
13021  case PT_TYPE_DATE:
13022  return empty_date;
13023 
13024  case PT_TYPE_TIME:
13025  return empty_time;
13026 
13027  case PT_TYPE_DATETIME:
13028  return empty_datetime;
13029  case PT_TYPE_DATETIMELTZ:
13030  return empty_dt_ltz;
13031  case PT_TYPE_DATETIMETZ:
13032  return empty_dt_tz;
13033 
13034  case PT_TYPE_CHAR:
13035  case PT_TYPE_VARCHAR:
13036  return empty_str;
13037 
13038  case PT_TYPE_VARNCHAR:
13039  case PT_TYPE_NCHAR:
13040  return empty_n_str;
13041 
13042  case PT_TYPE_SET:
13043  case PT_TYPE_MULTISET:
13044  case PT_TYPE_SEQUENCE:
13045  return empty_set;
13046 
13047  case PT_TYPE_BIT:
13048  case PT_TYPE_VARBIT:
13049  return empty_bit;
13050  case PT_TYPE_LOGICAL:
13051  case PT_TYPE_NONE:
13052  case PT_TYPE_MAYBE:
13053  case PT_TYPE_NA:
13054  case PT_TYPE_NULL:
13055  case PT_TYPE_STAR:
13056  case PT_TYPE_OBJECT:
13057  case PT_TYPE_MIDXKEY:
13058  case PT_TYPE_COMPOUND:
13059  case PT_TYPE_RESULTSET:
13060  case PT_TYPE_BLOB:
13061  case PT_TYPE_CLOB:
13062  case PT_TYPE_ELO:
13063  return NULL;
13064  case PT_TYPE_JSON:
13065  return empty_json;
13066 
13067  default:
13068  return NULL;
13069  }
13070 }
13071 
13072 
13073 /*
13074  * do_run_update_query_for_new_notnull_fields() - worker function for
13075  * do_update_new_notnull_cols_without_default().
13076  * It creates a complex UPDATE query and runs it.
13077  */
13078 static int
13080  int attr_count, MOP class_mop)
13081 {
13082  char *query, *q;
13083  int query_len, remaining, n;
13084 
13085  PT_NODE *attr;
13086  bool first = true;
13087  int error = NO_ERROR;
13088  int row_count = 0;
13089 
13090  assert (parser && alter && attr_list);
13091  assert (attr_count > 0);
13092 
13093  /* Allocate enough for each attribute's name, its default value, and for the "UPDATE table_name" part of the query.
13094  * 42 is more than the maximum length of any default value for an attribute, including three spaces, the coma sign
13095  * and an equal. */
13096 
13097  query_len = remaining = (attr_count + 1) * (DB_MAX_IDENTIFIER_LENGTH + 42);
13098  if (query_len > QUERY_MAX_SIZE)
13099  {
13100  ERROR1 (error, ER_UNEXPECTED, "Too many attributes.");
13101  return error;
13102  }
13103 
13104  q = query = (char *) malloc (query_len + 1);
13105  if (query == NULL)
13106  {
13107  ERROR1 (error, ER_OUT_OF_VIRTUAL_MEMORY, (size_t) (query_len + 1));
13108  return error;
13109  }
13110 
13111  query[0] = 0;
13112 
13113  /* Using UPDATE ALL to update the current class and all its children. */
13114 
13115  n = snprintf (q, remaining, "UPDATE ALL [%s] SET ", alter->info.alter.entity_name->info.name.original);
13116  if (n < 0)
13117  {
13118  ERROR1 (error, ER_UNEXPECTED, "Building UPDATE statement failed.");
13119  goto end;
13120  }
13121  remaining -= n;
13122  q += n;
13123 
13124  for (attr = attr_list; attr != NULL; attr = attr->next)
13125  {
13126  const char *sep = first ? "" : ", ";
13127  const char *hard_default = get_hard_default_for_type (attr->type_enum);
13128 
13129 
13130  n = snprintf (q, remaining, "%s[%s] = %s", sep, attr->info.attr_def.attr_name->info.name.original, hard_default);
13131  if (n < 0)
13132  {
13133  ERROR1 (error, ER_UNEXPECTED, "Building UPDATE statement failed.");
13134  goto end;
13135  }
13136  remaining -= n;
13137  q += n;
13138 
13139  first = false;
13140  }
13141 
13142  /* Now just RUN thew query */
13143 
13144  error = do_run_update_query_for_class (query, class_mop, &row_count);
13145 
13146 
13147 end:
13148  if (query)
13149  {
13150  free_and_init (query);
13151  }
13152 
13153  return error;
13154 }
13155 
13156 /*
13157  * do_run_update_query_for_new_default_expression_fields() - worker function for
13158  * do_update_new_cols_with_default_expression().
13159  *
13160  * parser(in): parser
13161  * alter(in): alter node
13162  * attr_list(in) attribute nodes list
13163  * attr_count(int): count attribute nodes
13164  * class_mop(in): class mop
13165  *
13166  * Note : It creates a complex UPDATE query and runs it.
13167  */
13168 static int
13170  int attr_count, MOP class_mop)
13171 {
13172  char *query, *q;
13173  int query_len, remaining, n;
13174  PT_NODE *attr;
13175  bool first = true;
13176  int error = NO_ERROR;
13177  int row_count = 0;
13178 
13179  assert (parser && alter && attr_list);
13180  assert (attr_count > 0);
13181 
13182  /* Allocate enough for each attribute's name, its default value, and for the "UPDATE table_name" part of the query.
13183  * 100 is more than the maximum length of any default value for an attribute, including three spaces, the comma sign
13184  * and an equal. */
13185 
13186  query_len = remaining = (attr_count + 1) * (DB_MAX_IDENTIFIER_LENGTH + 100);
13187  if (query_len > QUERY_MAX_SIZE)
13188  {
13189  ERROR1 (error, ER_UNEXPECTED, "Too many attributes.");
13190  return error;
13191  }
13192 
13193  q = query = (char *) malloc (query_len + 1);
13194  if (query == NULL)
13195  {
13196  ERROR1 (error, ER_OUT_OF_VIRTUAL_MEMORY, (size_t) (query_len + 1));
13197  return error;
13198  }
13199 
13200  query[0] = 0;
13201 
13202  /* Using UPDATE ALL to update the current class and all its children. */
13203  n = snprintf (q, remaining, "UPDATE ALL [%s] SET ", alter->info.alter.entity_name->info.name.original);
13204  if (n < 0)
13205  {
13206  ERROR1 (error, ER_UNEXPECTED, "Building UPDATE statement failed.");
13207  goto end;
13208  }
13209  remaining -= n;
13210  q += n;
13211 
13212  for (attr = attr_list; attr != NULL; attr = attr->next)
13213  {
13214  const char *sep = first ? "" : ", ";
13215  char *data_default;
13216 
13217  data_default = parser_print_tree (parser, attr->info.attr_def.data_default->info.data_default.default_value);
13218  if (data_default == NULL)
13219  {
13220  continue;
13221  }
13222 
13223  n = snprintf (q, remaining, "%s[%s] = %s", sep, attr->info.attr_def.attr_name->info.name.original, data_default);
13224  if (n < 0)
13225  {
13226  ERROR1 (error, ER_UNEXPECTED, "Building UPDATE statement failed.");
13227  goto end;
13228  }
13229  remaining -= n;
13230  q += n;
13231 
13232  first = false;
13233  }
13234 
13235  /* Now just RUN the query */
13236  error = do_run_update_query_for_class (query, class_mop, &row_count);
13237 
13238 end:
13239  if (query)
13240  {
13241  free_and_init (query);
13242  }
13243 
13244  return error;
13245 }
13246 
13247 /*
13248  * is_attribute_primary_key() - Returns true if the attribute given is part
13249  * of the primary key of the table.
13250  *
13251  *
13252  * return : true or false
13253  * class_name(in): the class name
13254  * attr_name(in): the attribute name
13255  *
13256  */
13257 static bool
13258 is_attribute_primary_key (const char *class_name, const char *attr_name)
13259 {
13260  DB_ATTRIBUTE *db_att = NULL;
13261 
13262  if (class_name == NULL || attr_name == NULL)
13263  {
13264  return false;
13265  }
13266 
13267  db_att = db_get_attribute_by_name (class_name, attr_name);
13268 
13269  if (db_att && db_attribute_is_primary_key (db_att))
13270  {
13271  return true;
13272  }
13273  return false;
13274 }
13275 
13276 
13277 
13278 
13279 /*
13280  * do_update_new_notnull_cols_without_default()
13281  * Populates the newly added columns with hard-coded defaults.
13282  *
13283  * Used only on ALTER TABLE ... ADD COLUMN, and only AFTER the operation has
13284  * been performed (i.e. the columns have been added to the schema, even
13285  * though the transaction has not been committed).
13286  *
13287  * IF the clause has added columns that:
13288  * 1. have no default value AND
13289  * 2a. have the NOT NULL constraint OR
13290  * 2b. are part of the PRIMARY KEY
13291  * THEN try to fill them with a hard-coded default (zero, empty string etc.)
13292  *
13293  * This is done in MySQL compatibility mode, to ensure consistency: otherwise
13294  * columns with the NOT NULL constraint would have ended up being filled
13295  * with NULL as a default.
13296  *
13297  * NOTE: there are types (such as OBJECT) that do not have a "zero"-like
13298  * value, and if we encounter one of these, we block the entire operation.
13299  *
13300  * return: Error code if operation fails or if one of the attributes to add
13301  * is of type OBJECT, with NOT NULL and no default value.
13302  * parser(in): Parser context
13303  * alter(in): Parse tree of the statement
13304  */
13305 static int
13307 {
13308  PT_NODE *relevant_attrs = NULL;
13309  int error = NO_ERROR;
13310  int attr_count = 0;
13311 
13312  PT_NODE *attr = NULL;
13313  PT_NODE *save = NULL;
13314  PT_NODE *copy = NULL;
13315 
13316  assert (alter->node_type == PT_ALTER);
13317  assert (alter->info.alter.code == PT_ADD_ATTR_MTHD);
13318 
13319  /* Look for attributes that: have NOT NULL, do not have a DEFAULT and their type has a "hard" default. Also look for
13320  * attributes that are primary keys Throw an error for types that do not have a hard default (like objects). */
13321  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
13322  {
13323  const bool is_not_null = (attr->info.attr_def.constrain_not_null != 0);
13324  const bool has_default = (attr->info.attr_def.data_default != NULL);
13325  const bool is_pri_key = is_attribute_primary_key (alter->info.alter.entity_name->info.name.original,
13327  if (has_default)
13328  {
13329  continue;
13330  }
13331 
13332  if (!is_not_null && !is_pri_key)
13333  {
13334  continue;
13335  }
13336 
13337  if (!db_class_has_instance (class_mop))
13338  {
13339  continue;
13340  }
13341 
13343  {
13345  goto end;
13346  }
13347 
13348  if (get_hard_default_for_type (attr->type_enum) == NULL)
13349  {
13351  goto end;
13352  }
13353 
13354  /* now we have an interesting node. Copy it in our list. */
13355  attr_count++;
13356  save = attr->next;
13357  attr->next = NULL;
13358  copy = parser_copy_tree (parser, attr);
13359  if (copy == NULL)
13360  {
13361  attr->next = save;
13363  parser_free_tree (parser, relevant_attrs);
13364  goto end;
13365  }
13366  relevant_attrs = parser_append_node (copy, relevant_attrs);
13367  attr->next = save;
13368  }
13369 
13370  if (relevant_attrs == NULL)
13371  {
13372  /* no interesting attribute found, just leave */
13373  goto end;
13374  }
13375 
13376  /* RUN an UPDATE query comprising all the attributes */
13377 
13378  error = do_run_update_query_for_new_notnull_fields (parser, alter, relevant_attrs, attr_count, class_mop);
13379  if (error != NO_ERROR)
13380  {
13381  goto end;
13382  }
13383 
13384 
13385 end:
13386  if (relevant_attrs != NULL)
13387  {
13388  parser_free_tree (parser, relevant_attrs);
13389  }
13390 
13391  return error;
13392 }
13393 
13394 /*
13395  * do_update_new_cols_with_default_expression() : Populates the newly added columns with default expression
13396  *
13397  * return: error code
13398  *
13399  * parser(in): Parser context
13400  * alter(in): Parse tree of the statement
13401  *
13402  * Note: Used only on ALTER TABLE ... ADD COLUMN, and only AFTER the operation has been performed (i.e. the columns
13403  * have been added to the schema, even though the transaction has not been committed).
13404  *
13405  */
13406 static int
13408 {
13409  PT_NODE *relevant_attrs = NULL;
13410  int error = NO_ERROR;
13411  int attr_count = 0;
13412  PT_NODE *pt_data_default = NULL;
13413  PT_NODE *attr = NULL;
13414  PT_NODE *save = NULL;
13415  PT_NODE *copy = NULL;
13416  DB_DEFAULT_EXPR default_expr;
13417 
13418  assert (alter->node_type == PT_ALTER);
13419  assert (alter->info.alter.code == PT_ADD_ATTR_MTHD);
13420 
13421  /* Look for attributes that have a DEFAULT expression. */
13422  for (attr = alter->info.alter.alter_clause.attr_mthd.attr_def_list; attr; attr = attr->next)
13423  {
13424  pt_data_default = attr->info.attr_def.data_default;
13425  if (pt_data_default == NULL)
13426  {
13427  /* don't have default clause */
13428  continue;
13429  }
13430 
13431  pt_get_default_expression_from_data_default_node (parser, pt_data_default, &default_expr);
13432  if (default_expr.default_expr_type == DB_DEFAULT_NONE)
13433  {
13434  /* don't have default expression */
13435  continue;
13436  }
13437 
13438  if (!db_is_class (class_mop) || !db_class_has_instance (class_mop))
13439  {
13440  continue;
13441  }
13442 
13443  /* now we have an interesting node. Copy it in our list. */
13444  attr_count++;
13445  save = attr->next;
13446  attr->next = NULL;
13447  copy = parser_copy_tree (parser, attr);
13448  if (copy == NULL)
13449  {
13450  attr->next = save;
13452  parser_free_tree (parser, relevant_attrs);
13453  goto end;
13454  }
13455  relevant_attrs = parser_append_node (copy, relevant_attrs);
13456  attr->next = save;
13457  }
13458 
13459  if (relevant_attrs == NULL)
13460  {
13461  /* no interesting attribute found, just leave */
13462  goto end;
13463  }
13464 
13465  /* RUN an UPDATE query comprising all the attributes */
13466  error = do_run_update_query_for_new_default_expression_fields (parser, alter, relevant_attrs, attr_count, class_mop);
13467  if (error != NO_ERROR)
13468  {
13469  goto end;
13470  }
13471 
13472 end:
13473  if (relevant_attrs != NULL)
13474  {
13475  parser_free_tree (parser, relevant_attrs);
13476  }
13477 
13478  return error;
13479 }
13480 
13481 /*
13482  * do_run_upgrade_instances_domain() - proxy function for server function
13483  * 'xlocator_upgrade_instances_domain'
13484  *
13485  * parser(in):
13486  * p_class_oid(in): class OID
13487  * att_id(in): constraint list
13488  */
13489 static int
13491 {
13492  int error = NO_ERROR;
13493 
13494  assert (parser != NULL);
13495  assert (p_class_oid != NULL);
13496  assert (att_id >= 0);
13497 
13498  error = locator_upgrade_instances_domain (p_class_oid, att_id);
13499 
13500  return error;
13501 
13502 }
13503 
13504 /*
13505  * do_drop_att_constraints() - drops constraints in list associated with a
13506  * class
13507  * class_mop(in): class object
13508  * constr_info_list(in): constraint list
13509  *
13510  * Note: Warning : Only non-unique, unique, and primary constraints are
13511  * handled; FOREIGN KEY constraints are not supported
13512  */
13513 static int
13514 do_drop_att_constraints (MOP class_mop, SM_CONSTRAINT_INFO * constr_info_list)
13515 {
13516  int error = NO_ERROR;
13517 
13518  SM_CONSTRAINT_INFO *constr;
13519 
13520  for (constr = constr_info_list; constr != NULL; constr = constr->next)
13521  {
13523  {
13524  error =
13525  sm_drop_constraint (class_mop, constr->constraint_type, constr->name, (const char **) constr->att_names, 0,
13526  false);
13527  if (error != NO_ERROR)
13528  {
13529  goto error_exit;
13530  }
13531  }
13533  {
13534  error = sm_drop_index (class_mop, constr->name);
13535  if (error != NO_ERROR)
13536  {
13537  goto error_exit;
13538  }
13539  }
13540  }
13541 error_exit:
13542  return error;
13543 }
13544 
13545 /*
13546  * do_recreate_att_constraints() - (re-)creates constraints in list associated
13547  * with a class
13548  * class_mop(in): class object
13549  * constr_info_list(in): constraint list
13550  *
13551  * Note: Warning : Only non-unique, unique, and primary constraints are
13552  * handled; FOREIGN KEY constraints are not supported
13553  */
13554 static int
13555 do_recreate_att_constraints (MOP class_mop, SM_CONSTRAINT_INFO * constr_info_list)
13556 {
13557  int error = NO_ERROR;
13558 
13559  SM_CONSTRAINT_INFO *constr;
13560 
13561  for (constr = constr_info_list; constr != NULL; constr = constr->next)
13562  {
13564  {
13565  error =
13566  sm_add_constraint (class_mop, constr->constraint_type, constr->name, (const char **) constr->att_names,
13567  constr->asc_desc, constr->prefix_length, false, constr->filter_predicate,
13568  constr->func_index_info, constr->comment, constr->index_status);
13569 
13570  if (error != NO_ERROR)
13571  {
13572  goto error_exit;
13573  }
13574  }
13575  }
13576 
13577 error_exit:
13578  return error;
13579 }
13580 
13581 /*
13582  * check_change_attribute() - Checks if an attribute change attribute is
13583  * possible, in the context of the requested
13584  * change mode
13585  * return: Error code
13586  * parser(in): Parser context
13587  * ctemplate(in/out): Class template
13588  * attribute(in/out): Attribute to add
13589  */
13590 static int
13591 check_change_attribute (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_NODE * attribute, PT_NODE * old_name_node,
13592  PT_NODE ** pointer_constraints, SM_ATTR_PROP_CHG * attr_chg_prop, SM_ATTR_CHG_SOL * change_mode)
13593 {
13595  int meta = 0, shared = 0;
13596  int error = NO_ERROR;
13597  const char *old_name = NULL;
13598  const char *attr_name = NULL;
13599  bool new_attempt = true;
13600  DB_VALUE def_value;
13601  DB_VALUE *ptr_def = &def_value;
13602  PT_NODE *cnstr;
13603  PT_NODE *not_null_node = NULL, *pk_node = NULL, *previous_node = NULL, *tmp_node = NULL;
13604  PT_NODE *constraints = *pointer_constraints;
13605 
13606  assert (attr_chg_prop != NULL);
13607  assert (change_mode != NULL);
13608 
13609  assert (attribute->node_type == PT_ATTR_DEF);
13610 
13611  *change_mode = SM_ATTR_CHG_ONLY_SCHEMA;
13612 
13613  db_make_null (&def_value);
13614 
13615  attr_name = get_attr_name (attribute);
13616 
13617  meta = (attribute->info.attr_def.attr_type == PT_META_ATTR);
13618  shared = (attribute->info.attr_def.attr_type == PT_SHARED);
13619  name_space = (meta) ? ID_CLASS_ATTRIBUTE : ((shared) ? ID_SHARED_ATTRIBUTE : ID_ATTRIBUTE);
13620  attr_chg_prop->name_space = name_space;
13621 
13622  /* check if class has subclasses : 'users' of class may be subclass, but also partitions of class */
13623  if (ctemplate->current->users != NULL && ctemplate->partition == NULL)
13624  {
13625  attr_chg_prop->class_has_subclass = true;
13626  }
13627 
13628  error = check_default_on_update_clause (parser, attribute);
13629  if (error != NO_ERROR)
13630  {
13631  goto exit;
13632  }
13633 
13634  error = get_att_default_from_def (parser, attribute, &ptr_def, NULL);
13635  if (error != NO_ERROR)
13636  {
13637  goto exit;
13638  }
13639  /* ptr_def is either NULL or pointing to address of def_value */
13640  assert (ptr_def == NULL || ptr_def == &def_value);
13641 
13642  if (ptr_def && DB_IS_NULL (ptr_def)
13644  {
13645  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
13646  {
13647  if (cnstr->info.constraint.type == PT_CONSTRAIN_NOT_NULL)
13648  {
13649  /* don't allow a default value of NULL for NOT NULL constrained columns */
13652  goto exit;
13653  }
13654  else if (cnstr->info.constraint.type == PT_CONSTRAIN_PRIMARY_KEY)
13655  {
13656  /* don't allow a default value of NULL in new PK constraint */
13659  goto exit;
13660  }
13661  }
13662  }
13663 
13664  /* Try to find out the combined constraints definition of NOT_NULL and PK */
13665  for (cnstr = constraints; cnstr != NULL; tmp_node = cnstr, cnstr = cnstr->next)
13666  {
13667  if (cnstr->info.constraint.type == PT_CONSTRAIN_NOT_NULL)
13668  {
13669  not_null_node = cnstr;
13670  previous_node = tmp_node;
13671  }
13672  else if (cnstr->info.constraint.type == PT_CONSTRAIN_PRIMARY_KEY)
13673  {
13674  pk_node = cnstr;
13675  }
13676 
13677  if (not_null_node != NULL && pk_node != NULL)
13678  {
13679  break;
13680  }
13681  }
13682 
13683  /* Exclude/remove the duplicated NOT_NULL constraint which would be implicitly defined by PK. */
13684  if (not_null_node != NULL && pk_node != NULL)
13685  {
13686  if (previous_node == NULL)
13687  {
13688  /* At the head of the list */
13689  constraints = not_null_node->next;
13690  *pointer_constraints = constraints;
13691  }
13692  else
13693  {
13694  previous_node->next = not_null_node->next;
13695  }
13696 
13697  not_null_node->next = NULL;
13698  parser_free_node (parser, not_null_node);
13699  }
13700 
13701  error = build_attr_change_map (parser, ctemplate, attribute, old_name_node, constraints, attr_chg_prop);
13702  if (error != NO_ERROR)
13703  {
13704  goto exit;
13705  }
13706 
13707  if (!is_att_property_structure_checked (attr_chg_prop))
13708  {
13709  assert (false);
13710  error = ER_UNEXPECTED;
13711  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Not all properties are checked.");
13712  goto exit;
13713  }
13714 
13715  /* get new name */
13716  if (old_name_node != NULL)
13717  {
13718  assert (old_name_node->node_type == PT_NAME);
13719  old_name = old_name_node->info.name.original;
13720  assert (old_name != NULL);
13721 
13722  /* attr_name is supplied using the ATTR_DEF node and it means: for MODIFY syntax : current and unchanged name
13723  * (attr_name) for CHANGE syntax : new name of the attribute (new_name) */
13724  if (is_att_prop_set (attr_chg_prop->p[P_NAME], ATT_CHG_PROPERTY_DIFF))
13725  {
13726  attr_name = old_name;
13727  }
13728  else
13729  {
13730  attr_name = old_name;
13731  }
13732  }
13733 
13734  if (!is_att_change_needed (attr_chg_prop))
13735  {
13737  error = NO_ERROR;
13738  /* just a warning : nothing to do */
13739  *change_mode = SM_ATTR_CHG_NOT_NEEDED;
13740  goto exit;
13741  }
13742 
13743  /* check if domain type is indexable : for constraints that may be acquired with ALTER.. CHANGE, check both if the
13744  * constraint is present in either old or new schema; if constraint cannot be acquired with CHANGE, check only if it
13745  * is present with old schema */
13746  /* TODO : this should be done at semantic check for all attribute definition nodes (including at table creation) */
13754  {
13755  if (!tp_valid_indextype (pt_type_enum_to_db (attribute->type_enum)))
13756  {
13757  error = ER_SM_INVALID_INDEX_TYPE;
13759  goto exit;
13760  }
13761  }
13762 
13763  /* check if attribute change is allowed : */
13764  error = check_att_chg_allowed (attr_name, attribute->type_enum, attr_chg_prop, *change_mode, false, &new_attempt);
13765  if (error != NO_ERROR && new_attempt)
13766  {
13767  *change_mode = SM_ATTR_CHG_WITH_ROW_UPDATE;
13768  error = check_att_chg_allowed (attr_name, attribute->type_enum, attr_chg_prop, *change_mode, false, &new_attempt);
13769  if (error != NO_ERROR && new_attempt)
13770  {
13771  *change_mode = SM_ATTR_CHG_BEST_EFFORT;
13772  error =
13773  check_att_chg_allowed (attr_name, attribute->type_enum, attr_chg_prop, *change_mode, true, &new_attempt);
13774  if (error != NO_ERROR)
13775  {
13776  goto exit;
13777  }
13778  }
13779  }
13780 
13781 exit:
13782  db_value_clear (&def_value);
13783  return error;
13784 }
13785 
13786 /*
13787  * check_change_class_collation() - Checks if it is necessary to update the
13788  * default collation of a class
13789  * return: Error code
13790  * parser(in): Parser context
13791  * ctemplate(in/out): Class template
13792  * alter(in): Node containing desired collation and codeset
13793  */
13794 static int
13795 check_change_class_collation (PARSER_CONTEXT * parser, DB_CTMPL * ctemplate, PT_ALTER_INFO * alter, bool * need_update,
13796  int *collation_id)
13797 {
13798  int error = NO_ERROR;
13799  int cs = -1, coll_id = -1;
13800 
13801  assert (ctemplate->current != NULL);
13802 
13803  *need_update = false;
13804  cs = alter->alter_clause.collation.charset;
13805  coll_id = alter->alter_clause.collation.collation_id;
13806 
13807  /* check if codeset, collation or both are set, and check if it is necessary to update the default collation of the
13808  * class */
13809  if (coll_id != -1)
13810  {
13811  if (ctemplate->current->collation_id != coll_id)
13812  {
13813  *need_update = true;
13814  }
13815  else
13816  {
13817  *need_update = false;
13818  }
13819  *collation_id = coll_id;
13820  }
13821  else
13822  {
13823  LANG_COLLATION *lc;
13824  assert (cs != -1);
13825 
13826  lc = lang_get_collation (ctemplate->current->collation_id);
13827  assert (lc != NULL);
13828 
13829  if ((lc->codeset != cs) || (LANG_GET_BINARY_COLLATION (cs) != ctemplate->current->collation_id))
13830  {
13831  *need_update = true;
13832  *collation_id = LANG_GET_BINARY_COLLATION (cs);
13833  }
13834  }
13835 
13836  return error;
13837 }
13838 
13839 /*
13840  * sort_constr_info_list - sorts the list of constraints in the order:
13841  * - non-unique indexes
13842  * - unique indexes
13843  * - primary keys
13844  * - foreign key constraints
13845  * return: none
13846  * source(in/out): list to sort
13847  */
13848 
13849 static int
13851 {
13852  int error = NO_ERROR;
13853  SM_CONSTRAINT_INFO *sorted, *next, *prev, *ins, *found, *constr;
13854  int constr_order[7] = { 0 };
13855 
13856  assert (orig_list != NULL);
13857 
13858  if (*orig_list == NULL)
13859  {
13860  return error;
13861  }
13862 
13863  /* TODO change this to compile-time asserts when we have such a mechanism. */
13866 
13867  constr_order[DB_CONSTRAINT_UNIQUE] = 2;
13868  constr_order[DB_CONSTRAINT_INDEX] = 0;
13869  constr_order[DB_CONSTRAINT_NOT_NULL] = 6;
13870  constr_order[DB_CONSTRAINT_REVERSE_UNIQUE] = 2;
13871  constr_order[DB_CONSTRAINT_REVERSE_INDEX] = 0;
13872  constr_order[DB_CONSTRAINT_PRIMARY_KEY] = 4;
13873  constr_order[DB_CONSTRAINT_FOREIGN_KEY] = 5;
13874 
13875  sorted = NULL;
13876  for (constr = *orig_list, next = NULL; constr != NULL; constr = next)
13877  {
13878  next = constr->next;
13879 
13880  for (ins = sorted, prev = NULL, found = NULL; ins != NULL && found == NULL; ins = ins->next)
13881  {
13882  if (constr->constraint_type < 0 || constr->constraint_type > DB_CONSTRAINT_FOREIGN_KEY
13884  {
13885  assert (false);
13886  return ER_UNEXPECTED;
13887  }
13888 
13889  if (constr_order[constr->constraint_type] < constr_order[ins->constraint_type])
13890  {
13891  found = ins;
13892  }
13893  else
13894  {
13895  prev = ins;
13896  }
13897  }
13898 
13899  constr->next = found;
13900  if (prev == NULL)
13901  {
13902  sorted = constr;
13903  }
13904  else
13905  {
13906  prev->next = constr;
13907  }
13908  }
13909  *orig_list = sorted;
13910 
13911  return error;
13912 }
13913 
13914 /*
13915  * save_constraint_info_from_pt_node() - Saves the information necessary to
13916  * create a constraint from a PT_CONSTRAINT_INFO node
13917  *
13918  * return: NO_ERROR on success, non-zero for ERROR
13919  * save_info(in/out): The information saved
13920  * pt_constr(in): The constraint node to be saved
13921  *
13922  * Note :this function handles only constraints for single
13923  * attributes : PT_CONSTRAIN_NOT_NULL, PT_CONSTRAIN_UNIQUE,
13924  * PT_CONSTRAIN_PRIMARY_KEY.
13925  * Foreign keys, indexes on multiple columns are not supported and also
13926  * 'prefix_length' and ASC/DESC info is not supported.
13927  * It process only one node; the 'next' PT_NODE is ignored.
13928  */
13929 static int
13930 save_constraint_info_from_pt_node (SM_CONSTRAINT_INFO ** save_info, const PT_NODE * const pt_constr)
13931 {
13932  int error_code = NO_ERROR;
13933  SM_CONSTRAINT_INFO *new_constraint = NULL;
13934  PT_NODE *constr_att_name = NULL;
13935 
13936  assert (pt_constr->node_type == PT_CONSTRAINT);
13937 
13938  new_constraint = (SM_CONSTRAINT_INFO *) calloc (1, sizeof (SM_CONSTRAINT_INFO));
13939  if (new_constraint == NULL)
13940  {
13941  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
13942  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, sizeof (SM_CONSTRAINT_INFO));
13943  goto error_exit;
13944  }
13945 
13946  /* set NULL, expect to generate constraint name */
13947  new_constraint->name = NULL;
13948 
13949  switch (pt_constr->info.constraint.type)
13950  {
13952  constr_att_name = pt_constr->info.constraint.un.primary_key.attrs;
13953  new_constraint->constraint_type = DB_CONSTRAINT_PRIMARY_KEY;
13954  break;
13955  case PT_CONSTRAIN_UNIQUE:
13956  constr_att_name = pt_constr->info.constraint.un.unique.attrs;
13957  new_constraint->constraint_type = DB_CONSTRAINT_UNIQUE;
13958  break;
13959  case PT_CONSTRAIN_NOT_NULL:
13960  constr_att_name = pt_constr->info.constraint.un.not_null.attr;
13961  new_constraint->constraint_type = DB_CONSTRAINT_NOT_NULL;
13962  break;
13963  default:
13964  assert (false);
13965  }
13966 
13967  if (constr_att_name->next != NULL)
13968  {
13969  error_code = ER_UNEXPECTED;
13970  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, "Constraint name should be the last attribute.");
13971  goto error_exit;
13972  }
13973 
13974  new_constraint->att_names = (char **) calloc (1 + 1, sizeof (char *));
13975  if (new_constraint->att_names == NULL)
13976  {
13977  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
13978  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, (1 + 1) * sizeof (char *));
13979  goto error_exit;
13980  }
13981 
13982  assert (constr_att_name->info.name.original != NULL);
13983 
13984  new_constraint->att_names[0] = strdup (constr_att_name->info.name.original);
13985  if (new_constraint->att_names[0] == NULL)
13986  {
13987  error_code = ER_OUT_OF_VIRTUAL_MEMORY;
13988  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1,
13989  (size_t) (strlen (constr_att_name->info.name.original) + 1));
13990  goto error_exit;
13991  }
13992 
13993  new_constraint->att_names[1] = NULL;
13994 
13995  assert (new_constraint->next == NULL);
13996  while ((*save_info) != NULL)
13997  {
13998  save_info = &((*save_info)->next);
13999  }
14000  *save_info = new_constraint;
14001 
14002  return error_code;
14003 
14004 error_exit:
14005  if (new_constraint != NULL)
14006  {
14007  sm_free_constraint_info (&new_constraint);
14008  }
14009  return error_code;
14010 }
14011 
14012 /*
14013  * do_check_rows_for_null() - checks if a column has NULL values
14014  * return: NO_ERROR or error code
14015  *
14016  * class_mop(in): class to check
14017  * att_name(in): name of column to check
14018  * has_nulls(out): true if column has rows with NULL
14019  *
14020  */
14021 int
14022 do_check_rows_for_null (MOP class_mop, const char *att_name, bool * has_nulls)
14023 {
14024  int error = NO_ERROR;
14025  int n = 0;
14026  int stmt_id = 0;
14027  DB_SESSION *session = NULL;
14028  DB_QUERY_RESULT *result = NULL;
14029  const char *class_name = NULL;
14030  char query[2 * SM_MAX_IDENTIFIER_LENGTH + 50] = { 0 };
14031  DB_VALUE count;
14032 
14033  assert (class_mop != NULL);
14034  assert (att_name != NULL);
14035  assert (has_nulls != NULL);
14036 
14037  *has_nulls = false;
14038  db_make_null (&count);
14039 
14040  class_name = db_get_class_name (class_mop);
14041  if (class_name == NULL)
14042  {
14043  error = ER_UNEXPECTED;
14044  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Cannot get class name of mop.");
14045  goto end;
14046  }
14047 
14048  n =
14049  snprintf (query, sizeof (query) / sizeof (char), "SELECT count(*) FROM [%s] WHERE [%s] IS NULL", class_name,
14050  att_name);
14051  if (n < 0 || (n == sizeof (query) / sizeof (char)))
14052  {
14053  error = ER_UNEXPECTED;
14054  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Building SELECT statement failed.");
14055  goto end;
14056  }
14057 
14058  /* RUN the query */
14059  session = db_open_buffer (query);
14060  if (session == NULL)
14061  {
14062  assert (er_errid () != NO_ERROR);
14063  error = er_errid ();
14064  goto end;
14065  }
14066 
14067  if (db_get_errors (session) || db_statement_count (session) != 1)
14068  {
14069  assert (er_errid () != NO_ERROR);
14070  error = er_errid ();
14071  goto end;
14072  }
14073 
14074  stmt_id = db_compile_statement (session);
14075  if (stmt_id != 1)
14076  {
14077  assert (er_errid () != NO_ERROR);
14078  error = er_errid ();
14079  goto end;
14080  }
14081 
14082  error = db_execute_statement_local (session, stmt_id, &result);
14083  if (error < 0)
14084  {
14085  goto end;
14086  }
14087 
14088  if (result == NULL)
14089  {
14090  error = ER_UNEXPECTED;
14091  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "Executing internal query failed.");
14092  goto end;
14093  }
14094 
14095  error = db_query_first_tuple (result);
14096  if (error != NO_ERROR)
14097  {
14098  goto end;
14099  }
14100 
14101  assert (result->query_type->db_type == DB_TYPE_INTEGER);
14102 
14103  error = db_query_set_copy_tplvalue (result, 0 /* peek */ );
14104  if (error != NO_ERROR)
14105  {
14106  goto end;
14107  }
14108 
14109  error = db_query_get_tuple_value (result, 0, &count);
14110  if (error != NO_ERROR)
14111  {
14112  goto end;
14113  }
14114 
14115  assert (!DB_IS_NULL (&count));
14117 
14118  if (db_get_int (&count) > 0)
14119  {
14120  *has_nulls = true;
14121  }
14122 
14123 end:
14124  if (result != NULL)
14125  {
14126  db_query_end (result);
14127  }
14128  if (session != NULL)
14129  {
14130  db_close_session (session);
14131  }
14132  db_value_clear (&count);
14133 
14134  return error;
14135 }
14136 
14137 /*
14138  * do_run_update_query_for_class() - runs an UPDATE query.
14139  * return: NO_ERROR or error code
14140  *
14141  * query(in): query statement
14142  * class_mop(in): class to check
14143  * suppress_replication(in): force suppress replication
14144  * row_count(out): count of updated rows
14145  *
14146  */
14147 static int
14148 do_run_update_query_for_class (char *query, MOP class_mop, int *row_count)
14149 {
14150  int error = NO_ERROR;
14151  DB_SESSION *session = NULL;
14152  int stmt_id = 0;
14153  bool save_tr_state = tr_get_execution_state ();
14154  bool check_tr_state = false;
14155 
14156  assert (query != NULL);
14157  assert (class_mop != NULL);
14158  assert (row_count != NULL);
14159 
14160  *row_count = -1;
14161 
14163  session = db_open_buffer (query);
14164  if (session == NULL)
14165  {
14166  assert (er_errid () != NO_ERROR);
14167  error = er_errid ();
14168  goto end;
14169  }
14170 
14171  if (db_get_errors (session) || db_statement_count (session) != 1)
14172  {
14173  assert (er_errid () != NO_ERROR);
14174  error = er_errid ();
14175  goto end;
14176  }
14177 
14178  stmt_id = db_compile_statement (session);
14179  if (stmt_id != 1)
14180  {
14181  assert (er_errid () != NO_ERROR);
14182  error = er_errid ();
14183  goto end;
14184  }
14185 
14186  /*
14187  * We are going to perform an UPDATE on the table. We need to disable
14188  * the triggers because these are not UPDATES that the user required
14189  * explicitly.
14190  */
14191 
14192  check_tr_state = tr_set_execution_state (false);
14193  assert (check_tr_state == save_tr_state);
14194 
14195  error = db_execute_statement_local (session, stmt_id, NULL);
14196  if (error < 0)
14197  {
14198  goto end;
14199  }
14200 
14201  error = NO_ERROR;
14202 
14203  /* Invalidate the XASL cache by using the touch function */
14204  assert (class_mop);
14205  error = sm_touch_class (class_mop);
14206  if (error != NO_ERROR)
14207  {
14208  goto end;
14209  }
14210 
14211  *row_count = db_get_parser (session)->execution_values.row_count;
14212 
14213 end:
14215 
14216  if (session != NULL)
14217  {
14218  db_free_query (session);
14219  db_close_session (session);
14220  }
14221 
14222  tr_set_execution_state (save_tr_state);
14223 
14224  return error;
14225 }
14226 
14227 /*
14228  * pt_node_to_function_index () - extracts function index information
14229  * based on the given expression
14230  * parser(in): parser context
14231  * spec(in): class spec
14232  * expr(in): expression used with function index
14233  * return: pointer to SM_FUNCTION_INFO structure, containing the
14234  * function index information
14235  */
14236 static SM_FUNCTION_INFO *
14238 {
14239  SM_FUNCTION_INFO *func_index_info;
14241  PT_NODE *expr = NULL;
14242  char *expr_str = NULL;
14243  TP_DOMAIN *d = NULL;
14244  unsigned int save_custom;
14245 
14246  if (node->node_type == PT_SORT_SPEC)
14247  {
14248  expr = node->info.sort_spec.expr;
14249  }
14250  else
14251  {
14252  expr = node;
14253  }
14254 
14255  func_index_info = (SM_FUNCTION_INFO *) db_ws_alloc (sizeof (SM_FUNCTION_INFO));
14256 
14257  if (func_index_info == NULL)
14258  {
14259  return NULL;
14260  }
14261  memset (func_index_info, 0, sizeof (SM_FUNCTION_INFO));
14262 
14263  if (expr->data_type)
14264  {
14265  d = pt_data_type_to_db_domain (parser, expr->data_type, NULL);
14266  }
14267  else
14268  {
14270  }
14271 
14272  if (node->node_type == PT_SORT_SPEC)
14273  {
14274  d->is_desc = (node->info.sort_spec.asc_or_desc == PT_ASC ? 0 : 1);
14275  }
14276 
14277  d = tp_domain_cache (d);
14278  func_index_info->fi_domain = d;
14279 
14280  assert (func_index_info->fi_domain != NULL);
14281 
14282  save_custom = parser->custom_print;
14284  expr_str = parser_print_tree_with_quotes (parser, expr);
14285  parser->custom_print = save_custom;
14286  assert (expr_str != NULL);
14287 
14288  func_index_info->expr_str = strdup (expr_str);
14289  if (func_index_info->expr_str == NULL)
14290  {
14292  goto error_exit;
14293  }
14294 
14295  func_index_info->expr_stream = NULL;
14296  func_index_info->expr_stream_size = -1;
14297 
14298  if (do_index == DO_INDEX_CREATE)
14299  {
14300  func_pred = pt_to_func_pred (parser, spec, expr);
14301  if (func_pred)
14302  {
14303  xts_map_func_pred_to_stream (func_pred, &func_index_info->expr_stream, &func_index_info->expr_stream_size);
14304  }
14305  else
14306  {
14307  goto error_exit;
14308  }
14309  }
14310 
14311  return func_index_info;
14312 
14313 error_exit:
14314  if (func_index_info != NULL)
14315  {
14316  sm_free_function_index_info (func_index_info);
14317  db_ws_free (func_index_info);
14318  }
14319  return NULL;
14320 }
14321 
14322 /*
14323  * do_recreate_func_index_constr () - rebuilds the function index expression
14324  * parser(in): parser context
14325  * constr(in): constraint info, must be a function index
14326  * func_index_info(in): function index info
14327  * alter (in): information regarding changes made by an ALTER statement
14328  * src_cls_name (in): current table name holding the constraint
14329  * new_cls_name (in): new table name holding the constraint
14330  * (when CREATE TABLE ... LIKE statement is used)
14331  * return: NO_ERROR or error code
14332  *
14333  */
14334 int
14336  PT_NODE * alter, const char *src_cls_name, const char *new_cls_name)
14337 {
14338  PT_NODE **stmt;
14339  PT_NODE *expr;
14340  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
14341  SM_FUNCTION_INFO *fi_info_ws = NULL;
14342  int error = NO_ERROR;
14343  const char *class_name = NULL;
14344  char *query_str = NULL;
14345  size_t query_str_len = 0;
14346  int saved_func_index_pos = -1, saved_attr_index_start = -1;
14347  bool free_packing_buff = false;
14348  bool free_parser = false;
14349  SM_FUNCTION_INFO *fi_info = NULL;
14350 
14351  if (constr)
14352  {
14353  fi_info = constr->func_index_info;
14354  }
14355  else
14356  {
14357  fi_info = func_index_info;
14358  }
14359 
14360  if (parser == NULL)
14361  {
14362  parser = parser_create_parser ();
14363  if (parser == NULL)
14364  {
14365  error = ER_FAILED;
14366  goto error;
14367  }
14368  free_parser = true;
14369  }
14370  if (alter && alter->node_type == PT_ALTER)
14371  {
14372  /* rebuilding the index due to ALTER CHANGE statement */
14373  if (alter->info.alter.entity_name)
14374  {
14375  class_name = alter->info.alter.entity_name->info.name.original;
14376  }
14377  }
14378  else
14379  {
14380  /* rebuilding the index due to CREATE TABLE ... LIKE statement */
14381  if (src_cls_name)
14382  {
14383  class_name = src_cls_name;
14384  }
14385  }
14386  if (class_name == NULL)
14387  {
14388  error = ER_FAILED;
14389  goto error;
14390  }
14391 
14392  query_str_len = strlen (fi_info->expr_str) + strlen (class_name) + 7 /* strlen("SELECT ") */ +
14393  6 /* strlen(" FROM ") */ +
14394  2 /* [] */ +
14395  1 /* terminating null */ ;
14396  query_str = (char *) malloc (query_str_len);
14397  if (query_str == NULL)
14398  {
14400  return ER_OUT_OF_VIRTUAL_MEMORY;
14401  }
14402  snprintf (query_str, query_str_len, "SELECT %s FROM [%s]", fi_info->expr_str, class_name);
14403  stmt = parser_parse_string_use_sys_charset (parser, query_str);
14404  if (stmt == NULL || *stmt == NULL || pt_has_error (parser))
14405  {
14406  error = ER_FAILED;
14407  goto error;
14408  }
14409  expr = (*stmt)->info.query.q.select.list;
14410 
14411  if (alter)
14412  {
14413  (void) parser_walk_tree (parser, expr, replace_names_alter_chg_attr, alter, NULL, NULL);
14414  }
14415  else
14416  {
14417  PT_NODE *new_node = pt_name (parser, new_cls_name);
14418  PT_NODE *old_name = (*stmt)->info.query.q.select.from->info.spec.entity_name;
14419  if (!old_name)
14420  {
14421  error = ER_FAILED;
14422  goto error;
14423  }
14424 
14425  if (new_node)
14426  {
14427  new_node->next = old_name->next;
14428  old_name->next = NULL;
14429  parser_free_tree (parser, old_name);
14430  (*stmt)->info.query.q.select.from->info.spec.entity_name = new_node;
14431  }
14432  (void) parser_walk_tree (parser, expr, pt_replace_names_index_expr, (void *) new_cls_name, NULL, NULL);
14433  }
14434 
14435  *stmt = pt_resolve_names (parser, *stmt, &sc_info);
14436  if (*stmt != NULL && !pt_has_error (parser))
14437  {
14438  *stmt = pt_semantic_type (parser, *stmt, &sc_info);
14439  }
14440  else
14441  {
14442  error = ER_FAILED;
14443  goto error;
14444  }
14445  if (*stmt != NULL && !pt_has_error (parser))
14446  {
14447  expr = (*stmt)->info.query.q.select.list;
14448  if (expr && !pt_is_function_index_expr (parser, expr, true))
14449  {
14450  error = ER_FAILED;
14451  goto error;
14452  }
14453  }
14454  else
14455  {
14456  error = ER_FAILED;
14457  goto error;
14458  }
14459 
14460  saved_func_index_pos = fi_info->col_id;
14461  saved_attr_index_start = fi_info->attr_index_start;
14462  if (constr)
14463  {
14464  /* free previous function index info */
14465  sm_free_function_index_info (fi_info);
14466  free_and_init (fi_info);
14467  }
14468  else
14469  {
14470  sm_free_function_index_info (fi_info);
14471  }
14472 
14474  free_packing_buff = true;
14475  fi_info_ws = pt_node_to_function_index (parser, (*stmt)->info.query.q.select.from, expr, DO_INDEX_CREATE);
14476  if (fi_info_ws == NULL)
14477  {
14478  error = ER_OUT_OF_VIRTUAL_MEMORY;
14479  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, sizeof (SM_FUNCTION_INFO));
14480  goto error;
14481  }
14482 
14483  if (constr)
14484  {
14485  /* original function index uses WS storage, switch to normal heap storage */
14486  fi_info = (SM_FUNCTION_INFO *) malloc (sizeof (SM_FUNCTION_INFO));
14487  if (fi_info == NULL)
14488  {
14489  error = ER_OUT_OF_VIRTUAL_MEMORY;
14490  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, sizeof (SM_FUNCTION_INFO));
14491  db_ws_free (fi_info_ws);
14492  goto error;
14493  }
14494  }
14495 
14496  memcpy (fi_info, fi_info_ws, sizeof (SM_FUNCTION_INFO));
14497  db_ws_free (fi_info_ws);
14498 
14499  fi_info->col_id = saved_func_index_pos;
14500  fi_info->attr_index_start = saved_attr_index_start;
14501  if (constr)
14502  {
14503  /* restore original values */
14504  constr->func_index_info = fi_info;
14505  }
14506 
14507 error:
14508  if (free_packing_buff)
14509  {
14511  }
14512 
14513  if (free_parser)
14514  {
14515  parser_free_parser (parser);
14516  }
14517  if (query_str)
14518  {
14519  free_and_init (query_str);
14520  }
14521  return error;
14522 }
14523 
14524 /*
14525  * do_recreate_filter_index_constr () - rebuilds the filter index expression
14526  * parser(in): parser context
14527  * filter_index_info(in): filter index information
14528  * alter (in): information regarding changes made by an ALTER statement
14529  * src_cls_name (in): current table name holding the constraint
14530  * new_cls_name (in): new table name holding the constraint
14531  * (when CREATE TABLE ... LIKE statement is used)
14532  * return: NO_ERROR or error code
14533  *
14534  */
14535 int
14537  const char *src_cls_name, const char *new_cls_name)
14538 {
14539  PT_NODE **stmt;
14540  PT_NODE *where_predicate;
14541  SEMANTIC_CHK_INFO sc_info = { NULL, NULL, 0, 0, 0, false, false };
14542  PARSER_VARCHAR *filter_expr = NULL;
14543  PRED_EXPR_WITH_CONTEXT *filter_predicate;
14544  int error;
14545  const char *class_name = NULL;
14546  char *query_str = NULL;
14547  size_t query_str_len = 0;
14548  char *pred_str = NULL;
14549  int pred_str_len = 0;
14550  bool free_packing_buff = false;
14551  SM_PREDICATE_INFO new_pred = { NULL, NULL, 0, NULL, 0 };
14552  bool free_parser = false;
14553  unsigned int save_custom;
14554 
14555  if (parser == NULL)
14556  {
14557  parser = parser_create_parser ();
14558  if (parser == NULL)
14559  {
14560  error = ER_FAILED;
14561  goto error;
14562  }
14563  free_parser = true;
14564  }
14565  if (alter && alter->node_type == PT_ALTER)
14566  {
14567  /* rebuilding the index due to ALTER CHANGE statement */
14568  if (alter->info.alter.entity_name)
14569  {
14570  class_name = alter->info.alter.entity_name->info.name.original;
14571  }
14572  }
14573  else
14574  {
14575  /* rebuilding the index due to CREATE TABLE ... LIKE statement */
14576  if (src_cls_name)
14577  {
14578  class_name = src_cls_name;
14579  }
14580  }
14581  if (class_name == NULL)
14582  {
14583  error = ER_FAILED;
14584  goto error;
14585  }
14586 
14587  query_str_len = strlen (filter_index_info->pred_string) + strlen (class_name) + 9 /* strlen("SELECT * ") */ +
14588  6 /* strlen(" FROM ") */ +
14589  2 /* [] */ +
14590  7 /* strlen(" WHERE " */ +
14591  1 /* terminating null */ ;
14592  query_str = (char *) malloc (query_str_len);
14593  if (query_str == NULL)
14594  {
14596  return ER_OUT_OF_VIRTUAL_MEMORY;
14597  }
14598  snprintf (query_str, query_str_len, "SELECT * FROM [%s] WHERE %s", class_name, filter_index_info->pred_string);
14599  stmt = parser_parse_string_use_sys_charset (parser, query_str);
14600  if (stmt == NULL || *stmt == NULL || pt_has_error (parser))
14601  {
14602  error = ER_FAILED;
14603  goto error;
14604  }
14605  where_predicate = (*stmt)->info.query.q.select.where;
14606 
14607  if (alter)
14608  {
14609  (void) parser_walk_tree (parser, where_predicate, replace_names_alter_chg_attr, alter, NULL, NULL);
14610  }
14611  else
14612  {
14613  PT_NODE *new_node = pt_name (parser, new_cls_name);
14614  PT_NODE *old_name = (*stmt)->info.query.q.select.from->info.spec.entity_name;
14615  if (!old_name)
14616  {
14617  error = ER_FAILED;
14618  goto error;
14619  }
14620 
14621  if (new_node)
14622  {
14623  new_node->next = old_name->next;
14624  old_name->next = NULL;
14625  parser_free_tree (parser, old_name);
14626  (*stmt)->info.query.q.select.from->info.spec.entity_name = new_node;
14627  }
14628  (void) parser_walk_tree (parser, where_predicate, pt_replace_names_index_expr, (void *) new_cls_name, NULL, NULL);
14629  }
14630 
14631  *stmt = pt_resolve_names (parser, *stmt, &sc_info);
14632  if (*stmt != NULL && !pt_has_error (parser))
14633  {
14634  *stmt = pt_semantic_type (parser, *stmt, &sc_info);
14635  }
14636  else
14637  {
14638  error = ER_FAILED;
14639  goto error;
14640  }
14641 
14642  if (*stmt == NULL || pt_has_error (parser))
14643  {
14644  error = ER_FAILED;
14645  goto error;
14646  }
14647 
14648  /* make sure paren_type is 0 so parenthesis are not printed */
14649  where_predicate->info.expr.paren_type = 0;
14650  save_custom = parser->custom_print;
14652  filter_expr = pt_print_bytes (parser, where_predicate);
14653  parser->custom_print = save_custom;
14654  if (filter_expr)
14655  {
14656  pred_str = (char *) filter_expr->bytes;
14657  pred_str_len = strlen (pred_str);
14658  new_pred.pred_string = (char *) calloc (pred_str_len + 1, sizeof (char));
14659  if (new_pred.pred_string == NULL)
14660  {
14661  error = ER_OUT_OF_VIRTUAL_MEMORY;
14662  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, (pred_str_len + 1) * sizeof (char));
14663  goto error;
14664  }
14665  memcpy (new_pred.pred_string, pred_str, pred_str_len);
14666 
14668  {
14671  error = ER_FAILED;
14672  goto error;
14673  }
14674  }
14675 
14677  free_packing_buff = true;
14678  filter_predicate = pt_to_pred_with_context (parser, where_predicate, (*stmt)->info.query.q.select.from);
14679  if (filter_predicate)
14680  {
14681  error = xts_map_filter_pred_to_stream (filter_predicate, &new_pred.pred_stream, &new_pred.pred_stream_size);
14682  if (error != NO_ERROR)
14683  {
14685  error = ER_FAILED;
14686  goto error;
14687  }
14688  }
14689  else
14690  {
14691  assert (er_errid () != NO_ERROR);
14692  error = er_errid ();
14693  goto error;
14694  }
14695 
14696  if (filter_predicate->attrids_pred)
14697  {
14698  int i;
14699  assert (filter_predicate->num_attrs_pred > 0);
14700  new_pred.att_ids = (int *) calloc (filter_predicate->num_attrs_pred, sizeof (int));
14701  if (new_pred.att_ids == NULL)
14702  {
14704  error = ER_FAILED;
14705  goto error;
14706  }
14707  for (i = 0; i < filter_predicate->num_attrs_pred; i++)
14708  {
14709  new_pred.att_ids[i] = filter_predicate->attrids_pred[i];
14710  }
14711  }
14712  else
14713  {
14714  new_pred.att_ids = NULL;
14715  }
14716  new_pred.num_attrs = filter_predicate->num_attrs_pred;
14717 
14718  if (filter_index_info->pred_string)
14719  {
14720  free_and_init (filter_index_info->pred_string);
14721  }
14722  if (filter_index_info->pred_stream)
14723  {
14724  free_and_init (filter_index_info->pred_stream);
14725  }
14726  if (filter_index_info->att_ids)
14727  {
14728  free_and_init (filter_index_info->att_ids);
14729  }
14730 
14731  filter_index_info->pred_string = new_pred.pred_string;
14732  filter_index_info->pred_stream = new_pred.pred_stream;
14733  filter_index_info->pred_stream_size = new_pred.pred_stream_size;
14734  filter_index_info->att_ids = new_pred.att_ids;
14735  filter_index_info->num_attrs = new_pred.num_attrs;
14736 
14737  if (free_parser)
14738  {
14739  parser_free_parser (parser);
14740  }
14741  if (query_str)
14742  {
14743  free_and_init (query_str);
14744  }
14745 
14747  return NO_ERROR;
14748 
14749 error:
14750  if (free_parser)
14751  {
14752  parser_free_parser (parser);
14753  }
14754  if (query_str)
14755  {
14756  free_and_init (query_str);
14757  }
14758  if (new_pred.pred_string)
14759  {
14760  free_and_init (new_pred.pred_string);
14761  }
14762  if (new_pred.pred_stream)
14763  {
14764  free_and_init (new_pred.pred_stream);
14765  }
14766  if (new_pred.att_ids)
14767  {
14768  free_and_init (new_pred.att_ids);
14769  }
14770  if (free_packing_buff)
14771  {
14773  }
14774  return error;
14775 }
14776 
14777 /*
14778  * replace_names_alter_chg_attr() - Replaces the attribute name in a given
14779  * expression, based on the changes imposed
14780  * the ALTER CHANGE statement
14781  * return: PT_NODE pointer
14782  * parser(in): Parser context
14783  * node(in):
14784  * void_arg(in):
14785  * continue_walk(in):
14786  *
14787  * Note:
14788  */
14789 static PT_NODE *
14790 replace_names_alter_chg_attr (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk)
14791 {
14792  PT_NODE *alter = (PT_NODE *) void_arg;
14793  PT_NODE *old_name = NULL;
14794  const char *new_name = NULL;
14795 
14796  assert (alter->node_type == PT_ALTER);
14797 
14798  if (alter->info.alter.alter_clause.attr_mthd.attr_def_list)
14799  {
14800  new_name = get_attr_name (alter->info.alter.alter_clause.attr_mthd.attr_def_list);
14801  }
14802  old_name = alter->info.alter.alter_clause.attr_mthd.attr_old_name;
14803  if (old_name == NULL || new_name == NULL)
14804  {
14805  *continue_walk = PT_STOP_WALK;
14806  return node;
14807  }
14808  *continue_walk = PT_CONTINUE_WALK;
14809 
14810  if (node->node_type == PT_DOT_)
14811  {
14812  if (PT_IS_NAME_NODE (node->info.dot.arg2))
14813  {
14814  PT_NODE *new_node = NULL;
14815  if (intl_identifier_casecmp (node->info.dot.arg2->info.name.original, old_name->info.name.original) == 0)
14816  {
14817  new_node = pt_name (parser, new_name);
14818  }
14819  else
14820  {
14821  new_node = pt_name (parser, node->info.dot.arg2->info.name.original);
14822  }
14823  if (new_node)
14824  {
14825  new_node->next = node->next;
14826  node->next = NULL;
14827  parser_free_tree (parser, node);
14828  node = new_node;
14829  }
14830  }
14831  }
14832 
14833  return node;
14834 }
14835 
14836 /*
14837  * pt_replace_names_index_expr () - Replaces the table name in a given
14838  * expression, based on the name required
14839  * when copying a function/filter index on
14840  * CREATE TABLE ... LIKE or when adding an
14841  * function/filter index to partitions of a class.
14842  *
14843  * return: PT_NODE pointer
14844  * parser(in): Parser context
14845  * node(in):
14846  * void_arg(in):
14847  * continue_walk(in):
14848  *
14849  * Note:
14850  */
14851 static PT_NODE *
14852 pt_replace_names_index_expr (PARSER_CONTEXT * parser, PT_NODE * node, void *void_arg, int *continue_walk)
14853 {
14854  const char *new_name = (char *) void_arg;
14855 
14856  *continue_walk = PT_CONTINUE_WALK;
14857 
14858  if (node->node_type == PT_DOT_)
14859  {
14860  if (PT_IS_NAME_NODE (node->info.dot.arg1))
14861  {
14862  PT_NODE *new_node = pt_name (parser, new_name);
14863  PT_NODE *dot_arg = node->info.dot.arg1;
14864  if (new_node)
14865  {
14866  new_node->next = dot_arg->next;
14867  dot_arg->next = NULL;
14868  parser_free_tree (parser, dot_arg);
14869  node->info.dot.arg1 = new_node;
14870  }
14871  }
14872  }
14873 
14874  return node;
14875 }
14876 
14877 /*
14878  * get_index_type_qualifiers() - get qualifiers of the index type that
14879  * matches the index name.
14880  * return: NO_ERROR or error code
14881  * obj(in): Memory Object Pointer
14882  * is_reverse(out): TRUE if the index type has the reverse feature.
14883  * is_unique(out): TRUE if the index type has the unique feature.
14884  * index_name(in): the name of index
14885  *
14886  * note:
14887  * Only index types that satisfy the SM_IS_INDEX_FAMILY
14888  * condition will be searched for.
14889  */
14890 
14891 static int
14892 get_index_type_qualifiers (MOP obj, bool * is_reverse, bool * is_unique, const char *index_name)
14893 {
14894  int error_code = NO_ERROR;
14895  SM_CLASS_CONSTRAINT *sm_all_constraints = NULL;
14897 
14898  if (obj == NULL)
14899  {
14900  error_code = ER_FAILED;
14901  return error_code;
14902  }
14903 
14904  sm_all_constraints = sm_class_constraints (obj);
14905  sm_constraint = classobj_find_constraint_by_name (sm_all_constraints, index_name);
14906  if (sm_all_constraints == NULL || sm_constraint == NULL)
14907  {
14908  error_code = ER_SM_NO_INDEX;
14909  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, index_name);
14910  return error_code;
14911  }
14912 
14913  if (!SM_IS_INDEX_FAMILY (sm_constraint->type))
14914  {
14916  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error_code, 1, index_name);
14917  return error_code;
14918  }
14919 
14920  switch (sm_constraint->type)
14921  {
14922  case SM_CONSTRAINT_INDEX:
14923  *is_reverse = false;
14924  *is_unique = false;
14925  break;
14926  case SM_CONSTRAINT_UNIQUE:
14927  *is_reverse = false;
14928  *is_unique = true;
14929  break;
14931  *is_reverse = true;
14932  *is_unique = false;
14933  break;
14935  *is_reverse = true;
14936  *is_unique = true;
14937  break;
14938  default:
14939  break;
14940  }
14941 
14942  return error_code;
14943 }
14944 
14945 /*
14946  * pt_node_to_partition_info() -
14947  * return: Error code
14948  * parser(in): Parser context
14949  * node(in): Parser tree of an partition class
14950  * entity_name(in):
14951  * class_name(in): class name
14952  * partition_name(in): partition name
14953  * minval(in):
14954  *
14955  * Note:
14956  */
14957 static SM_PARTITION *
14958 pt_node_to_partition_info (PARSER_CONTEXT * parser, PT_NODE * node, PT_NODE * entity_name, char *class_name,
14959  char *partition_name, DB_VALUE * minval)
14960 {
14961  DB_VALUE val, *ptval, *hashsize;
14962  PT_NODE *parts;
14963  char *query, *query_str = NULL, *p;
14964  DB_COLLECTION *dbc = NULL;
14965  size_t buf_size;
14967 
14968  partition = classobj_make_partition_info ();
14969  if (partition == NULL)
14970  {
14972  return NULL;
14973  }
14974 
14975  if (node->node_type == PT_PARTITION)
14976  {
14977  partition->pname = NULL;
14978  }
14979  else
14980  {
14981  partition->pname = ws_copy_string ((char *) node->info.parts.name->info.name.original);
14982  if (partition->pname == NULL)
14983  {
14985  strlen ((char *) node->info.parts.name->info.name.original));
14986  return NULL;
14987  }
14988  }
14989 
14990  if (node->node_type == PT_PARTITION)
14991  {
14992  partition->partition_type = node->info.partition.type;
14993  }
14994  else
14995  {
14996  partition->partition_type = node->info.parts.type;
14997  }
14998 
14999  if (node->node_type == PT_PARTITION)
15000  {
15001  unsigned int save_custom;
15002 
15003  save_custom = parser->custom_print;
15005  query = parser_print_tree_with_quotes (parser, node->info.partition.expr);
15006  parser->custom_print = save_custom;
15007  if (query == NULL)
15008  {
15009  goto fail_return;
15010  }
15011 
15012  buf_size = strlen (query) + strlen (class_name) + 7 /* strlen("SELECT ") */ +
15013  6 /* strlen(" FROM ") */ +
15014  2 /* [] */ +
15015  1 /* terminating null */ ;
15016  if (buf_size > DB_MAX_PARTITION_EXPR_LENGTH)
15017  {
15019  goto fail_return;
15020  }
15021 
15022  query_str = (char *) malloc (buf_size);
15023  if (query_str == NULL)
15024  {
15026  goto fail_return;
15027  }
15028  sprintf (query_str, "SELECT %s FROM [%s]", query, class_name);
15029  partition->expr = ws_copy_string (query_str);
15030  if (partition->expr == NULL)
15031  {
15033  goto fail_return;
15034  }
15035  }
15036  else
15037  {
15038  partition->expr = NULL;
15039  }
15040  if (query_str)
15041  {
15042  free_and_init (query_str);
15043  }
15044 
15045  dbc = set_create_sequence (0);
15046  if (dbc == NULL)
15047  {
15048  goto fail_return;
15049  }
15050  if (node->node_type == PT_PARTITION)
15051  {
15052  DB_VALUE expr;
15053  SM_FUNCTION_INFO *part_expr = NULL;
15054 
15055  p = (char *) node->info.partition.keycol->info.name.original;
15057  set_add_element (dbc, &val);
15058  if (node->info.partition.type == PT_PARTITION_HASH)
15059  {
15060  hashsize = pt_value_to_db (parser, node->info.partition.hashsize);
15061  set_add_element (dbc, hashsize);
15062  }
15063  else
15064  {
15065  set_add_element (dbc, minval);
15066  }
15067 
15068  /* Now compile the partition expression and add it to the end of the collection */
15069  part_expr = compile_partition_expression (parser, entity_name, node);
15070  if (part_expr == NULL)
15071  {
15072  if (pt_has_error (parser))
15073  {
15075  }
15076 
15077  goto fail_return;
15078  }
15079  db_make_char (&expr, part_expr->expr_stream_size, part_expr->expr_stream, part_expr->expr_stream_size,
15081  set_add_element (dbc, &expr);
15082 
15083  /* Notice that we're not calling pr_clear_value on expr here because memory allocated for expr_stream is
15084  * deallocated by 'sm_free_function_index_info' */
15085  sm_free_function_index_info (part_expr);
15086  db_ws_free (part_expr);
15087  part_expr = NULL;
15088  }
15089  else
15090  {
15091  if (node->info.parts.type == PT_PARTITION_RANGE)
15092  {
15093  if (minval == NULL)
15094  {
15095  db_make_null (&val);
15096  set_add_element (dbc, &val);
15097  }
15098  else
15099  {
15100  set_add_element (dbc, minval);
15101  }
15102  }
15103  if (node->info.parts.values == NULL)
15104  { /* RANGE-MAXVALUE */
15105  db_make_null (&val);
15106  set_add_element (dbc, &val);
15107  }
15108  else
15109  {
15110  for (parts = node->info.parts.values; parts; parts = parts->next)
15111  {
15112  ptval = pt_value_to_db (parser, parts);
15113  if (ptval == NULL)
15114  {
15115  goto fail_return;
15116  }
15117  set_add_element (dbc, ptval);
15118  }
15119  }
15120  }
15121 
15122  partition->values = db_seq_copy (dbc);
15123 
15124  if (node->node_type != PT_PARTITION)
15125  {
15126  if (node->info.parts.comment != NULL)
15127  {
15128  assert (node->info.parts.comment->node_type == PT_VALUE);
15129  p = (char *) node->info.parts.comment->info.value.data_value.str->bytes;
15130  partition->comment = ws_copy_string (p);
15131  if (partition->comment == NULL)
15132  {
15134  goto fail_return;
15135  }
15136  }
15137  }
15138 
15139  set_free (dbc);
15140  return partition;
15141 
15142 fail_return:
15143  if (dbc != NULL)
15144  {
15145  set_free (dbc);
15146  }
15147  classobj_free_partition_info (partition);
15148  if (query_str != NULL)
15149  {
15150  free_and_init (query_str);
15151  }
15152 
15153  assert (er_errid () != NO_ERROR);
15154  return NULL;
15155 }
15156 
15157 /*
15158  * do_save_all_indexes () - Save all constraint info for a given class
15159  * return: error code
15160  * classmop(in):
15161  * saved_index_info_listpp(out):
15162  *
15163  */
15164 static int
15165 do_save_all_indexes (MOP classmop, SM_CONSTRAINT_INFO ** saved_index_info_listpp)
15166 {
15167  int error = NO_ERROR;
15169  SM_CONSTRAINT_INFO *index_save_info = NULL, *saved = NULL;
15170  SM_CLASS *class_ = NULL;
15171 
15172  assert (classmop != NULL);
15173  assert (saved_index_info_listpp != NULL);
15174 
15175  *saved_index_info_listpp = NULL;
15176 
15177  error = au_fetch_class (classmop, &class_, AU_FETCH_READ, DB_AUTH_SELECT);
15178  if (error != NO_ERROR)
15179  {
15180  return error;
15181  }
15182 
15183  if (class_->constraints == NULL)
15184  {
15185  /* no constraints, nothing to do */
15186  return NO_ERROR;
15187  }
15188 
15189  if (class_->class_type != SM_CLASS_CT)
15190  {
15191  return NO_ERROR;
15192  }
15193 
15194  for (c = class_->constraints; c; c = c->next)
15195  {
15197  {
15198  continue;
15199  }
15200 
15201  /* save constraints */
15202  error = sm_save_constraint_info (&index_save_info, c);
15203  if (error == NO_ERROR)
15204  {
15205  assert (index_save_info != NULL);
15206  saved = index_save_info;
15207  while (saved->next)
15208  {
15209  saved = saved->next;
15210  }
15211  }
15212  else
15213  {
15214  return error;
15215  }
15216  }
15217 
15218  *saved_index_info_listpp = index_save_info;
15219  return NO_ERROR;
15220 }
15221 
15222 /*
15223  * do_drop_saved_indexes () - drop all indexes from a constraint info list
15224  * return: error
15225  * classmop (in) :
15226  * index_save_info :
15227  */
15228 static int
15229 do_drop_saved_indexes (MOP classmop, SM_CONSTRAINT_INFO * index_save_info)
15230 {
15231  int error = NO_ERROR;
15232  SM_CONSTRAINT_INFO *saved = NULL;
15233 
15234  for (saved = index_save_info; saved != NULL; saved = saved->next)
15235  {
15237  {
15238  error =
15239  sm_drop_constraint (classmop, saved->constraint_type, saved->name, (const char **) saved->att_names, false,
15240  false);
15241  if (error != NO_ERROR)
15242  {
15243  return error;
15244  }
15245  }
15246  else
15247  {
15248  error = sm_drop_index (classmop, saved->name);
15249  if (error != NO_ERROR)
15250  {
15251  return error;
15252  }
15253  }
15254  }
15255 
15256  return NO_ERROR;
15257 }
15258 
15259 /*
15260  * do_recreate_saved_indexes () - recreate all indexes from a constraint
15261  * info list
15262  * return: error
15263  * classmop (in) :
15264  * index_save_info :
15265  */
15266 static int
15267 do_recreate_saved_indexes (MOP classmop, SM_CONSTRAINT_INFO * index_save_info)
15268 {
15269  int error = NO_ERROR;
15270  SM_CONSTRAINT_INFO *saved = NULL;
15271 
15272  for (saved = index_save_info; saved != NULL; saved = saved->next)
15273  {
15275  {
15276  error = sm_add_constraint (classmop, saved->constraint_type, saved->name, (const char **) saved->att_names,
15277  saved->asc_desc, saved->prefix_length, false, saved->filter_predicate,
15278  saved->func_index_info, saved->comment, saved->index_status);
15279 
15280  if (error != NO_ERROR)
15281  {
15282  return error;
15283  }
15284  }
15285  }
15286 
15287  return NO_ERROR;
15288 }
15289 
15290 int
15291 do_alter_index_status (PARSER_CONTEXT * parser, const PT_NODE * statement)
15292 {
15293  int error = NO_ERROR;
15294  DB_OBJECT *obj;
15295  PT_NODE *cls = NULL;
15296  SM_TEMPLATE *ctemplate = NULL;
15297  const char *class_name = NULL;
15298  const char *index_name = NULL;
15299  SM_INDEX_STATUS index_status;
15300  bool do_rollback = false;
15301 
15302  index_name = statement->info.index.index_name ? statement->info.index.index_name->info.name.original : NULL;
15303 
15304  if (index_name == NULL)
15305  {
15306  goto error_exit;
15307  }
15308 
15309  index_status = (SM_INDEX_STATUS) statement->info.index.index_status;
15310 
15311  cls = statement->info.index.indexed_class ? statement->info.index.indexed_class->info.spec.flat_entity_list : NULL;
15312  if (cls == NULL)
15313  {
15314  goto error_exit;
15315  }
15316 
15317  class_name = cls->info.name.resolved;
15318  obj = db_find_class (class_name);
15319  if (obj == NULL)
15320  {
15321  ASSERT_ERROR_AND_SET (error);
15322  goto error_exit;
15323  }
15324 
15326  if (error != NO_ERROR)
15327  {
15328  goto error_exit;
15329  }
15330 
15331  do_rollback = true;
15332 
15333  ctemplate = smt_edit_class_mop (obj, AU_INDEX);
15334  if (ctemplate == NULL)
15335  {
15336  ASSERT_ERROR_AND_SET (error);
15337  goto error_exit;
15338  }
15339 
15340  error = smt_change_constraint_status (ctemplate, index_name, index_status);
15341  if (error != NO_ERROR)
15342  {
15343  goto error_exit;
15344  }
15345 
15346  /* classobj_free_template() is included in sm_update_class() */
15347  error = sm_update_class (ctemplate, NULL);
15348  if (error != NO_ERROR)
15349  {
15350  /* Even though sm_update() did not return NO_ERROR, ctemplate is already freed */
15351  ctemplate = NULL;
15352  goto error_exit;
15353  }
15354 
15355 end:
15356 
15357  return error;
15358 
15359 error_exit:
15360  if (ctemplate != NULL)
15361  {
15362  /* smt_quit() always returns NO_ERROR */
15363  smt_quit (ctemplate);
15364  }
15365 
15366  if (do_rollback == true)
15367  {
15368  if (do_rollback && error != ER_LK_UNILATERALLY_ABORTED)
15369  {
15371  }
15372  }
15373  error = (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
15374 
15375  goto end;
15376 }
15377 
15378 int
15380 {
15381  return ib_thread_count;
15382 }
PT_NODE * mq_clear_ids(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *spec)
char * sm_produce_constraint_name_tmpl(SM_TEMPLATE *tmpl, DB_CONSTRAINT_TYPE constraint_type, const char **att_names, const int *asc_desc, const char *given_name)
int dbt_constrain_non_null(DB_CTMPL *def, const char *name, int class_attribute, int on_or_off)
Definition: db_temp.c:344
DB_OBJECT * db_find_class(const char *name)
Definition: db_info.c:133
int au_check_serial_authorization(MOP serial_object)
PT_NODE * pt_name(PARSER_CONTEXT *parser_ptr, const char *name)
PT_MISC_TYPE attr_type
Definition: parse_tree.h:1864
PT_NODE * order_by
Definition: parse_tree.h:2769
#define ER_LK_UNILATERALLY_ABORTED
Definition: error_code.h:130
PT_NODE * pt_compile(PARSER_CONTEXT *parser, PT_NODE *volatile statement)
Definition: compile.c:380
PT_NODE * next
Definition: parse_tree.h:3447
PT_NAME_INFO name
Definition: parse_tree.h:3318
const char * expr
Definition: class_object.h:697
int db_execute_statement_local(DB_SESSION *session, int stmt, DB_QUERY_RESULT **result)
Definition: db_vdb.c:2939
FUNC_PRED * pt_to_func_pred(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *expr)
static bool is_att_property_structure_checked(const SM_ATTR_PROP_CHG *attr_chg_properties)
DB_CONSTRAINT_TYPE constraint_type
int tran_system_savepoint(const char *savept_name)
PT_MISC_TYPE delete_action
Definition: parse_tree.h:3088
static int check_att_chg_allowed(const char *att_name, const PT_TYPE_ENUM t, const SM_ATTR_PROP_CHG *attr_chg_prop, SM_ATTR_CHG_SOL chg_how, bool log_error_allowed, bool *new_attempt)
struct pt_alter_info::@111::@115 rename
static int add_foreign_key(DB_CTMPL *ctemplate, const PT_NODE *cnstr, const char **att_names)
#define CHECK_MODIFICATION_ERROR()
Definition: db.h:121
static int do_run_upgrade_instances_domain(PARSER_CONTEXT *parser, OID *p_class_oid, int att_id)
#define NO_ERROR
Definition: error_code.h:46
int do_statement(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_UNION_INFO union_
Definition: parse_tree.h:2782
int sm_touch_class(MOP classmop)
const char ** classobj_point_at_att_names(SM_CLASS_CONSTRAINT *constraint, int *count_ref)
int set_get_element_nocopy(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2616
#define UNIQUE_SAVEPOINT_RENAME
#define AU_DISABLE(save)
Definition: authenticate.h:106
#define ws_free_string_and_init(str)
Definition: work_space.h:376
#define UNIQUE_SAVEPOINT_REVOKE_USER
PT_NODE * resolution_list
Definition: parse_tree.h:1908
#define DB_MAX_BIT_PRECISION
Definition: dbtype_def.h:549
PT_METHOD_DEF_INFO method_def
Definition: parse_tree.h:3317
int dbt_add_foreign_key(DB_CTMPL *def, const char *constraint_name, const char **attnames, const char *ref_class, const char **ref_attrs, int del_action, int upd_action, const char *comment)
Definition: db_temp.c:524
#define LANG_SYS_COLLATION
#define LANG_GET_BINARY_COLLATION(c)
#define ER_AU_MEMBER_CAUSES_CYCLES
Definition: error_code.h:206
#define SM_IS_CONSTRAINT_EXCEPT_INDEX_FAMILY(c)
Definition: class_object.h:134
int do_get_partition_size(MOP class_)
SM_CLASS * current
Definition: class_object.h:783
int sm_add_constraint(MOP classop, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, const int *asc_desc, const int *attrs_prefix_length, int class_attributes, SM_PREDICATE_INFO *filter_index, SM_FUNCTION_INFO *function_index, const char *comment, SM_INDEX_STATUS index_status)
#define IS_NAME(n)
int dbt_reset_query_spec(DB_CTMPL *def)
Definition: db_temp.c:1240
PT_RENAME_INFO rename
Definition: parse_tree.h:3327
int dbt_drop_class_method(DB_CTMPL *def, const char *name)
Definition: db_temp.c:885
const char * pt_node_to_db_domain_name(PT_NODE *node)
Definition: parse_dbi.c:2224
#define ER_OBJ_TEMPLATE_INTERNAL
Definition: error_code.h:281
SM_FOREIGN_KEY_INFO * fk_info
Definition: class_object.h:537
PT_NODE * attr_name
Definition: parse_tree.h:1858
PT_NODE ** parser_parse_string_use_sys_charset(PARSER_CONTEXT *parser, const char *buffer)
PT_STATEMENT_INFO info
Definition: parse_tree.h:3487
#define PT_ERRORm(parser, node, setNo, msgNo)
Definition: parse_tree.h:63
static int acquire_locks_for_multiple_rename(const PT_NODE *statement)
int dbt_drop_attribute(DB_CTMPL *def, const char *name)
Definition: db_temp.c:653
DB_OBJLIST * inheritance
Definition: class_object.h:718
PT_NODE * spec_list
Definition: parse_tree.h:2309
TP_DOMAIN * classobj_find_cons_index2_col_type_list(SM_CLASS_CONSTRAINT *cons, OID *root_oid)
int tp_domain_compatible(const TP_DOMAIN *src, const TP_DOMAIN *dest)
PT_NODE * values
Definition: parse_tree.h:2029
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
PT_NODE * default_value
Definition: parse_tree.h:2004
#define ER_SM_ATTR_NOT_NULL
Definition: error_code.h:1327
#define ER_ALTER_CHANGE_CLASS_HIERARCHY
Definition: error_code.h:1302
#define ER_INVALID_PARTITION_REQUEST
Definition: error_code.h:1123
PT_NODE * table_option_list
Definition: parse_tree.h:1905
static int do_recreate_att_constraints(MOP class_mop, SM_CONSTRAINT_INFO *constr_info_list)
static int get_index_type_qualifiers(MOP obj, bool *is_reverse, bool *is_unique, const char *index_name)
static int check_default_on_update_clause(PARSER_CONTEXT *parser, PT_NODE *attribute)
int smt_quit(SM_TEMPLATE *template_)
PT_NODE * spec
Definition: parse_tree.h:3182
DB_ATTRIBUTE * db_get_attributes(DB_OBJECT *obj)
Definition: db_info.c:908
#define CHECK_2ARGS_ERROR(obj1, obj2)
Definition: db.h:195
#define MSGCAT_SEMANTIC_INVALID_SET_ELEMENT
PT_ATTR_ORDERING_INFO attr_ordering
Definition: parse_tree.h:3273
int pt_check_enum_data_type(PARSER_CONTEXT *parser, PT_NODE *dt)
SM_PREDICATE_INFO * filter_predicate
Definition: class_object.h:536
int dbt_drop_constraint(DB_CTMPL *def, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **attnames, int class_attributes)
Definition: db_temp.c:473
int obj_delete(MOP op)
int classobj_copy_attlist(SM_ATTRIBUTE *attlist, MOP filter_class, int ordered, SM_ATTRIBUTE **copy_ptr)
char * MOBJ
Definition: work_space.h:174
bool tr_get_execution_state(void)
#define CHECK_PARTITION_PARENT
static int do_change_att_schema_only(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *attribute, PT_NODE *old_name_node, PT_NODE *constraints, SM_ATTR_PROP_CHG *attr_chg_prop, SM_ATTR_CHG_SOL *change_mode)
#define ER_FK_CANT_ON_PARTITION
Definition: error_code.h:1248
DB_ATTRIBUTE * db_get_class_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:878
MOBJ locator_fetch_set(int num_mops, MOP *mop_set, DB_FETCH_MODE inst_purpose, DB_FETCH_MODE class_purpose, int quit_on_errors)
Definition: locator_cl.c:2464
DB_ATTRIBUTE * partition_parent_atts
Definition: class_object.h:813
#define TP_IS_SET_TYPE(typenum)
#define ER_SM_NO_PARTITION_ON_HIERARCHIES
Definition: error_code.h:1597
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
struct pt_alter_info::@111::@119 auto_increment
DB_DOMAIN * pt_type_enum_to_db_domain(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:1549
PT_MISC_TYPE
Definition: parse_tree.h:983
#define PARTITIONED_SUB_CLASS_TAG
Definition: parse_tree.h:2033
static DB_QUERY_TYPE * query_get_column_with_name(DB_QUERY_TYPE *query_columns, const char *name)
PT_NODE * mq_translate(PARSER_CONTEXT *parser, PT_NODE *volatile node)
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_get_int(const DB_VALUE *value)
int do_add_supers(const PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, const PT_NODE *supers)
#define ER_QPROC_DB_SERIAL_NOT_FOUND
Definition: error_code.h:964
#define ER_INHERIT_FROM_PARTITION_TABLE
Definition: error_code.h:1508
MOBJ locator_create_heap_if_needed(MOP class_mop, bool reuse_oid)
Definition: locator_cl.c:5690
DB_TYPE
Definition: dbtype_def.h:670
#define ER_INTERFACE_NOT_SUPPORTED_OPERATION
Definition: error_code.h:1177
#define ER_FAILED
Definition: error_code.h:47
DB_OBJLIST * inheritance
Definition: class_object.h:788
DB_TYPE db_type
Definition: db_query.h:60
int do_rename(const PARSER_CONTEXT *parser, const PT_NODE *statement)
int db_make_varchar(DB_VALUE *value, const int max_char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
int pt_get_select_query_columns(PARSER_CONTEXT *parser, PT_NODE *create_select, DB_QUERY_TYPE **query_columns)
#define AUTO_INCREMENT_SERIAL_NAME_EXTRA_LENGTH
Definition: transform.h:179
int locator_redistribute_partition_data(OID *class_oid, int no_oids, OID *oid_list)
SM_METHOD * class_methods
Definition: class_object.h:795
#define MSGCAT_SEMANTIC_OUT_OF_MEMORY
SM_CLASS_CONSTRAINT * classobj_find_class_primary_key(SM_CLASS *class_)
static PT_NODE * create_select_to_insert_into(PARSER_CONTEXT *parser, const char *class_name, PT_NODE *create_select, PT_CREATE_SELECT_ACTION create_select_action, DB_QUERY_TYPE *query_columns)
SM_CLASS_CONSTRAINT * classobj_find_cons_primary_key(SM_CLASS_CONSTRAINT *cons_list)
#define ER_ALTER_CHANGE_HARD_DEFAULT_NOT_EXIST
Definition: error_code.h:1329
static int drop_class_name(const char *name, bool is_cascade_constraints)
#define ER_AU_USER_EXISTS
Definition: error_code.h:228
struct tp_domain * setdomain
Definition: object_domain.h:82
TP_DOMAIN * domain
Definition: class_object.h:444
PT_SPEC_INFO spec
Definition: parse_tree.h:3346
#define UNIQUE_SAVEPOINT_GRANT_USER
#define ER_FK_MUST_NOT_BE_NOT_NULL
Definition: error_code.h:1249
ATTR_ID * attrids_pred
Definition: xasl.h:1060
int dbt_drop_resolution(DB_CTMPL *def, MOP super, const char *name)
Definition: db_temp.c:1160
static int do_alter_clause_rename_entity(PARSER_CONTEXT *const parser, PT_NODE *const alter)
static const char * attribute_name(PARSER_CONTEXT *parser, PT_NODE *att)
int dbt_change_default(DB_CTMPL *def, const char *name, int class_attribute, DB_VALUE *value)
Definition: db_temp.c:611
PT_NODE * arg2
Definition: parse_tree.h:2664
void db_namelist_free(DB_NAMELIST *list)
Definition: db_virt.c:71
DB_CTMPL * dbt_copy_class(const char *new_name, const char *existing_name, SM_CLASS **class_)
Definition: db_temp.c:160
SM_CONSTRAINT_TYPE
Definition: class_object.h:274
static int do_promote_partition(SM_CLASS *class_)
SM_FOREIGN_KEY_ACTION
void pt_reset_error(PARSER_CONTEXT *parser)
static int get_att_order_from_def(PT_NODE *attribute, bool *ord_first, const char **ord_after_name)
PT_NODE * object_id_list
Definition: parse_tree.h:1910
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
PT_TABLE_OPTION_INFO table_option
Definition: parse_tree.h:3347
enum pt_type_enum PT_TYPE_ENUM
Definition: parse_tree.h:962
struct setobj * set
Definition: db_set.h:43
SM_PARTITION * partition
Definition: class_object.h:760
int do_check_partitioned_class(DB_OBJECT *classop, int check_map, char *keyattr)
#define ASSERT_ERROR_AND_SET(error_code)
int db_query_end(DB_QUERY_RESULT *result)
Definition: db_query.c:3362
void pt_record_error(PARSER_CONTEXT *parser, int stmt_no, int line_no, int col_no, const char *msg, const char *context)
DB_SEQ * properties
Definition: class_object.h:807
#define UNIQUE_SAVEPOINT_CHANGE_COLUMN_COMMENT
#define assert_release(e)
Definition: error_manager.h:96
#define DB_MAX_NCHAR_PRECISION
Definition: dbtype_def.h:541
#define SM_MAX_IDENTIFIER_LENGTH
static int do_recreate_saved_indexes(MOP classmop, SM_CONSTRAINT_INFO *index_save_info)
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
int do_drop_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
#define PARTITION_VARCHAR_LEN
PT_EXPR_INFO expr
Definition: parse_tree.h:3299
int db_truncate_class(DB_OBJECT *class_)
Definition: db_class.c:1859
PARSER_CONTEXT * parser_create_parser(void)
Definition: parse_tree.c:1169
int do_set_object_id(const PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *object_id_list)
static bool is_attribute_primary_key(const char *class_name, const char *attr_name)
PT_NODE * pt_entity(PARSER_CONTEXT *parser, const PT_NODE *entity_name, const PT_NODE *range_var, const PT_NODE *flat_list)
int db_value_compare(const DB_VALUE *value1, const DB_VALUE *value2)
Definition: db_macro.c:1855
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2552
PT_GRANT_INFO grant
Definition: parse_tree.h:3306
#define ER_PARTITION_EXPRESSION_TOO_LONG
Definition: error_code.h:1539
static int add_query_to_virtual_class(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, const PT_NODE *queries)
void * triggers
Definition: class_object.h:811
static int truncate_class_name(const char *name)
int do_rollback(PARSER_CONTEXT *parser, PT_NODE *statement)
PT_TYPE_ENUM pt_db_to_type_enum(const DB_TYPE t)
Definition: parse_dbi.c:2595
#define ER_SM_CONSTRAINT_HAS_DIFFERENT_TYPE
Definition: error_code.h:1256
const char * pt_type_enum_to_db_domain_name(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:1427
SM_NAME_SPACE
PARSER_CONTEXT * db_get_parser(DB_SESSION *session)
Definition: db_vdb.c:3714
#define ER_PARTITION_NOT_EXIST
Definition: error_code.h:1110
#define PT_IS_LOB_TYPE(t)
Definition: parse_tree.h:239
DB_OBJECT * dbt_finish_class(DB_CTMPL *def)
Definition: db_temp.c:226
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define ER_ALTER_CHANGE_WARN_NO_CHANGE
Definition: error_code.h:1311
void sm_free_constraint_info(SM_CONSTRAINT_INFO **save_info)
static int do_remove_partition_post(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
DB_OBJECT * db_find_user(const char *name)
Definition: db_admin.c:1606
PT_NODE * ordering_info
Definition: parse_tree.h:1862
#define SM_IS_CONSTRAINT_UNIQUE_FAMILY(c)
Definition: class_object.h:111
static int do_create_partition_constraints(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
SM_CLASS_CONSTRAINT * classobj_find_constraint_by_name(SM_CLASS_CONSTRAINT *cons_list, const char *name)
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
#define OID_SET_NULL(oidp)
Definition: oid.h:85
static int do_reorganize_partition_post(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
void pt_exit_packing_buf(void)
int do_alter(PARSER_CONTEXT *parser, PT_NODE *alter)
void sm_downcase_name(const char *name, char *buf, int maxlen)
#define ER_CANNOT_HAVE_PK_DEFAULT_NULL
Definition: error_code.h:1380
int do_update_auto_increment_serial_on_rename(MOP serial_obj, const char *class_name, const char *att_name)
PT_NODE * as_attr_mthd_name
Definition: parse_tree.h:2642
DB_OBJLIST * db_get_superclasses(DB_OBJECT *obj)
Definition: db_info.c:630
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
SM_FUNCTION_INFO * func_index_info
Definition: class_object.h:541
SM_NAME_SPACE new_name_space
int smt_add_constraint(SM_TEMPLATE *template_, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, const int *asc_desc, const int *attrs_prefix_length, int class_attribute, SM_FOREIGN_KEY_INFO *fk_info, SM_PREDICATE_INFO *filter_index, SM_FUNCTION_INFO *function_index, const char *comment, SM_INDEX_STATUS index_status)
static int do_add_attribute_from_select_column(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, DB_QUERY_TYPE *column)
const char * pname
Definition: class_object.h:694
unsigned int custom_print
Definition: parse_tree.h:3556
#define ER_SM_INDEX_PREFIX_LENGTH_ON_UNIQUE_FOREIGN
Definition: error_code.h:1258
TP_DOMAIN * tp_domain_copy(const TP_DOMAIN *domain, bool check_cache)
static int do_coalesce_partition_post(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
struct sm_constraint_info * next
DB_DOMAIN * pt_node_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *node, const char *class_name)
Definition: parse_dbi.c:2244
struct sm_class_constraint * next
Definition: class_object.h:530
#define DB_MAX_PARTITION_EXPR_LENGTH
Definition: dbtype_def.h:619
SM_NAME_SPACE name_space
Definition: class_object.h:386
#define GET_NAME(n)
int er_errid(void)
PT_ALTER_CODE
Definition: parse_tree.h:1224
int smt_add_set_argument_domain(SM_TEMPLATE *template_, const char *name, int class_method, const char *implementation, int index, const char *domain_string, DB_DOMAIN *domain)
int db_is_subclass(MOP classmop, MOP supermop)
Definition: db_info.c:445
int do_get_partition_parent(DB_OBJECT *const classop, MOP *const parentop)
int sm_set_class_comment(MOP classop, const char *comment)
static int do_reorganize_partition_pre(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
int dbt_add_set_attribute_domain(DB_CTMPL *def, const char *name, int class_attribute, const char *domain)
Definition: db_temp.c:569
const char * comment
Definition: class_object.h:698
#define PT_NAME_INFO_IS_FLAGED(e, f)
Definition: parse_tree.h:2574
#define ER_SM_CONSTRAINT_NOT_FOUND
Definition: error_code.h:870
PT_NODE * attr_mthd_name
Definition: parse_tree.h:2640
PT_MISC_TYPE mthd_type
Definition: parse_tree.h:2379
PT_NODE * pt_sort_in_desc_order(PT_NODE *vlist)
Definition: parse_dbi.c:2484
int sm_save_function_index_info(SM_FUNCTION_INFO **save_info, SM_FUNCTION_INFO *func_index_info)
#define TP_TIMESTAMPTZ_AS_CHAR_LENGTH
#define MSGCAT_SEMANTIC_INVALID_PARTITION_DEFINITION
static int do_alter_change_tbl_comment(PARSER_CONTEXT *const parser, PT_NODE *const alter)
HFID * sm_get_ch_heap(MOP classmop)
#define UNIQUE_SAVEPOINT_CHANGE_ATTR
PT_NODE * function_expr
Definition: parse_tree.h:1935
DB_VALUE * max
int collation_id
Definition: class_object.h:750
#define UNIQUE_SAVEPOINT_ALTER_INDEX
PT_NODE * attr_list
Definition: parse_tree.h:2333
int do_drop(PARSER_CONTEXT *parser, PT_NODE *statement)
unsigned partition_pruned
Definition: parse_tree.h:3463
#define UNIQUE_SAVEPOINT_MULTIPLE_ALTER
PT_NODE * spec_list
Definition: parse_tree.h:2097
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
static int do_alter_clause_change_attribute(PARSER_CONTEXT *const parser, PT_NODE *const alter)
int db_class_has_instance(DB_OBJECT *classobj)
Definition: db_info.c:686
int locator_upgrade_instances_domain(OID *class_oid, int attribute_id)
int db_attribute_is_shared(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1429
const char * AU_PUBLIC_USER_NAME
Definition: authenticate.c:112
PT_NODE * data_type
Definition: parse_tree.h:3453
int db_attribute_is_non_null(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1355
static int do_find_auto_increment_serial(MOP *auto_increment_obj, const char *class_name, const char *attr_name)
PT_NODE * new_name
Definition: parse_tree.h:2624
DB_ATTRIBUTE * db_get_attribute_by_name(const char *class_name, const char *attribute_name)
Definition: db_info.c:823
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
SM_FOREIGN_KEY_ACTION update_action
Definition: class_object.h:482
void ws_free_string(const char *str)
Definition: work_space.c:3480
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: parse_tree.h:2006
#define UNIQUE_SAVEPOINT_CHANGE_TBL_COMMENT
PT_DOT_INFO dot
Definition: parse_tree.h:3287
#define UNIQUE_SAVEPOINT_ADD_ATTR_MTHD
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
PT_NODE * arg2
Definition: parse_tree.h:2086
SM_CLASS_CONSTRAINT * sm_class_constraints(MOP classop)
PT_FOREIGN_KEY_INFO foreign_key
Definition: parse_tree.h:3105
#define ERROR0(error, code)
Definition: error_manager.h:48
SM_METHOD * methods
Definition: class_object.h:791
int pt_coerce_value_for_default_value(PARSER_CONTEXT *parser, PT_NODE *src, PT_NODE *dest, PT_TYPE_ENUM desired_type, PT_NODE *elem_type_list, DB_DEFAULT_EXPR_TYPE default_expr_type)
int dbt_add_super(DB_CTMPL *def, MOP super)
Definition: db_temp.c:905
DB_VALUE * min
static int build_att_type_change_map(TP_DOMAIN *curr_domain, TP_DOMAIN *req_domain, SM_ATTR_PROP_CHG *attr_chg_properties)
int smt_add_attribute_w_dflt_w_order(DB_CTMPL *def, const char *name, const char *domain_string, DB_DOMAIN *domain, DB_VALUE *default_value, const SM_NAME_SPACE name_space, const bool add_first, const char *add_after_attribute, DB_DEFAULT_EXPR *default_expr, DB_DEFAULT_EXPR_TYPE *on_update, const char *comment)
static int check_change_attribute(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *attribute, PT_NODE *old_name_node, PT_NODE **pointer_constraints, SM_ATTR_PROP_CHG *attr_chg_prop, SM_ATTR_CHG_SOL *change_mode)
PT_NODE * method_args_list
Definition: parse_tree.h:2377
#define MSGCAT_SEMANTIC_CANT_COERCE_TO
int ib_get_thread_count()
DB_QUERY_TYPE * db_query_format_next(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1577
void parser_free_parser(PARSER_CONTEXT *parser)
Definition: parse_tree.c:1240
const char * comment
Definition: class_object.h:542
int do_truncate(PARSER_CONTEXT *parser, PT_NODE *statement)
int dbt_add_class_resolution(DB_CTMPL *def, MOP super, const char *name, const char *alias)
Definition: db_temp.c:1139
static int do_alter_index_comment(PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_NODE * class_attr_def_list
Definition: parse_tree.h:1903
#define CT_SERIAL_NAME
Definition: transform.h:135
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
#define UNIQUE_SAVEPOINT_DROP_ENTITY
int intl_identifier_lower(const char *src, char *dst)
int smt_change_constraint_comment(SM_TEMPLATE *ctemplate, const char *index_name, const char *comment)
int do_recreate_filter_index_constr(PARSER_CONTEXT *parser, SM_PREDICATE_INFO *filter_index_info, PT_NODE *alter, const char *src_cls_name, const char *new_cls_name)
SM_CONSTRAINT_FAMILY
Definition: class_object.h:321
int er_get_severity(void)
PT_TYPE_ENUM type_enum
Definition: parse_tree.h:3457
static DB_CONSTRAINT_TYPE get_reverse_unique_index_type(const bool is_reverse, const bool is_unique)
void pt_report_to_ersys(const PARSER_CONTEXT *parser, const PT_ERROR_TYPE error_type)
Definition: query_result.c:287
int size
Definition: set_object.h:72
PT_NODE * indexed_class
Definition: parse_tree.h:1927
char * db_query_format_name(DB_QUERY_TYPE *query_type)
Definition: db_query.c:1609
#define ER_ALTER_CHANGE_ADD_NOT_NULL_SET_HARD_DEFAULT
Definition: error_code.h:1328
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
DB_TYPE pt_type_enum_to_db(const PT_TYPE_ENUM t)
Definition: parse_dbi.c:2314
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
#define UNIQUE_SAVEPOINT_TRUNCATE
#define ER_PT_SEMANTIC
Definition: error_code.h:581
unsigned char bytes[1]
Definition: parse_tree.h:3431
#define ER_UNEXPECTED
Definition: error_code.h:1254
int file_apply_tde_to_class_files(const OID *class_oid)
#define PT_ERRORmf3(parser, node, setNo, msgNo, arg1, arg2, arg3)
Definition: parse_tree.h:66
SM_CONSTRAINT_INFO * new_constr_info
PT_NODE * limit
Definition: parse_tree.h:2773
DB_DATA data
Definition: dbtype_def.h:1083
PT_NODE * pt_semantic_check(PARSER_CONTEXT *parser, PT_NODE *node)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
SM_CONSTRAINT_INFO * constr_info
int do_drop_partitioned_class(MOP class_, int drop_sub_flag, bool is_cascade_constraints)
PT_NODE * partition_info
Definition: parse_tree.h:1914
#define ER_NOTNULL_ON_TYPE_WITHOUT_DEFAULT_VALUE
Definition: error_code.h:1319
void pt_free_statement_xasl_id(PT_NODE *statement)
#define DB_MAX_VARBIT_PRECISION
Definition: dbtype_def.h:552
DB_ATTRIBUTE * db_get_attribute(DB_OBJECT *obj, const char *name)
Definition: db_info.c:791
#define ER_SM_NOT_NULL_NOT_ALLOWED
Definition: error_code.h:1267
union pt_alter_info::@111 alter_clause
PT_NODE * arg1
Definition: parse_tree.h:2663
int pt_check_grammar_charset_collation(PARSER_CONTEXT *parser, PT_NODE *charset_node, PT_NODE *coll_node, int *charset, int *coll_id)
void classobj_initialize_default_expr(DB_DEFAULT_EXPR *default_expr)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
PT_ALTER_INFO alter
Definition: parse_tree.h:3268
int do_add_resolutions(const PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, const PT_NODE *resolution)
Definition: db_set.h:35
bool classobj_is_pk_referred(MOP clsop, SM_FOREIGN_KEY_INFO *fk_info, bool include_self_ref, char **fk_name)
INTL_CODESET codeset
static int add_union_query(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, const PT_NODE *query)
LANG_COLLATION * lang_get_collation(const int coll_id)
#define TP_TIMESTAMP_AS_CHAR_LENGTH
PT_NODE * index_name
Definition: parse_tree.h:1929
#define UNIQUE_PARTITION_SAVEPOINT_ALTER
const char * sm_ch_name(const MOBJ clobj)
short constrain_not_null
Definition: parse_tree.h:1866
#define ER_QPROC_SERIAL_NOT_FOUND
Definition: error_code.h:965
#define DB_MAX_VARCHAR_PRECISION
Definition: dbtype_def.h:536
int tp_domain_match(const TP_DOMAIN *dom1, const TP_DOMAIN *dom2, TP_MATCH exact)
DB_OBJECT * db_object
Definition: parse_tree.h:2546
#define DB_MAX_NUMERIC_PRECISION
Definition: dbtype_def.h:522
PT_OP_TYPE pt_op_type_from_default_expr_type(DB_DEFAULT_EXPR_TYPE expr_type)
void pt_get_default_expression_from_data_default_node(PARSER_CONTEXT *parser, PT_NODE *data_default_node, DB_DEFAULT_EXPR *default_expr)
PT_NODE * parser_make_expression(PARSER_CONTEXT *parser, PT_OP_TYPE OP, PT_NODE *arg1, PT_NODE *arg2, PT_NODE *arg3)
#define PT_ERRORmf2(parser, node, setNo, msgNo, arg1, arg2)
Definition: parse_tree.h:65
int tran_abort_upto_system_savepoint(const char *savepoint_name)
#define assert(x)
static SM_PARTITION * pt_node_to_partition_info(PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *entity_name, char *class_name, char *partition_name, DB_VALUE *minval)
int dbt_drop_method(DB_CTMPL *def, const char *name)
Definition: db_temp.c:865
#define ER_ALTER_CHANGE_ATTR_TO_FROM_SHARED_NOT_ALLOWED
Definition: error_code.h:1417
PT_NODE * constraint_list
Definition: parse_tree.h:1912
#define ER_SM_NO_INDEX
Definition: error_code.h:345
PT_NODE * resolution_list
Definition: parse_tree.h:1756
#define ER_ALTER_CHANGE_TYPE_WITH_INDEX
Definition: error_code.h:1309
PT_NODE * referenced_attrs
Definition: parse_tree.h:3086
DB_CONSTRAINT_TYPE
Definition: dbtype_def.h:452
int set_add_element(DB_COLLECTION *set, DB_VALUE *value)
Definition: set_object.c:2641
SM_PARTITION * partition
SM_ATTR_CHG_SOL
int do_add_method_files(const PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *method_files)
struct pt_alter_info::@111::@113 attr_mthd
TDE_ALGORITHM
Definition: tde.h:71
#define ER_LC_UNKNOWN_CLASSNAME
Definition: error_code.h:121
int sm_att_constrained(MOP classop, const char *name, SM_ATTRIBUTE_FLAG cons)
SM_PARTITION * partition
Definition: class_object.h:814
PT_NODE * query
Definition: parse_tree.h:1762
SM_ATTRIBUTE * shared_attributes
Definition: class_object.h:803
DB_QUERY_TYPE * query_type
Definition: db_query.h:119
PT_PARTITION_TYPE type
Definition: parse_tree.h:2030
PT_NODE * method_name
Definition: parse_tree.h:2376
static int build_attr_change_map(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *attr_def, PT_NODE *attr_old_name, PT_NODE *constraints, SM_ATTR_PROP_CHG *attr_chg_properties)
#define AUTO_INCREMENT_SERIAL_NAME_MAX_LENGTH
Definition: transform.h:180
int smt_change_constraint_status(SM_TEMPLATE *ctemplate, const char *index_name, SM_INDEX_STATUS index_status)
char * spec_name
Definition: db_query.h:58
PT_MISC_TYPE asc_or_desc
Definition: parse_tree.h:2830
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)
static int adjust_partition_size(MOP class_, DB_CTMPL *tmpl)
SM_PARTITION * classobj_make_partition_info(void)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
struct db_value_slist * next
static int do_save_all_indexes(MOP classmop, SM_CONSTRAINT_INFO **saved_index_info_listpp)
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
static int validate_attribute_domain(PARSER_CONTEXT *parser, PT_NODE *attribute, const bool check_zero_precision)
#define ERROR1(error, code, arg1)
Definition: error_manager.h:56
int sm_att_default_value(MOP classop, const char *name, DB_VALUE *value, DB_DEFAULT_EXPR **default_expr, DB_DEFAULT_EXPR_TYPE **on_update_expr)
int do_grant(const PARSER_CONTEXT *parser, const PT_NODE *statement)
int db_constrain_non_null(MOP class_, const char *name, int class_attribute, int on_or_off)
Definition: db_class.c:1455
DB_VALUE db_value
Definition: parse_tree.h:3059
PT_NODE * of_sup_class_name
Definition: parse_tree.h:2641
PT_MISC_TYPE grant_option
Definition: parse_tree.h:2310
PT_NODE * hashsize
Definition: parse_tree.h:2021
PART_CLASS_INFO * next
int do_add_queries(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, const PT_NODE *queries)
#define ER_FK_CANT_ON_SHARED_ATTRIBUTE
Definition: error_code.h:1263
PT_MISC_TYPE with_check_option
Definition: parse_tree.h:1900
int db_query_first_tuple(DB_QUERY_RESULT *result)
Definition: db_query.c:2309
const char * pt_show_type_enum(PT_TYPE_ENUM t)
#define ER_IT_DATA_OVERFLOW
Definition: error_code.h:505
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
int smt_assign_argument_domain(SM_TEMPLATE *template_, const char *name, int class_method, const char *implementation, int index, const char *domain_string, DB_DOMAIN *domain)
PT_NODE * entity
Definition: parse_tree.h:2038
#define MSGCAT_SET_PARSER_RUNTIME
int db_attribute_is_primary_key(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1255
PT_DATA_VALUE data_value
Definition: parse_tree.h:3058
PT_NODE * flat_entity_list
Definition: parse_tree.h:2140
int smt_add_attribute_w_dflt(DB_CTMPL *def, const char *name, const char *domain_string, DB_DOMAIN *domain, DB_VALUE *default_value, const SM_NAME_SPACE name_space, DB_DEFAULT_EXPR *default_expr, DB_DEFAULT_EXPR_TYPE *on_update, const char *comment)
int do_rename_partition(MOP old_class, const char *newname)
PT_MISC_TYPE all_distinct
Definition: parse_tree.h:2746
DB_VALUE original_value
Definition: class_object.h:393
unsigned is_desc
static int do_update_new_notnull_cols_without_default(PARSER_CONTEXT *parser, PT_NODE *alter, MOP class_mop)
void lang_set_parser_use_client_charset(bool use)
#define CHECK_1ARG_ERROR(obj)
Definition: db.h:186
int sm_is_partitioned_class(MOP op)
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:725
struct pt_alter_info::@111::@117 collation
#define MSGCAT_SEMANTIC_OVERFLOW_COERCING_TO
static PT_NODE * replace_names_alter_chg_attr(PARSER_CONTEXT *parser, PT_NODE *node, void *void_arg, int *continue_walk)
const char * original
Definition: parse_tree.h:2544
int dbt_rename_method_file(DB_CTMPL *def, const char *old_name, const char *new_name)
Definition: db_temp.c:1075
int sm_save_constraint_info(SM_CONSTRAINT_INFO **save_info, const SM_CLASS_CONSTRAINT *const c)
PT_NODE * pt_semantic_quick_check_node(PARSER_CONTEXT *parser, PT_NODE **spec_p, PT_NODE **node_p)
int au_set_password(MOP user, const char *password)
DB_SEQ * db_seq_copy(DB_SEQ *source)
Definition: db_set.c:428
int sm_update_statistics(MOP classop, bool with_fullscan)
int intl_identifier_casecmp(const char *str1, const char *str2)
#define ER_SM_INVALID_FILTER_PREDICATE_LENGTH
Definition: error_code.h:1353
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
int db_value_free(DB_VALUE *value)
Definition: db_macro.c:1610
void pt_evaluate_tree_having_serial(PARSER_CONTEXT *parser, PT_NODE *tree, DB_VALUE *db_value, int vals_cnt)
PT_PARTITION_INFO partition
Definition: parse_tree.h:3321
#define MSGCAT_RUNTIME_RESOURCES_EXHAUSTED
#define DB_MAX_IDENTIFIER_LENGTH
Definition: dbtype_def.h:495
SM_DOMAIN * domain
Definition: db_query.h:62
#define TP_DOMAIN_COLLATION(dom)
PT_NODE_TYPE node_type
Definition: parse_tree.h:3439
int locator_flush_class(MOP class_mop)
Definition: locator_cl.c:5068
void au_change_owner_method(MOP obj, DB_VALUE *returnval, DB_VALUE *class_, DB_VALUE *owner)
PT_NODE * string
Definition: parse_tree.h:2252
SM_QUERY_SPEC * query_spec
Definition: class_object.h:800
PT_NODE * parser_copy_tree(PARSER_CONTEXT *parser, const PT_NODE *tree)
#define UNIQUE_SAVEPOINT_CHANGE_DEF_COLL
PT_PARTITION_TYPE type
Definition: parse_tree.h:2023
#define SM_COMPARE_NAMES
Definition: class_object.h:47
PT_NODE * pt_semantic_type(PARSER_CONTEXT *parser, PT_NODE *tree, SEMANTIC_CHK_INFO *sc_info)
DB_CTMPL * dbt_create_vclass(const char *name)
Definition: db_temp.c:104
DB_SEQ * values
Definition: class_object.h:696
#define ER_DO_ALTER_ADD_WITH_UNIQUE
Definition: error_code.h:900
int do_create_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_PARTS_INFO parts
Definition: parse_tree.h:3322
#define MAX_FILTER_PREDICATE_STRING_LENGTH
static int do_update_new_cols_with_default_expression(PARSER_CONTEXT *parser, PT_NODE *alter, MOP class_mop)
char * attr_name
Definition: db_query.h:57
DB_ATTRIBUTE * db_attribute_next(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1020
SM_ATTRIBUTE * instance_attributes
Definition: class_object.h:802
PT_FILE_PATH_INFO file_path
Definition: parse_tree.h:3300
int dbt_drop_super(DB_CTMPL *def, MOP super)
Definition: db_temp.c:925
DO_INDEX
const char * sm_get_ch_name(MOP op)
DB_DOMAIN * pt_data_type_to_db_domain(PARSER_CONTEXT *parser, PT_NODE *dt, const char *class_name)
Definition: parse_dbi.c:1805
PT_NODE * from
Definition: parse_tree.h:2686
static int do_drop_saved_indexes(MOP classmop, SM_CONSTRAINT_INFO *index_save_info)
PT_HINT_ENUM hint
Definition: parse_tree.h:1828
VID_OID oid_info
Definition: work_space.h:120
int dbt_add_resolution(DB_CTMPL *def, MOP super, const char *name, const char *alias)
Definition: db_temp.c:1117
int do_create_local(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *pt_node, DB_QUERY_TYPE *create_select_columns)
DB_VALUE * db_value_copy(DB_VALUE *value)
Definition: db_macro.c:1537
static int update_locksets_for_multiple_rename(const char *class_name, int *num_mops, MOP *mop_set, int *num_names, char **name_set, bool error_on_misssing_class)
#define DB_IS_CONSTRAINT_REVERSE_INDEX_FAMILY(c)
Definition: dbtype_def.h:177
int do_add_constraints(DB_CTMPL *ctemplate, PT_NODE *constraints)
#define CHECK_3ARGS_ERROR(obj1, obj2, obj3)
Definition: db.h:198
#define TP_DOMAIN_TYPE(dom)
int do_check_fk_constraints(DB_CTMPL *ctemplate, PT_NODE *constraints)
TP_DOMAIN * fi_domain
Definition: class_object.h:502
PT_ALTER_CODE code
Definition: parse_tree.h:1937
PT_DATA_TYPE_INFO data_type
Definition: parse_tree.h:3284
void pt_enter_packing_buf(void)
int db_grant(MOP user, MOP class_, AU_TYPE auth, int grant_option)
Definition: db_admin.c:1794
static void cleanup(int signo)
Definition: broker.c:717
PARSER_VARCHAR * str
Definition: parse_tree.h:3036
#define PT_NAME_INFO_DESC
Definition: parse_tree.h:2564
struct pt_alter_info::@111::@118 index
SP_PARSER_CTX * parser
DB_OBJECT * obj
PT_ATTR_DEF_INFO attr_def
Definition: parse_tree.h:3272
PT_NODE * comment
Definition: parse_tree.h:2031
PT_NODE * comment
Definition: parse_tree.h:1936
#define NULL
Definition: freelistheap.h:34
PT_ALTER_CODE code
Definition: parse_tree.h:1751
OID oid
Definition: work_space.h:65
struct pt_alter_info::@111::@121 comment
static int get_att_default_from_def(PARSER_CONTEXT *parser, PT_NODE *attribute, DB_VALUE **default_value, const char *classname)
int tp_valid_indextype(DB_TYPE type)
static int do_alter_change_default_cs_coll(PARSER_CONTEXT *const parser, PT_NODE *const alter)
const char * er_msg(void)
int db_is_class(MOP obj)
Definition: db_info.c:310
struct pr_type * type
Definition: object_domain.h:76
PT_NODE * value_clauses
Definition: parse_tree.h:2334
#define UNIQUE_SAVEPOINT_DROP_USER_ENTITY
if(extra_options)
Definition: dynamic_load.c:958
DB_SESSION * db_open_buffer(const char *buffer)
Definition: db_vdb.c:232
static int do_run_update_query_for_class(char *query, MOP class_mop, int *row_count)
PT_INDEX_INFO index
Definition: parse_tree.h:3308
int db_compile_statement(DB_SESSION *session)
Definition: db_vdb.c:766
void db_close_session(DB_SESSION *session)
Definition: db_vdb.c:3319
int do_change_auto_increment_serial(PARSER_CONTEXT *const parser, MOP serial_obj, PT_NODE *node_new_val)
bool allow_prefix_index
#define SM_PROPERTY_UNIQUE
#define PT_VALUE_GET_BYTES(node)
Definition: parse_tree.h:250
PT_NODE * where
Definition: parse_tree.h:1934
DB_AUTH pt_auth_to_db_auth(const PT_NODE *auth)
Definition: parse_dbi.c:2539
PT_TABLE_OPTION_TYPE option
Definition: parse_tree.h:2916
void db_free_query(DB_SESSION *session)
Definition: db_vdb.c:3683
LC_FIND_CLASSNAME
static int execute_create_select_query(PARSER_CONTEXT *parser, const char *const class_name, PT_NODE *create_select, PT_CREATE_SELECT_ACTION create_select_action, DB_QUERY_TYPE *query_columns, PT_NODE *flagged_statement)
PT_CREATE_SELECT_ACTION create_select_action
Definition: parse_tree.h:1919
PT_CREATE_ENTITY_INFO create_entity
Definition: parse_tree.h:3279
#define SM_IS_CONSTRAINT_INDEX_FAMILY(c)
Definition: class_object.h:117
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
PARSER_VARCHAR * pt_print_bytes(PARSER_CONTEXT *parser, const PT_NODE *node)
#define TP_DATETIME_AS_CHAR_LENGTH
struct pt_alter_info::@110 super
int sm_set_class_collation(MOP classop, int collation_id)
#define ER_OBJ_INVALID_ATTRIBUTE
Definition: error_code.h:273
DB_CTMPL * dbt_create_class(const char *name)
Definition: db_temp.c:76
static int do_run_update_query_for_new_notnull_fields(PARSER_CONTEXT *parser, PT_NODE *alter, PT_NODE *attr_list, int attr_count, MOP class_mop)
#define TP_BIGINT_PRECISION
PT_NODE * spec_list
Definition: parse_tree.h:2651
#define PT_IS_COLLECTION_TYPE(t)
Definition: parse_tree.h:143
const char * loader_commands
Definition: class_object.h:799
#define TP_DATETIMETZ_AS_CHAR_LENGTH
short db_value_is_in_workspace
Definition: parse_tree.h:3061
int db_rename_class(MOP classop, const char *new_name)
Definition: db_class.c:151
PT_CREATE_SELECT_ACTION
Definition: parse_tree.h:1889
SM_TEMPLATE * smt_edit_class_mop(MOP op, DB_AUTH db_auth_type)
#define GET_STRING(n)
struct pt_alter_info::@111::@120 user
PT_NODE * vclass_comment
Definition: parse_tree.h:1918
int db_drop_user(DB_OBJECT *user)
Definition: db_admin.c:1668
PT_NODE * arg1
Definition: parse_tree.h:2085
PT_NODE * where
Definition: parse_tree.h:2687
PT_QUERY_INFO query
Definition: parse_tree.h:3325
int dbt_set_object_id(DB_CTMPL *def, DB_NAMELIST *id_list)
Definition: db_temp.c:1281
LC_FIND_CLASSNAME locator_reserve_class_names(const int num_classes, const char **class_names, OID *class_oids)
static int fetch_result(T_SRV_HANDLE *, int, int, char, int, T_NET_BUF *, T_REQ_INFO *)
Definition: cas_execute.c:5332
struct db_objlist * next
Definition: dbtype_def.h:442
int do_revoke(const PARSER_CONTEXT *parser, const PT_NODE *statement)
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:794
PT_AUTO_INCREMENT_INFO auto_increment
Definition: parse_tree.h:3275
static int do_alter_partitioning_pre(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
#define ER_CANNOT_HAVE_NOTNULL_DEFAULT_NULL
Definition: error_code.h:1332
#define MSGCAT_SEMANTIC_INV_PREC
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
PT_CONSTRAINT_TYPE type
Definition: parse_tree.h:3096
int pr_clear_value(DB_VALUE *value)
PT_NODE * spec
Definition: parse_tree.h:2331
void db_free_query_format(DB_QUERY_TYPE *q)
Definition: db_query.c:154
DB_CTMPL * dbt_edit_class(MOP classobj)
Definition: db_temp.c:133
#define ER_ALTER_CHANGE_TYPE_WITH_AUTO_INCR
Definition: error_code.h:1307
#define TP_TIME_AS_CHAR_LENGTH
#define UNIQUE_SAVEPOINT_CREATE_ENTITY
#define UNIQUE_SAVEPOINT_CREATE_USER_ENTITY
void pt_copy_statement_flags(PT_NODE *source, PT_NODE *destination)
DB_SEQ * properties
Definition: class_object.h:457
static int sort_constr_info_list(SM_CONSTRAINT_INFO **source)
#define ER_CANNOT_GET_LOCK
Definition: error_code.h:1255
int sm_set_class_tde_algorithm(MOP classop, TDE_ALGORITHM tde_algo)
SM_INDEX_STATUS index_status
Definition: parse_tree.h:1943
PT_NODE * prefix_length
Definition: parse_tree.h:1933
const char * comment
DB_DOMAIN * db_attribute_domain(DB_ATTRIBUTE *attribute)
Definition: db_info.c:1165
#define ER_ALTER_CHANGE_TYPE_NOT_SUPP
Definition: error_code.h:1305
bool is_cascade_constraints
Definition: parse_tree.h:2101
struct db_domain_info::general_info general_info
SM_RESOLUTION * resolutions
Definition: class_object.h:792
DB_METHOD * db_get_method(DB_OBJECT *obj, const char *name)
Definition: db_info.c:1454
static PT_NODE * get_attribute_with_name(PT_NODE *atts, const char *name)
DB_DEFAULT_EXPR_TYPE on_update
Definition: parse_tree.h:1860
static SM_FUNCTION_INFO * compile_partition_expression(PARSER_CONTEXT *parser, PT_NODE *entity_name, PT_NODE *pinfo)
PT_NODE * parser_append_node(PT_NODE *node, PT_NODE *list)
struct db_object * op
Definition: dbtype_def.h:443
char * pt_short_print(PARSER_CONTEXT *parser, const PT_NODE *node)
int dbt_add_method(DB_CTMPL *def, const char *name, const char *implementation)
Definition: db_temp.c:756
SM_CLASS_CONSTRAINT * constraints
Definition: class_object.h:757
int dbt_add_query_spec(DB_CTMPL *def, const char *query)
Definition: db_temp.c:1201
int smt_change_attribute_w_dflt_w_order(DB_CTMPL *def, const char *name, const char *new_name, const char *new_domain_string, DB_DOMAIN *new_domain, const SM_NAME_SPACE name_space, DB_VALUE *new_default_value, DB_DEFAULT_EXPR *new_default_expr, DB_DEFAULT_EXPR_TYPE on_update_expr, const bool change_first, const char *change_after_attribute, SM_ATTRIBUTE **found_att)
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
static SM_FUNCTION_INFO * pt_node_to_function_index(PARSER_CONTEXT *parser, PT_NODE *spec, PT_NODE *sort_spec, DO_INDEX do_index)
static int do_drop_att_constraints(MOP class_mop, SM_CONSTRAINT_INFO *constr_info_list)
int dbt_add_class_method(DB_CTMPL *def, const char *name, const char *implementation)
Definition: db_temp.c:777
DB_DEFAULT_EXPR_TYPE on_update_default_expr
Definition: class_object.h:452
static void reset_att_property_structure(SM_ATTR_PROP_CHG *attr_chg_properties)
void parser_free_node(const PARSER_CONTEXT *parser, PT_NODE *node)
Definition: parse_tree.c:869
unsigned int flags
Definition: class_object.h:459
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
const char * pt_data_type_to_db_domain_name(const PT_NODE *dt)
Definition: parse_dbi.c:1655
static int do_add_attribute(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *atts, PT_NODE *constraints, bool error_on_not_normal)
#define ER_SM_INVALID_DEF_CONSTRAINT_NAME_PARAMS
Definition: error_code.h:896
PT_NODE * column_names
Definition: parse_tree.h:1928
SM_CLASS_HEADER header
Definition: class_object.h:710
const unsigned char * pt_get_varchar_bytes(const PARSER_VARCHAR *string)
Definition: parse_tree.c:1089
#define CHECK_PARTITION_SUBS
SM_CLASS_CONSTRAINT * classobj_find_class_index(SM_CLASS *class_, const char *name)
#define TP_TYPE_HAS_COLLATION(typeid)
#define HFID_IS_NULL(hfid)
bool db_value_is_null(const DB_VALUE *value)
#define SM_IS_INDEX_FAMILY(c)
Definition: class_object.h:139
#define ER_SM_FK_MYSQL_DIFFERENT
Definition: error_code.h:1257
static int do_copy_indexes(PARSER_CONTEXT *parser, MOP classmop, SM_CLASS *src_class)
PT_NODE * referenced_class
Definition: parse_tree.h:3085
#define AU_SELECT
Definition: authenticate.h:69
#define MSGCAT_SET_ERROR
PT_SORT_SPEC_INFO sort_spec
Definition: parse_tree.h:3343
#define ER_AU_INVALID_USER
Definition: error_code.h:229
#define ER_LC_CLASSNAME_EXIST
Definition: error_code.h:122
DB_AUTH
Definition: dbtype_def.h:239
PT_NODE * old_name
Definition: parse_tree.h:2622
#define ARG_FILE_LINE
Definition: error_manager.h:44
PT_NODE * auto_increment
Definition: parse_tree.h:1861
static int do_alter_change_owner(PARSER_CONTEXT *const parser, PT_NODE *const alter)
SM_METHOD_FILE * method_files
Definition: class_object.h:798
int sm_partitioned_class_type(DB_OBJECT *classop, int *partition_type, char *keyattr, MOP **partitions)
#define ER_ALTER_CHANGE_TYPE_NEED_ROW_CHECK
Definition: error_code.h:1306
void parser_free_tree(PARSER_CONTEXT *parser, PT_NODE *tree)
PT_NODE * auth_cmd_list
Definition: parse_tree.h:2649
int do_add_methods(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *methods)
#define TP_INTEGER_PRECISION
#define SM_PROPERTY_PRIMARY_KEY
PT_DROP_INFO drop
Definition: parse_tree.h:3288
PT_NODE * user_list
Definition: parse_tree.h:2650
int xts_map_func_pred_to_stream(const FUNC_PRED *xasl_tree, char **xasl_stream, int *xasl_stream_size)
#define AU_ENABLE(save)
Definition: authenticate.h:113
const char * name
Definition: class_object.h:787
#define QSTR_IS_FIXED_LENGTH(s)
Definition: string_opfunc.h:50
int pt_attr_check_default_cs_coll(PARSER_CONTEXT *parser, PT_NODE *attr, int default_cs, int default_coll)
SM_FOREIGN_KEY_ACTION delete_action
Definition: class_object.h:481
char * sm_produce_constraint_name(const char *class_name, DB_CONSTRAINT_TYPE constraint_type, const char **att_names, const int *asc_desc, const char *given_name)
int do_drop_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_NODE * pt_resolve_names(PARSER_CONTEXT *parser, PT_NODE *statement, SEMANTIC_CHK_INFO *sc_info)
static int do_create_partition_constraint(PT_NODE *alter, SM_CLASS *root_class, SM_CLASS_CONSTRAINT *constraint, SM_PARTITION_ALTER_INFO *pinfo)
PT_NODE * user_list
Definition: parse_tree.h:2308
#define MSGCAT_SET_PARSER_SEMANTIC
void classobj_free_partition_info(SM_PARTITION *partition_info)
int er_errid_if_has_error(void)
#define ER_SM_ONLY_NORMAL_ATTRIBUTES
Definition: error_code.h:1252
static int do_alter_clause_drop_index(PARSER_CONTEXT *const parser, PT_NODE *const alter)
int do_add_attributes(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_NODE *atts, PT_NODE *constraints, DB_QUERY_TYPE *create_select_columns)
PT_MISC_TYPE update_action
Definition: parse_tree.h:3089
struct pt_constraint_info::@127::@130 unique
static int save_constraint_info_from_pt_node(SM_CONSTRAINT_INFO **save_info, const PT_NODE *const pt_constr)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static bool is_att_prop_set(const int prop, const int value)
#define IS_STRING(n)
#define strlen(s1)
Definition: intl_support.c:43
static int build_att_coll_change_map(TP_DOMAIN *curr_domain, TP_DOMAIN *req_domain, SM_ATTR_PROP_CHG *attr_chg_properties)
static const char * get_hard_default_for_type(PT_TYPE_ENUM type)
PT_RESOLUTION_INFO resolution
Definition: parse_tree.h:3329
char * parser_print_tree_with_quotes(PARSER_CONTEXT *parser, const PT_NODE *node)
DB_METHOD * db_get_class_method(DB_OBJECT *obj, const char *name)
Definition: db_info.c:1484
SM_COMPONENT header
Definition: class_object.h:441
DB_CONSTRAINT_TYPE db_constraint_type(const DB_CONSTRAINT *constraint)
Definition: db_info.c:1978
bool pt_is_function_index_expr(PARSER_CONTEXT *parser, PT_NODE *expr, bool report_error)
#define ER_SM_INVALID_INDEX_TYPE
Definition: error_code.h:341
#define ERROR2(error, code, arg1, arg2)
Definition: error_manager.h:64
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
PT_OP_TYPE
Definition: parse_tree.h:1320
PT_MISC_TYPE entity_type
Definition: parse_tree.h:1899
const char * ch_name
Definition: class_object.h:350
int dbt_drop_query_spec(DB_CTMPL *def, const int query_no)
Definition: db_temp.c:1221
#define ER_AUTO_INCREMENT_SINGLE_COL_AMBIGUITY
Definition: error_code.h:1317
struct pt_constraint_info::@127::@129 not_null
enum intl_codeset INTL_CODESET
Definition: intl_support.h:190
PT_NODE * function_name
Definition: parse_tree.h:2378
bool tr_set_execution_state(bool new_state)
int dbt_change_query_spec(DB_CTMPL *def, const char *new_query, const int query_no)
Definition: db_temp.c:1261
int sm_drop_index(MOP classop, const char *constraint_name)
PT_MISC_TYPE shared
Definition: parse_tree.h:2005
bool prm_get_bool_value(PARAM_ID prm_id)
PT_ALTER_USER_INFO alter_user
Definition: parse_tree.h:3270
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
MOP ws_find_class(const char *name)
Definition: work_space.c:2278
SM_CLASS_TYPE class_type
Definition: class_object.h:713
#define ER_ALTER_CHANGE_MULTIPLE_PK
Definition: error_code.h:1325
PRED_EXPR_WITH_CONTEXT * pt_to_pred_with_context(PARSER_CONTEXT *parser, PT_NODE *predicate, PT_NODE *spec)
#define ER_CREATE_AS_SELECT_NULL_TYPE
Definition: error_code.h:1264
SM_FUNCTION_INFO * func_index_info
PT_MISC_TYPE only_all
Definition: parse_tree.h:2145
void * db_ws_alloc(size_t size)
Definition: quick_fit.c:73
static int do_check_fk_constraints_internal(DB_CTMPL *ctemplate, PT_NODE *constraints, bool is_partitioned)
static PT_NODE * pt_replace_names_index_expr(PARSER_CONTEXT *parser, PT_NODE *node, void *void_arg, int *continue_walk)
PT_MISC_TYPE meta_class
Definition: parse_tree.h:2146
int sm_drop_constraint(MOP classop, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, bool class_attributes, bool mysql_index_name)
void er_clear(void)
int db_query_set_copy_tplvalue(DB_QUERY_RESULT *result, int copy)
Definition: db_query.c:3386
PT_NODE * method_def_list
Definition: parse_tree.h:1906
PT_NODE * password
Definition: parse_tree.h:1835
SM_CLASS * sm_get_class_with_statistics(MOP classop)
SM_PREDICATE_INFO * filter_predicate
int serial_decache(OID *oid)
#define ER_ALTER_CHANGE_PARTITIONS
Definition: error_code.h:1303
PT_NODE * method_file_list
Definition: parse_tree.h:1907
#define TP_FLOATING_PRECISION_VALUE
#define ER_ALTER_PARTITIONS_FK_NOT_ALLOWED
Definition: error_code.h:1379
static bool is_att_change_needed(const SM_ATTR_PROP_CHG *attr_chg_properties)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
static int do_run_update_query_for_new_default_expression_fields(PARSER_CONTEXT *parser, PT_NODE *alter, PT_NODE *attr_list, int attr_count, MOP class_mop)
static int adjust_partition_range(DB_OBJLIST *objs)
char * parser_print_tree(PARSER_CONTEXT *parser, const PT_NODE *node)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
static int do_recreate_renamed_class_indexes(const PARSER_CONTEXT *parser, const char *const old_class_name, const char *const class_name)
int dbt_rename(DB_CTMPL *def, const char *name, int class_namespace, const char *newname)
Definition: db_temp.c:967
DB_OBJLIST * users
Definition: class_object.h:712
int xts_map_filter_pred_to_stream(const PRED_EXPR_WITH_CONTEXT *pred, char **pred_stream, int *pred_stream_size)
int i
Definition: dynamic_load.c:954
PT_VALUE_INFO value
Definition: parse_tree.h:3358
int db_make_null(DB_VALUE *value)
#define AU_INDEX
Definition: authenticate.h:74
DB_TYPE id
#define SM_PROPERTY_FOREIGN_KEY
PT_NODE * list
Definition: parse_tree.h:2685
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define QUERY_MAX_SIZE
int do_update_maxvalue_of_auto_increment_serial(PARSER_CONTEXT *parser, MOP *serial_object, const char *class_name, PT_NODE *att)
struct tp_domain * next
Definition: object_domain.h:74
int do_is_partitioned_subclass(int *is_partitioned, const char *classname, char *keyattr)
struct pt_alter_info::@111::@114 ch_attr_def
static int do_coalesce_partition_pre(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
static int do_alter_change_col_comment(PARSER_CONTEXT *const parser, PT_NODE *const alter)
#define ER_NOT_ALLOWED_ACCESS_TO_PARTITION
Definition: error_code.h:1137
PT_NODE * sup_class_list
Definition: parse_tree.h:1755
PT_NODE * data_default
Definition: parse_tree.h:1859
DB_COLLECTION * set
Definition: dbtype_def.h:1063
#define pt_is_set_type(n)
Definition: parse_tree.h:267
#define ER_SM_INVALID_CONSTRAINT
Definition: error_code.h:871
struct pt_constraint_info::@127::@128 primary_key
const char * name
Definition: class_object.h:385
int sm_att_fk_constrained(MOP classop, const char *name)
PT_NODE * auth_cmd_list
Definition: parse_tree.h:2307
DB_OBJECT * db_add_user(const char *name, int *exists)
Definition: db_admin.c:1646
char * strdup(const char *str)
Definition: porting.c:901
void dbt_abort_class(DB_CTMPL *def)
Definition: db_temp.c:249
int db_get_error(const DB_VALUE *value)
SM_INDEX_STATUS index_status
Definition: class_object.h:544
PT_TRUNCATE_INFO truncate
Definition: parse_tree.h:3351
#define ER_PARTITION_WORK_FAILED
Definition: error_code.h:1109
#define DB_MAX_VARNCHAR_PRECISION
Definition: dbtype_def.h:546
int do_alter_index(PARSER_CONTEXT *parser, const PT_NODE *statement)
PT_MISC_TYPE attr_type
Definition: parse_tree.h:2643
PT_NODE * create_index
Definition: parse_tree.h:1826
int ws_list_length(DB_LIST *list)
Definition: work_space.c:3925
#define PT_INTERNAL_ERROR(parser, what)
Definition: parse_tree.h:112
static int do_promote_partition_by_name(const char *class_name, const char *part_num, char **partition_name)
#define TP_SMALLINT_PRECISION
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_make_int(DB_VALUE *value, const int num)
static int do_redistribute_partitions_data(const char *class_name, const char *keyname, char **promoted, int promoted_count, PT_ALTER_CODE alter_op, bool should_update, bool should_insert)
static int do_alter_index_rebuild(PARSER_CONTEXT *parser, const PT_NODE *statement)
int db_query_get_tuple_value(DB_QUERY_RESULT *result, int index, DB_VALUE *value)
Definition: db_query.c:2873
static const char * get_attr_name(PT_NODE *attribute)
struct db_object * class_mop
Definition: object_domain.h:81
int pt_coerce_value(PARSER_CONTEXT *parser, PT_NODE *src, PT_NODE *dest, PT_TYPE_ENUM desired_type, PT_NODE *elem_type_list)
#define pt_has_error(parser)
Definition: parser.h:507
int db_revoke(MOP user, MOP class_mop, AU_TYPE auth)
Definition: db_admin.c:1821
MOP sm_find_class(const char *name)
const char * alias_print
Definition: parse_tree.h:3455
int smt_find_attribute(SM_TEMPLATE *template_, const char *name, int class_attribute, SM_ATTRIBUTE **attp)
int dbt_add_method_file(DB_CTMPL *def, const char *name)
Definition: db_temp.c:1015
#define STATS_WITH_SAMPLING
Definition: statistics.h:35
PT_NODE * pt_domain_to_data_type(PARSER_CONTEXT *parser, DB_DOMAIN *domain)
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)
SM_CLASS_TYPE smt_get_class_type(SM_TEMPLATE *template_)
const char * resolved
Definition: parse_tree.h:2545
#define OID_ISNULL(oidp)
Definition: oid.h:81
#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
int smt_set_attribute_default(SM_TEMPLATE *template_, const char *name, int class_attribute, DB_VALUE *proposed_value, DB_DEFAULT_EXPR *default_expr)
int do_get_partition_keycol(char *keycol, MOP class_)
int p[NUM_ATT_CHG_PROP]
int sm_att_unique_constrained(MOP classop, const char *name)
#define LANG_SYS_CODESET
#define TP_DOMAIN_CODESET(dom)
int dbt_change_method_implementation(DB_CTMPL *def, const char *name, int class_method, const char *newname)
Definition: db_temp.c:845
#define PT_HAS_COLLATION(t)
Definition: parse_tree.h:243
static int do_remove_partition_pre(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
PT_CONSTRAINT_INFO constraint
Definition: parse_tree.h:3278
char * ws_copy_string(const char *str)
Definition: work_space.c:3457
static int do_alter_one_clause_with_template(PARSER_CONTEXT *parser, PT_NODE *alter)
static int do_alter_change_auto_increment(PARSER_CONTEXT *const parser, PT_NODE *const alter)
SM_RESOLUTION * class_resolutions
Definition: class_object.h:796
PT_REVOKE_INFO revoke
Definition: parse_tree.h:3330
static int do_alter_partitioning_post(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
#define INTL_CAN_COERCE_CS(cs_from, cs_to)
Definition: intl_support.h:97
int do_check_rows_for_null(MOP class_mop, const char *att_name, bool *has_nulls)
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
DB_VALUE * default_value
Definition: esql_cli.c:348
int column_number
Definition: parse_tree.h:3442
int pt_length_of_list(const PT_NODE *list)
struct parser_node::@132 flag
PT_NODE * entity_name
Definition: parse_tree.h:2130
int db_add_member(DB_OBJECT *user, DB_OBJECT *member)
Definition: db_admin.c:1694
static int do_alter_index_status(PARSER_CONTEXT *parser, const PT_NODE *statement)
int dbt_change_domain(DB_CTMPL *def, const char *name, int class_attribute, const char *domain)
Definition: db_temp.c:591
MOP do_get_serial_obj_id(DB_IDENTIFIER *serial_obj_id, DB_OBJECT *serial_class_mop, const char *serial_name)
const char * comment
Definition: class_object.h:758
static int do_create_partition(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
#define SM_PROPERTY_REVERSE_UNIQUE
PT_SELECT_INFO select
Definition: parse_tree.h:2781
DB_VALUE * pt_value_to_db(PARSER_CONTEXT *parser, PT_NODE *value)
Definition: parse_dbi.c:1088
#define UNIQUE_SAVEPOINT_REPLACE_VIEW
PT_DATA_DEFAULT_INFO data_default
Definition: parse_tree.h:3283
int db_compile_and_execute_local(const char *CSQL_query, void *result, DB_QUERY_ERROR *query_error)
Definition: db_vdb.c:3068
#define TP_DATE_AS_CHAR_LENGTH
int dbt_drop_method_file(DB_CTMPL *def, const char *name)
Definition: db_temp.c:1035
SM_NAME_SPACE name_space
static int create_or_drop_index_helper(PARSER_CONTEXT *parser, const char *const constraint_name, const bool is_reverse, const bool is_unique, PT_NODE *spec, PT_NODE *column_names, PT_NODE *column_prefix_length, PT_NODE *filter_predicate, int func_index_pos, int func_index_args_count, PT_NODE *function_expr, PT_NODE *comment, DB_OBJECT *const obj, SM_INDEX_STATUS index_status, DO_INDEX do_index)
#define SM_PROPERTY_NOT_NULL
struct pt_alter_info::@111::@116 partition
PT_INSERT_INFO insert
Definition: parse_tree.h:3309
union pt_constraint_info::@127 un
int do_recreate_func_index_constr(PARSER_CONTEXT *parser, SM_CONSTRAINT_INFO *constr, SM_FUNCTION_INFO *func_index_info, PT_NODE *alter, const char *src_cls_name, const char *new_cls_name)
int do_create_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
static int check_change_class_collation(PARSER_CONTEXT *parser, DB_CTMPL *ctemplate, PT_ALTER_INFO *alter, bool *need_update, int *collation_id)
PT_NODE * user_name
Definition: parse_tree.h:1834
int db_namelist_append(DB_NAMELIST **list, const char *name)
Definition: db_virt.c:108
DB_SESSION_ERROR * db_get_errors(DB_SESSION *session)
Definition: db_vdb.c:926
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)
static int do_promote_partition_list(PARSER_CONTEXT *parser, PT_NODE *alter, SM_PARTITION_ALTER_INFO *pinfo)
char keycol[DB_MAX_IDENTIFIER_LENGTH]
int dbt_drop_class_attribute(DB_CTMPL *def, const char *name)
Definition: db_temp.c:734
SM_INDEX_STATUS
Definition: class_object.h:510
#define PT_IS_NAME_NODE(n)
Definition: parse_tree.h:320
SM_ATTRIBUTE * attributes
Definition: class_object.h:790
static int do_alter_clause_add_index(PARSER_CONTEXT *const parser, PT_NODE *const alter)
int do_create_entity(PARSER_CONTEXT *parser, PT_NODE *node)
#define ER_OBJ_NOT_A_CLASS
Definition: error_code.h:288
#define TP_IS_CHAR_BIT_TYPE(typeid)
const char * comment
Definition: class_object.h:467
int db_drop_class_ex(MOP class_, bool is_cascade_constraints)
Definition: db_class.c:122
int do_alter_user(const PARSER_CONTEXT *parser, const PT_NODE *statement)
int au_set_user_comment(MOP user, const char *comment)
void tp_domain_free(TP_DOMAIN *dom)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
int db_statement_count(DB_SESSION *session)
Definition: db_vdb.c:132
int do_create_auto_increment_serial(PARSER_CONTEXT *parser, MOP *serial_object, const char *class_name, PT_NODE *att)
#define PT_ERRORmf(parser, node, setNo, msgNo, arg1)
Definition: parse_tree.h:64
PT_NODE * name
Definition: parse_tree.h:2028
static int do_rename_internal(const char *const old_name, const char *const new_name)
#define ER_IS_ABORTED_DUE_TO_DEADLOCK(err)
int db_add_constraint(MOP classmop, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, int class_attributes)
Definition: db_class.c:1777
PT_NODE * comment
Definition: parse_tree.h:1863
#define ER_ALTER_CHANGE_TYPE_UPGRADE_CFG
Definition: error_code.h:1308
DB_DEFAULT_EXPR_TYPE
Definition: dbtype_def.h:1181
PT_CREATE_USER_INFO create_user
Definition: parse_tree.h:3281
int do_drop_partition_list(MOP class_, PT_NODE *name_list, DB_CTMPL *tmpl)
PT_NODE * constraint_list
Definition: parse_tree.h:1825
int sm_rename_class(MOP op, const char *new_name)
#define ER_AU_MISSING_OR_INVALID_USER
Definition: error_code.h:230
int classobj_drop_prop(DB_SEQ *properties, const char *name)
Definition: class_object.c:394
static SM_FOREIGN_KEY_ACTION map_pt_to_sm_action(const PT_MISC_TYPE action)
int tde_algorithm
Definition: class_object.h:767
const char * name
Definition: class_object.h:532
#define UNIQUE_SAVEPOINT_ALTER_USER_ENTITY
int sm_delete_class_mop(MOP op, bool is_cascade_constraints)
int sm_update_class(SM_TEMPLATE *template_, MOP *classmop)
int db_find_user_to_drop(const char *name, DB_OBJECT **user)
Definition: db_admin.c:1626
SM_INDEX_STATUS index_status
unsigned int flags
Definition: class_object.h:762
PT_NODE * keycol
Definition: parse_tree.h:2020
int sm_set_class_flag(MOP classop, SM_CLASS_FLAG flag, int on_or_off)
#define DB_MAX_CHAR_PRECISION
Definition: dbtype_def.h:533
int ib_thread_count
DB_OBJLIST * db_get_subclasses(DB_OBJECT *obj)
Definition: db_info.c:659
EXECUTION_STATE_VALUES execution_values
Definition: parse_tree.h:3562
PT_NODE * pt_node_list(PARSER_CONTEXT *parser_ptr, PT_MISC_TYPE list_type, PT_NODE *list)
#define ER_ALTER_CHANGE_FK
Definition: error_code.h:1304
void sm_free_function_index_info(SM_FUNCTION_INFO *func_index_info)