CUBRID Engine  latest
schema_template.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  * schema_template.c - Schema manager templates
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <assert.h>
32 
33 #include "error_manager.h"
34 #include "object_representation.h"
35 #include "object_domain.h"
36 #include "work_space.h"
37 #include "object_primitive.h"
38 #include "class_object.h"
39 #include "schema_manager.h"
40 #include "set_object.h"
41 #include "locator_cl.h"
42 #include "authenticate.h"
43 #include "transform_cl.h"
44 #include "statistics.h"
45 #include "virtual_object.h"
46 #include "db.h"
47 #include "release_string.h"
48 #include "execute_schema.h"
49 #if defined(WINDOWS)
50 #include "misc_string.h"
51 #endif
52 
53 #include "dbtype.h"
54 
55 #define DOWNCASE_NAME(a, b) \
56  do { \
57  sm_downcase_name(a, b, SM_MAX_IDENTIFIER_LENGTH); \
58  ws_free_string(a); \
59  a = ws_copy_string(b); \
60  } while(0)
61 
62 static int find_method (SM_TEMPLATE * template_, const char *name, int class_method, SM_METHOD ** methodp);
63 static SM_COMPONENT *find_component (SM_TEMPLATE * template_, const char *name, int class_stuff);
64 static int find_any (SM_TEMPLATE * template_, const char *name, int class_stuff, SM_COMPONENT ** thing);
65 static int find_signature (SM_TEMPLATE * template_, const char *name, int class_method, const char *signame,
66  SM_METHOD ** methodp, SM_METHOD_SIGNATURE ** sigp);
67 static int find_argument (SM_TEMPLATE * template_, const char *name, int class_method, const char *signame, int index,
68  int create, SM_METHOD ** methodp, SM_METHOD_SIGNATURE ** sigp, SM_METHOD_ARGUMENT ** argp);
69 static int check_namespace (SM_TEMPLATE * temp, const char *name, const bool class_namespace);
70 static SM_RESOLUTION *find_alias (SM_RESOLUTION * reslist, const char *name, SM_NAME_SPACE name_space);
71 static int resolve_class_domain (SM_TEMPLATE * tmp, DB_DOMAIN * domain);
72 static int get_domain_internal (SM_TEMPLATE * tmp, const char *domain_string, DB_DOMAIN ** domainp, int check_internal);
73 static int get_domain (SM_TEMPLATE * tmp, const char *domain_string, DB_DOMAIN ** domain);
74 static int check_domain_class_type (SM_TEMPLATE * template_, DB_OBJECT * domain_classobj);
75 static SM_TEMPLATE *def_class_internal (const char *name, int class_type);
77  const char *constraint_name, SM_ATTRIBUTE ** atts, const int *asc_desc,
78  const int *attr_prefix_length, SM_FOREIGN_KEY_INFO * fk_info,
79  char *shared_cons_name, SM_PREDICATE_INFO * filter_index,
80  SM_FUNCTION_INFO * function_index, const char *comment,
81  SM_INDEX_STATUS index_status);
82 static int smt_set_attribute_orig_default_value (SM_ATTRIBUTE * att, DB_VALUE * new_orig_value,
83  DB_DEFAULT_EXPR * default_expr);
84 static int smt_drop_constraint_from_property (SM_TEMPLATE * template_, const char *constraint_name,
85  SM_ATTRIBUTE_FLAG constraint);
86 static int smt_check_foreign_key (SM_TEMPLATE * template_, const char *constraint_name, SM_ATTRIBUTE ** atts,
87  int n_atts, SM_FOREIGN_KEY_INFO * fk_info);
88 static int check_alias_delete (SM_TEMPLATE * template_, const char *name, SM_NAME_SPACE name_space, int error);
89 static int check_resolution_name (MOP classmop, const char *name, int class_name);
90 static int check_local_definition (SM_TEMPLATE * template_, const char *name, const char *alias,
91  SM_NAME_SPACE name_space);
92 static int add_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, const char *alias,
93  SM_NAME_SPACE name_space);
94 static int delete_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, SM_NAME_SPACE name_space);
95 static int smt_add_attribute_to_list (SM_ATTRIBUTE ** att_list, SM_ATTRIBUTE * att, const bool add_first,
96  const char *add_after_attribute);
97 static int smt_change_attribute (SM_TEMPLATE * template_, const char *name, const char *new_name,
98  const char *new_domain_string, DB_DOMAIN * new_domain, const SM_NAME_SPACE name_space,
99  const bool change_first, const char *change_after_attribute,
100  SM_ATTRIBUTE ** found_att);
101 static int smt_change_attribute_pos_in_list (SM_ATTRIBUTE ** att_list, SM_ATTRIBUTE * att, const bool change_first,
102  const char *change_after_attribute);
103 static int smt_change_class_shared_attribute_domain (SM_ATTRIBUTE * att, DB_DOMAIN * new_domain);
104 
105 
106 #if defined (ENABLE_RENAME_CONSTRAINT)
107 static int rename_constraint (SM_TEMPLATE * ctemplate, SM_CLASS_CONSTRAINT * sm_cons, const char *old_name,
108  const char *new_name, SM_CONSTRAINT_FAMILY element_type);
109 
110 static int rename_constraints_partitioned_class (SM_TEMPLATE * ctemplate, const char *old_name, const char *new_name,
111  SM_CONSTRAINT_FAMILY element_type);
112 #endif
113 
114 static int change_constraints_comment_partitioned_class (MOP obj, const char *index_name, const char *comment);
115 
116 static MOP smt_find_owner_of_constraint (SM_TEMPLATE * ctemplate, const char *constraint_name);
117 
118 static int change_constraints_status_partitioned_class (MOP obj, const char *index_name, SM_INDEX_STATUS index_status);
119 static SM_CLASS_CONSTRAINT *smt_find_constraint (SM_TEMPLATE * ctemplate, const char *constraint_name);
120 
121 /* TEMPLATE SEARCH FUNCTIONS */
122 /*
123  * These are used to walk over the template structures and extract information
124  * of interest, signaling errors if things don't look right. These will
125  * be called by the smt interface functions so we don't have to duplicate
126  * a lot of the error checking code in every function.
127 */
128 
129 /*
130  * smt_find_attribute() - Locate an instance, shared or class attribute
131  * in a template. Signal an error if not found.
132  * return: NO_ERROR on success, non-zero for ERROR
133  * template(in): schema template
134  * name(in): attribute name
135  * class_attribute(in): non-zero if looking for class attribute
136  * attp(out): returned pointer to attribute structure
137  */
138 
139 int
140 smt_find_attribute (SM_TEMPLATE * template_, const char *name, int class_attribute, SM_ATTRIBUTE ** attp)
141 {
142  int error = NO_ERROR;
143  SM_ATTRIBUTE *attr_list;
144 
145  *attp = NULL;
146 
147  if (!sm_check_name (name))
148  {
149  ASSERT_ERROR_AND_SET (error);
150  return error;
151  }
152 
153  attr_list = class_attribute ? template_->class_attributes : template_->attributes;
154 
155  *attp = (SM_ATTRIBUTE *) SM_FIND_NAME_IN_COMPONENT_LIST (attr_list, name);
156 
157  if (*attp != NULL)
158  {
159  // found local attr
160  return NO_ERROR;
161  }
162 
163  if (template_->current == NULL)
164  {
165  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, name);
166  return error;
167  }
168 
169  /* check for mistaken references to inherited attributes and give a better message */
170  *attp = classobj_find_attribute (template_->current, name, class_attribute);
171 
172  if (*attp != NULL)
173  {
174  // found inherited attr
175  ERROR2 (error, ER_SM_INHERITED_ATTRIBUTE, name, sm_get_ch_name ((*attp)->class_mop));
176  return error;
177  }
178  else
179  {
180  /* wasn't inherited, give the ususal message */
181  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, name);
182  return error;
183  }
184 }
185 
186 /*
187  * find_method() - Locate an instance or class method in a template.
188  * Signal an error if not found.
189  * return: NO_ERROR on success, non-zero for ERROR
190  * template(in): schema template
191  * name(in): method name
192  * class_method(in): non-zero if looking for a class method
193  * methodp(out): returned pointer to method structure
194  */
195 
196 static int
197 find_method (SM_TEMPLATE * template_, const char *name, int class_method, SM_METHOD ** methodp)
198 {
199  int error = NO_ERROR;
200  SM_METHOD *method_list;
201 
202  *methodp = NULL;
203 
204  if (!sm_check_name (name))
205  {
206  ASSERT_ERROR_AND_SET (error);
207  return error;
208  }
209 
210  method_list = (class_method ? template_->class_methods : template_->methods);
211 
212  *methodp = (SM_METHOD *) SM_FIND_NAME_IN_COMPONENT_LIST (method_list, name);
213 
214  if (*methodp != NULL)
215  {
216  return NO_ERROR;
217  }
218 
219  if (template_->current == NULL)
220  {
221  ERROR1 (error, ER_SM_METHOD_NOT_FOUND, name);
222  return error;
223  }
224 
225  /* check for mistaken references to inherited methods and give a better message */
226  *methodp = classobj_find_method (template_->current, name, class_method);
227 
228  if (*methodp != NULL)
229  {
230  /* inherited, indicate the source class */
231  ERROR2 (error, ER_SM_INHERITED_METHOD, name, sm_get_ch_name ((*methodp)->class_mop));
232  return error;
233  }
234  else
235  {
236  /* wasn't inherited, give the ususal message */
237  ERROR1 (error, ER_SM_METHOD_NOT_FOUND, name);
238  return error;
239  }
240 }
241 
242 /*
243  * find_component() - This function will search through the various lists in
244  * the template looking for a named component. No errors are signaled if the
245  * component isn't found. Used by find_any and a few others that need
246  * to do this kind of search.
247  * return: component pointer
248  * template(in): class template
249  * name(in): name of attribute or method
250  * class_stuff(in): non-zero if looking in the class name_space
251  */
252 
253 static SM_COMPONENT *
254 find_component (SM_TEMPLATE * template_, const char *name, int class_stuff)
255 {
256  SM_ATTRIBUTE *att, *attr_list;
257  SM_METHOD *method, *method_list;
258  SM_COMPONENT *comp;
259 
260  comp = NULL;
261 
262  /* check attributes */
263  attr_list = (class_stuff ? template_->class_attributes : template_->attributes);
264  att = (SM_ATTRIBUTE *) SM_FIND_NAME_IN_COMPONENT_LIST (attr_list, name);
265  if (att != NULL)
266  {
267  return (SM_COMPONENT *) att;
268  }
269 
270  /* couldn't find an attribute, look at the methods */
271  method_list = (class_stuff ? template_->class_methods : template_->methods);
272  method = (SM_METHOD *) SM_FIND_NAME_IN_COMPONENT_LIST (method_list, name);
273  if (method != NULL)
274  {
275  return (SM_COMPONENT *) method;
276  }
277 
278  return NULL;
279 }
280 
281 /*
282  * find_any() - This is used by smt_delete_any to locate any kind of attribute or
283  * method by name and give an appropriate error messages if not found.
284  * This is pretty much a concatentation of find_attribute and find_method
285  * except that error messages are smarter.
286  * return: NO_ERROR on success, non-zero for ERROR
287  * template(in): class definition template
288  * name(in): name of attribute or method
289  * class_stuff(in): non-zero if looking in the class name_space
290  * thing(out): pointer for matching attribute or method (set on return)
291  */
292 
293 static int
294 find_any (SM_TEMPLATE * template_, const char *name, int class_stuff, SM_COMPONENT ** thing)
295 {
296  int error = NO_ERROR;
297  SM_ATTRIBUTE *att;
298  SM_METHOD *method;
299  SM_COMPONENT *comp;
300 
301  *thing = NULL;
302 
303  if (!sm_check_name (name))
304  {
305  ASSERT_ERROR_AND_SET (error);
306  return error;
307  }
308 
309  comp = find_component (template_, name, class_stuff);
310  if (comp != NULL)
311  {
312  *thing = comp;
313  return NO_ERROR;
314  }
315 
316  /* couldn't find anything, must signal an error */
317  if (template_->current == NULL)
318  {
319  ERROR1 (error, ER_SM_ATTMETH_NOT_FOUND, name);
320  return error;
321  }
322 
323  /* check inherited attributes for better message */
324  att = classobj_find_attribute (template_->current, name, class_stuff);
325  if (att != NULL)
326  {
327  /* inherited, indicate the source class */
329  return error;
330  }
331 
332  /* check inherited methods */
333  method = classobj_find_method (template_->current, name, class_stuff);
334  if (method != NULL)
335  {
336  /* inherited, indicate the source class */
337  ERROR2 (error, ER_SM_INHERITED_METHOD, name, sm_get_ch_name (method->class_mop));
338  return error;
339  }
340  else
341  {
342  /* couldn't find any mistaken references to inherited things, give the usual message */
343  ERROR1 (error, ER_SM_ATTMETH_NOT_FOUND, name);
344  return error;
345  }
346 }
347 
348 /*
349  * find_signature() - Locate the method signature for a particular method
350  * implementation function.
351  * A signature is identified by the name of the C function that
352  * implements the method.
353  * Remember that the function name stored in the template has
354  * an undersore prefix added (for the dynamic loader) so we need to
355  * ignore that in the search.
356  * If the signature name passed in is NULL, we must perform the
357  * search using the default "classname_methodname" format.
358  * NOTE: Multiple signatures for methods is not currently supported
359  * throughout the system so there will always be only a single
360  * method signature. Support for multiple signatures in the
361  * schema manager was left in for future expansion.
362  * Since we don't actually support multiple signatures, right now
363  * we ignore the signame parameter and always return the first
364  * (and only) signature in the list.
365  * return: NO_ERROR on success, non-zero for ERROR
366  * template(in): schema template
367  * name(in): method name
368  * class_method(in): non-zero if looking for class methods
369  * signame(in): method function name (signature name)
370  * methodp(out): returned pointer to method structure
371  * sigp(out): returned pointer to signature structure
372  */
373 
374 static int
375 find_signature (SM_TEMPLATE * template_, const char *name, int class_method, const char *signame, SM_METHOD ** methodp,
376  SM_METHOD_SIGNATURE ** sigp)
377 {
378  int error = NO_ERROR;
379  SM_METHOD *method;
380  SM_METHOD_SIGNATURE *sig;
381 
382  error = find_method (template_, name, class_method, &method);
383  if (error == NO_ERROR)
384  {
385  /* punt, can only have one signature so first one wins need to do a "real" search here if we ever support
386  * multiple signatures */
387  sig = method->signatures;
388 
389  if (sig == NULL)
390  {
391  ERROR2 (error, ER_SM_SIGNATURE_NOT_FOUND, name, signame);
392  }
393  else
394  {
395  *methodp = method;
396  *sigp = sig;
397  }
398  }
399 
400  return error;
401 }
402 
403 /*
404  * find_argument() - Locate a method argument structure for a method
405  * in a template. See the discussion of signatures in find_signature.
406  * If the create flag is set, the argument will be created if it doesn't
407  * already exist.
408  * return: NO_ERROR on success, non-zero for ERROR
409  * template(in): schema template
410  * name(in): method name
411  * class_method(in): non-zero if looking for class methods
412  * signame(in): method function name (signature name, can be NULL)
413  * index(in): argument index
414  * create(in): non-zero to create argument if not found
415  * methodp(out): returned pointer to method structure
416  * sigp(out): returned pointer to signature structure
417  * argp(out): returned pointer to argument structrue
418  */
419 
420 static int
421 find_argument (SM_TEMPLATE * template_, const char *name, int class_method, const char *signame, int index, int create,
422  SM_METHOD ** methodp, SM_METHOD_SIGNATURE ** sigp, SM_METHOD_ARGUMENT ** argp)
423 {
424  int error = NO_ERROR;
425  SM_METHOD_SIGNATURE *sig;
426  SM_METHOD_ARGUMENT *arg;
427 
428  error = find_signature (template_, name, class_method, signame, methodp, &sig);
429  if (error == NO_ERROR)
430  {
431  if (index)
432  {
433  arg = classobj_find_method_arg (&sig->args, index, create);
434  if (arg == NULL && create)
435  {
436  assert (er_errid () != NO_ERROR);
437  error = er_errid (); /* memory allocation error */
438  }
439  else
440  {
441  /* keep track of the highest argument index */
442  if (create && (index > sig->num_args))
443  {
444  sig->num_args = index;
445  }
446  }
447  }
448  else
449  {
450  arg = sig->value;
451  if (arg == NULL && create)
452  {
453  arg = classobj_make_method_arg (0);
454  sig->value = arg;
455  }
456  }
457  if (arg == NULL)
458  {
459  if (!error)
460  {
461  ERROR2 (error, ER_SM_METHOD_ARG_NOT_FOUND, name, index);
462  }
463  }
464  else
465  {
466  *sigp = sig;
467  *argp = arg;
468  }
469  }
470 
471  return error;
472 }
473 
474 /*
475  * check_namespace() - This is called when any kind of attribute or method is
476  * being added to a template. We check to see if there is already a component
477  * with that name and signal an appropriate error.
478  * return: NO_ERROR on success, non-zero for ERROR
479  * temp(in): schema template
480  * name(in): attribute or method name
481  * class_namespace(in): true if looking in the class name_space
482  */
483 
484 static int
485 check_namespace (SM_TEMPLATE * temp, const char *name, const bool class_namespace)
486 {
487  int error = NO_ERROR;
488 
489  if (class_namespace)
490  {
492  {
493  ERROR1 (error, ER_SM_NAME_RESERVED_BY_ATT, name);
494  }
495  else if (SM_FIND_NAME_IN_COMPONENT_LIST (temp->class_methods, name) != NULL)
496  {
497  ERROR1 (error, ER_SM_NAME_RESERVED_BY_METHOD, name);
498  }
499  }
500  else
501  {
502  if (SM_FIND_NAME_IN_COMPONENT_LIST (temp->attributes, name) != NULL)
503  {
504  ERROR1 (error, ER_SM_NAME_RESERVED_BY_ATT, name);
505  }
506  else if (SM_FIND_NAME_IN_COMPONENT_LIST (temp->methods, name) != NULL)
507  {
508  ERROR1 (error, ER_SM_NAME_RESERVED_BY_METHOD, name);
509  }
510  }
511 
512  return error;
513 }
514 
515 /*
516  * find_alias() - Searches a resolution list for an alias resolution where the
517  * alias name matches the supplied name.
518  * return: resolution structure
519  * reslist(in): list of resolutions
520  * name(in): component name
521  * name_space(in): name_space identifier (class or instance)
522  */
523 
524 static SM_RESOLUTION *
525 find_alias (SM_RESOLUTION * reslist, const char *name, SM_NAME_SPACE name_space)
526 {
527  SM_RESOLUTION *res, *found;
528 
529  for (res = reslist, found = NULL; res != NULL && found == NULL; res = res->next)
530  {
531  if (name_space == res->name_space && res->alias != NULL && (SM_COMPARE_NAMES (res->alias, name) == 0))
532  {
533  found = res;
534  }
535  }
536 
537  return found;
538 }
539 
540 /* DOMAIN DECODING */
541 /*
542  * resolve_class_domain()
543  * get_domain_internal()
544  * get_domain() - Maps a domain string into a domain structure.
545  */
546 
547 static int
549 {
550  int error = NO_ERROR;
551  DB_DOMAIN *tmp_domain;
552 
553  if (domain)
554  {
555  switch (TP_DOMAIN_TYPE (domain))
556  {
557  case DB_TYPE_SET:
558  case DB_TYPE_MULTISET:
559  case DB_TYPE_SEQUENCE:
560  tmp_domain = domain->setdomain;
561  while (tmp_domain)
562  {
563  error = resolve_class_domain (tmp, tmp_domain);
564  if (error != NO_ERROR)
565  {
566  return error;
567  }
568  tmp_domain = tmp_domain->next;
569  }
570  break;
571 
572  case DB_TYPE_OBJECT:
573  if (domain->self_ref)
574  {
575  domain->type = tp_Type_null;
576  /* kludge, store the template as the "class" for this special domain */
577  domain->class_mop = (MOP) tmp;
578  }
579  break;
580 
581  default:
582  break;
583  }
584  }
585 
586  return error;
587 }
588 
589 static int
590 get_domain_internal (SM_TEMPLATE * tmp, const char *domain_string, DB_DOMAIN ** domainp, int check_internal)
591 {
592  int error = NO_ERROR;
593  DB_DOMAIN *domain = (DB_DOMAIN *) 0;
594  PR_TYPE *type;
595 
596  /* If the domain is already determined, use it */
597  if (*domainp)
598  {
599  domain = *domainp;
600  }
601  else
602  {
603  if (domain_string == NULL)
604  {
606  }
607  else
608  {
609  if (domain_string[0] == '*')
610  {
611  if (check_internal)
612  {
613  ERROR1 (error, ER_SM_DOMAIN_NOT_A_CLASS, domain_string);
614  }
615  else
616  {
617  type = pr_find_type (domain_string);
618  if (type)
619  {
620  domain = tp_domain_construct (type->id, NULL, 0, 0, NULL);
621  }
622  }
623  }
624  else
625  {
626  domain = pt_string_to_db_domain (domain_string, tmp->name);
627  }
628  }
629  }
630 
631  if (domain != NULL)
632  {
633  error = resolve_class_domain (tmp, domain);
634  if (error != NO_ERROR)
635  {
636  domain = NULL;
637  }
638  }
639  else
640  {
641  assert (er_errid () != NO_ERROR);
642  error = er_errid ();
643  }
644 
645  *domainp = domain;
646 
647  return error;
648 }
649 
650 static int
651 get_domain (SM_TEMPLATE * tmp, const char *domain_string, DB_DOMAIN ** domain)
652 {
653  return (get_domain_internal (tmp, domain_string, domain, false));
654 }
655 
656 /*
657  * check_domain_class_type() - see if a class is of the appropriate type for
658  * an attribute. Classes can only have attributes of class domains and
659  * virtual classes can have attributes of both class and vclass domains.
660  * return: NO_ERROR on success, non-zero for ERROR
661  * template(in): class template
662  * domain_classobj(in): class to examine
663  */
664 
665 static int
666 check_domain_class_type (SM_TEMPLATE * template_, DB_OBJECT * domain_classobj)
667 {
668  int error = NO_ERROR;
669  SM_CLASS *class_;
670 
671  /* If its a class, the domain can only be "object" or another class */
672  if (template_->class_type == SM_CLASS_CT)
673  {
674  if (domain_classobj != NULL && !(error = au_fetch_class_force (domain_classobj, &class_, AU_FETCH_READ))
675  && template_->class_type != class_->class_type)
676  {
678  }
679  }
680 
681  return error;
682 }
683 
684 /* SCHEMA TEMPLATE CREATION */
685 
686 /*
687  * def_class_internal() - Begins the definition of a new class.
688  * An empty template is created and returned. The class name
689  * is not registed with the server at this time, that is deferred
690  * until the template is applied with sm_update_class.
691  * return: schema template
692  * name(in): new class name
693  * class_type(in): type of class
694  */
695 
696 static SM_TEMPLATE *
697 def_class_internal (const char *name, int class_type)
698 {
699  char realname[SM_MAX_IDENTIFIER_LENGTH];
700  SM_TEMPLATE *template_ = NULL;
701  PR_TYPE *type;
702 
703  if (sm_check_name (name))
704  {
705  type = pr_find_type (name);
706  if (type != NULL)
707  {
709  }
710  else
711  {
712  sm_downcase_name (name, realname, SM_MAX_IDENTIFIER_LENGTH);
713  name = realname;
714  template_ = classobj_make_template (name, NULL, NULL);
715  if (template_ != NULL)
716  {
717  template_->class_type = (SM_CLASS_TYPE) class_type;
718  }
719  }
720  }
721 
722  return template_;
723 }
724 
725 /*
726  * smt_def_class() - Begins the definition of a normal class.
727  * See description of def_class_internal.
728  * return: template
729  * name(in): class name
730  */
731 
732 SM_TEMPLATE *
733 smt_def_class (const char *name)
734 {
735  return (def_class_internal (name, SM_CLASS_CT));
736 }
737 
738 /*
739  * smt_edit_class_mop() - Begins the editing of an existing class.
740  * A template is created and populated with the current definition
741  * of a class.
742  * This will get a write lock on the class as well.
743  * At this time we could also get write locks on the subclasses but
744  * if we defer this until sm_update_class, we can be smarter about
745  * getting locks only on the affected subclasses.
746  * return: schema template
747  * op(in): class MOP
748  */
749 
750 SM_TEMPLATE *
751 smt_edit_class_mop (MOP op, DB_AUTH db_auth_type)
752 {
753  SM_TEMPLATE *template_;
754  SM_CLASS *class_;
755  int is_class = 0;
756 
757  template_ = NULL;
758 
759  /* op should be a class */
760  is_class = locator_is_class (op, DB_FETCH_WRITE);
761  if (is_class < 0)
762  {
763  return NULL;
764  }
765  if (!is_class)
766  {
768  }
769  else
770  {
771  if (au_fetch_class (op, &class_, AU_FETCH_WRITE, db_auth_type) == NO_ERROR)
772  {
773  /* cleanup the class and flush out the run-time information prior to editing */
774  if (sm_clean_class (op, class_) == NO_ERROR)
775  {
776  template_ = classobj_make_template (sm_get_ch_name (op), op, class_);
777  }
778  }
779  }
780 
781  return template_;
782 }
783 
784 #if defined(ENABLE_UNUSED_FUNCTION)
785 /*
786  * smt_edit_class() - Begins the editing of an existing class.
787  * Behaves like smt_edit_class_mop except that the class is identified
788  * by name rather than with a MOP.
789  * return: schema template
790  * name(in): class name
791  */
792 
793 SM_TEMPLATE *
794 smt_edit_class (const char *name)
795 {
796  SM_TEMPLATE *template_;
797  MOP op;
798 
799  template_ = NULL;
800  if (sm_check_name (name))
801  {
802  op = sm_find_class ((char *) name);
803  if (op != NULL)
804  {
805  template_ = smt_edit_class_mop (op);
806  }
807  }
808 
809  return template_;
810 }
811 #endif /* ENABLE_UNUSED_FUNCTION */
812 
813 /*
814  * smt_copy_class_mop() - Duplicates an existing class for CREATE LIKE.
815  * A template is created and populated with a copy of the current definition
816  * of the given class.
817  * return: schema template
818  * op(in): class MOP of the class to duplicate
819  * class_(out): the current definition of the duplicated class is returned
820  * in order to be used for subsequent operations (such as
821  * duplicating indexes).
822  */
823 
824 SM_TEMPLATE *
825 smt_copy_class_mop (const char *name, MOP op, SM_CLASS ** class_)
826 {
827  SM_TEMPLATE *template_ = NULL;
828  int is_class = 0;
829 
830  assert (*class_ == NULL);
831 
832  /* op should be a class */
833  is_class = locator_is_class (op, DB_FETCH_READ);
834  if (is_class < 0)
835  {
836  return NULL;
837  }
838  if (!is_class)
839  {
841  return NULL;
842  }
843 
844  if (au_fetch_class (op, class_, AU_FETCH_READ, DB_AUTH_SELECT) == NO_ERROR)
845  {
846  if ((*class_)->class_type != SM_CLASS_CT)
847  {
849  return NULL;
850  }
851 
852  template_ = classobj_make_template_like (name, *class_);
853  }
854 
855  return template_;
856 }
857 
858 /*
859  * smt_copy_class() - Duplicates an existing class for CREATE LIKE.
860  * Behaves like smt_copy_class_mop except that the class is identified
861  * by name rather than with a MOP.
862  * return: schema template
863  * new_name(in): name of the class to be created
864  * existing_name(in): name of the class to be duplicated
865  * class_(out): the current definition of the duplicated class is returned
866  * in order to be used for subsequent operations (such as
867  * duplicating indexes).
868  */
869 
870 SM_TEMPLATE *
871 smt_copy_class (const char *new_name, const char *existing_name, SM_CLASS ** class_)
872 {
873  SM_TEMPLATE *template_ = NULL;
874 
875  if (sm_check_name (existing_name) != 0)
876  {
877  MOP op = sm_find_class (existing_name);
878  if (op != NULL)
879  {
880  template_ = smt_copy_class_mop (new_name, op, class_);
881  }
882  }
883 
884  return template_;
885 }
886 
887 /*
888  * smt_quit() - This is called to abort the creation of a schema template.
889  * If a template cannot be applied due to errors, you must either
890  * fix the template and re-apply it or use smt_quit to throw
891  * away the template and release the storage that has been allocated.
892  * return: NO_ERROR on success, non-zero for ERROR (always NO_ERROR)
893  * template(in): schema template to destroy
894  */
895 
896 int
897 smt_quit (SM_TEMPLATE * template_)
898 {
899  int error = NO_ERROR;
900 
901  if (template_ != NULL)
902  {
903  classobj_free_template (template_);
904  }
905 
906  return error;
907 }
908 
909 /* TEMPLATE ATTRIBUTE FUNCTIONS */
910 /*
911  * smt_add_attribute_w_dflt_w_order()
912  * return: NO_ERROR on success, non-zero for ERROR
913  * def(in/out):
914  * name(in): attribute name
915  * domain_string(in): domain name string
916  * domain(in): domain
917  * default_value(in):
918  * name_space(in): attribute name_space (class, instance, or shared)
919  * add_first(in): the attribute should be added at the beginning of the attributes list
920  * add_after_attribute(in): the attribute should be added in the attributes
921  * list after the attribute with the given name
922  * default_expr(in): default expression
923  * on_update(in): on_update default expression
924  * comment(in): attribute comment
925  */
926 int
927 smt_add_attribute_w_dflt_w_order (DB_CTMPL * def, const char *name, const char *domain_string, DB_DOMAIN * domain,
928  DB_VALUE * default_value, const SM_NAME_SPACE name_space, const bool add_first,
929  const char *add_after_attribute, DB_DEFAULT_EXPR * default_expr,
930  DB_DEFAULT_EXPR_TYPE * on_update, const char *comment)
931 {
932  int error = NO_ERROR;
933  int is_class_attr;
934 
935  is_class_attr = (name_space == ID_CLASS_ATTRIBUTE);
936 
937  error = smt_add_attribute_any (def, name, domain_string, domain, name_space, add_first, add_after_attribute, comment);
938  if (error != NO_ERROR)
939  {
940  return error;
941  }
942 
943  if (default_value != NULL)
944  {
945  error = smt_set_attribute_default (def, name, is_class_attr, default_value, default_expr);
946  if (error != NO_ERROR)
947  {
948  return error;
949  }
950  }
951 
952  if (on_update != NULL)
953  {
954  error = smt_set_attribute_on_update (def, name, is_class_attr, *on_update);
955  }
956 
957  return error;
958 }
959 
960 /*
961  * smt_add_attribute_w_dflt()
962  * return: NO_ERROR on success, non-zero for ERROR
963  * def(in/out):
964  * name(in): attribute name
965  * domain_string(in): domain name string
966  * domain(in): domain
967  * default_value(in):
968  * name_space(in): attribute name_space (class, instance, or shared)
969  * default_expr(in): default expression
970  * on_update(in): on_update default expression
971  * comment(in): attribute comment
972  */
973 int
974 smt_add_attribute_w_dflt (DB_CTMPL * def, const char *name, const char *domain_string, DB_DOMAIN * domain,
975  DB_VALUE * default_value, const SM_NAME_SPACE name_space, DB_DEFAULT_EXPR * default_expr,
976  DB_DEFAULT_EXPR_TYPE * on_update, const char *comment)
977 {
978  return smt_add_attribute_w_dflt_w_order (def, name, domain_string, domain, default_value, name_space, false, NULL,
979  default_expr, on_update, comment);
980 }
981 
982 /*
983  * smt_add_attribute_any() - Adds an attribute to a template.
984  * Handles instance, class, or shared attributes as defined by
985  * the "name_space" argument. The other name_space specific attribute
986  * functions all call this to do the work.
987  * The domain may be specified either with a string or a DB_DOMAIN *.
988  * If domain is not NULL, it is used. Otherwise domain_string is used.
989  * return: NO_ERROR on success, non-zero for ERROR
990  * template(in/out): schema template
991  * name(in): attribute name
992  * domain_string(in): domain name string
993  * domain(in): domain
994  * namespace(in): attribute name_space (class, instance, or shared)
995  * add_first(in): the attribute should be added at the beginning of the
996  * attributes list
997  * add_after_attribute(in): the attribute should be added in the attributes
998  * list after the attribute with the given name
999  */
1000 
1001 int
1002 smt_add_attribute_any (SM_TEMPLATE * template_, const char *name, const char *domain_string, DB_DOMAIN * domain,
1003  const SM_NAME_SPACE name_space, const bool add_first, const char *add_after_attribute,
1004  const char *comment)
1005 {
1006  int error_code = NO_ERROR;
1007  SM_ATTRIBUTE *att = NULL;
1008  SM_ATTRIBUTE **att_list = NULL;
1009  bool class_namespace = false;
1010  char real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
1011  char add_after_attribute_real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
1012 
1013  assert (template_ != NULL);
1014 
1015  switch (name_space)
1016  {
1017  case ID_INSTANCE:
1018  case ID_ATTRIBUTE:
1019  case ID_SHARED_ATTRIBUTE:
1020  att_list = &template_->attributes;
1021  class_namespace = false;
1022  break;
1023 
1024  case ID_CLASS:
1025  case ID_CLASS_ATTRIBUTE:
1026  att_list = &template_->class_attributes;
1027  class_namespace = true;
1028  break;
1029 
1030  default:
1031  ERROR0 (error_code, ER_SM_INVALID_ARGUMENTS);
1032  goto error_exit;
1033  }
1034 
1035  if (!sm_check_name (name))
1036  {
1037  assert (er_errid () != NO_ERROR);
1038  error_code = er_errid ();
1039  goto error_exit;
1040  }
1041 
1042  sm_downcase_name (name, real_name, SM_MAX_IDENTIFIER_LENGTH);
1043  name = real_name;
1044 
1045  if (add_after_attribute != NULL)
1046  {
1047  sm_downcase_name (add_after_attribute, add_after_attribute_real_name, SM_MAX_IDENTIFIER_LENGTH);
1048  add_after_attribute = add_after_attribute_real_name;
1049  }
1050 
1051  error_code = check_namespace (template_, name, class_namespace);
1052  if (error_code != NO_ERROR)
1053  {
1054  goto error_exit;
1055  }
1056 
1057  error_code = get_domain (template_, domain_string, &domain);
1058  if (error_code != NO_ERROR)
1059  {
1060  goto error_exit;
1061  }
1062 
1063  if (domain == NULL)
1064  {
1065  ERROR0 (error_code, ER_SM_INVALID_ARGUMENTS);
1066  goto error_exit;
1067  }
1068 
1069  if (TP_DOMAIN_TYPE (domain) == DB_TYPE_OBJECT)
1070  {
1071  error_code = check_domain_class_type (template_, domain->class_mop);
1072  if (error_code != NO_ERROR)
1073  {
1074  goto error_exit;
1075  }
1076  }
1077 
1078  att = classobj_make_attribute (name, domain->type, name_space);
1079  if (att == NULL)
1080  {
1081  assert (er_errid () != NO_ERROR);
1082  error_code = er_errid ();
1083  goto error_exit;
1084  }
1085  att->comment = ws_copy_string (comment);
1086 
1087  /* Flag this attribute as new so that we can initialize the original_value properly. Make sure this isn't saved on
1088  * disk ! */
1089  att->flags |= SM_ATTFLAG_NEW;
1090  att->class_mop = template_->op;
1091  att->domain = domain;
1092  att->auto_increment = NULL;
1093 
1094  error_code = smt_add_attribute_to_list (att_list, att, add_first, add_after_attribute);
1095  if (error_code != NO_ERROR)
1096  {
1097  goto error_exit;
1098  }
1099 
1100  return error_code;
1101 
1102 error_exit:
1103  if (att != NULL)
1104  {
1106  att = NULL;
1107  }
1108  return error_code;
1109 }
1110 
1111 /*
1112  * smt_add_attribute_to_list()
1113  * return: NO_ERROR on success, non-zero for ERROR
1114  * att_list(in/out): the list to add to
1115  * att(in): the attribute to add
1116  * add_first(in): the attribute should be added at the beginning of the
1117  * attributes list
1118  * add_after_attribute(in): the attribute should be added in the attributes
1119  * list after the attribute with the given name
1120  */
1121 
1122 static int
1123 smt_add_attribute_to_list (SM_ATTRIBUTE ** att_list, SM_ATTRIBUTE * att, const bool add_first,
1124  const char *add_after_attribute)
1125 {
1126  int error_code = NO_ERROR;
1127  SM_ATTRIBUTE *crt_att = NULL;
1128 
1129  assert (att->header.next == NULL);
1130  assert (att_list != NULL);
1131 
1132  if (add_first)
1133  {
1134  assert (add_after_attribute == NULL);
1135  *att_list = (SM_ATTRIBUTE *) WS_LIST_NCONC (att, *att_list);
1136  goto end;
1137  }
1138 
1139  if (add_after_attribute == NULL)
1140  {
1141  WS_LIST_APPEND (att_list, att);
1142  goto end;
1143  }
1144 
1145  for (crt_att = *att_list; crt_att != NULL; crt_att = (SM_ATTRIBUTE *) crt_att->header.next)
1146  {
1147  if (intl_identifier_casecmp (crt_att->header.name, add_after_attribute) == 0)
1148  {
1149  break;
1150  }
1151  }
1152  if (crt_att == NULL)
1153  {
1154  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_COLNAME, 1, add_after_attribute);
1155  error_code = ER_QPROC_INVALID_COLNAME;
1156  goto error_exit;
1157  }
1158  att->header.next = crt_att->header.next;
1159  crt_att->header.next = (SM_COMPONENT *) (att);
1160 
1161 end:
1162  return error_code;
1163 
1164 error_exit:
1165  return error_code;
1166 }
1167 
1168 /*
1169  * smt_add_attribute() - Adds an instance attribute to a class
1170  * return: NO_ERROR on success, non-zero for ERROR
1171  * template(in/out): schema template
1172  * name(in): attribute name
1173  * domain_string(in): domain name string
1174  * domain(in): domain structure
1175  */
1176 /*
1177  * TODO Replace calls to this function with calls to smt_add_attribute_any ()
1178  * and remove this function.
1179  */
1180 int
1181 smt_add_attribute (SM_TEMPLATE * template_, const char *name, const char *domain_string, DB_DOMAIN * domain)
1182 {
1183  return (smt_add_attribute_any (template_, name, domain_string, domain, ID_ATTRIBUTE, false, NULL, NULL));
1184 }
1185 
1186 /*
1187  * smt_add_set_attribute_domain() - Adds a domain to an attribute whose
1188  * basic type is one of the set types.
1189  * return: NO_ERROR on success, non-zero for ERROR
1190  * template(in/out): schema template
1191  * name(in): attribute name
1192  * class_attribute(in): non-zero if using class name_space
1193  * domain_string(in): domain name string
1194  * domain(in): domain structure
1195  */
1196 
1197 int
1198 smt_add_set_attribute_domain (SM_TEMPLATE * template_, const char *name, int class_attribute, const char *domain_string,
1199  DB_DOMAIN * domain)
1200 {
1201  int error = NO_ERROR;
1202  SM_ATTRIBUTE *att;
1203  TP_DOMAIN *newdomain;
1204 
1205  error = smt_find_attribute (template_, name, class_attribute, &att);
1206  if (error != NO_ERROR)
1207  {
1208  return error;
1209  }
1210 
1211  if ((att->domain == NULL) || !pr_is_set_type (TP_DOMAIN_TYPE (att->domain)))
1212  {
1213  ERROR1 (error, ER_SM_DOMAIN_NOT_A_SET, name);
1214  }
1215  else
1216  {
1217  error = get_domain (template_, domain_string, &domain);
1218  if (error == NO_ERROR && domain != NULL)
1219  {
1220  if (pr_is_set_type (TP_DOMAIN_TYPE (domain)))
1221  {
1222  ERROR1 (error, ER_SM_NO_NESTED_SETS, name);
1223  }
1224  else
1225  {
1226  /* We need to make sure that we don't update a cached domain since we may not be the only one pointing to
1227  * it. If the domain is cached, make a copy of it, update it, then cache it. */
1228  if (att->domain->is_cached)
1229  {
1230  newdomain = tp_domain_copy (att->domain, false);
1231  if (newdomain)
1232  {
1233  error = tp_domain_add (&newdomain->setdomain, domain);
1234  if (error != NO_ERROR)
1235  {
1236  tp_domain_free (newdomain);
1237  }
1238  else
1239  {
1240  newdomain = tp_domain_cache (newdomain);
1241  att->domain = newdomain;
1242  }
1243  }
1244  else
1245  {
1246  assert (er_errid () != NO_ERROR);
1247  error = er_errid ();
1248  }
1249  }
1250  else
1251  {
1252  error = tp_domain_add (&att->domain->setdomain, domain);
1253  }
1254  }
1255  }
1256  }
1257 
1258  return error;
1259 }
1260 
1261 /*
1262  * smt_delete_set_attribute_domain() - Remove a domain entry from the domain
1263  * list of an attribute whose basic type is one of the set types.
1264  * return: NO_ERROR on success, non-zero for ERROR
1265  * template(in/out): schema template
1266  * name(in): attribute name
1267  * class_attribute(in): non-zero if looking at class attriutes
1268  * domain_string(in): domain name string
1269  * domain(in): domain structure
1270  */
1271 
1272 int
1273 smt_delete_set_attribute_domain (SM_TEMPLATE * template_, const char *name, int class_attribute,
1274  const char *domain_string, DB_DOMAIN * domain)
1275 {
1276  int error = NO_ERROR;
1277  SM_ATTRIBUTE *att;
1278 
1279  error = smt_find_attribute (template_, name, class_attribute, &att);
1280  if (error == NO_ERROR)
1281  {
1282  if ((att->domain == NULL) || !pr_is_set_type (TP_DOMAIN_TYPE (att->domain)))
1283  {
1284  ERROR1 (error, ER_SM_DOMAIN_NOT_A_SET, name);
1285  }
1286  else
1287  {
1288  error = get_domain (template_, domain_string, &domain);
1289  if (error == NO_ERROR)
1290  {
1291  assert (domain != NULL);
1292  if (domain == NULL || !tp_domain_drop (&att->domain->setdomain, domain))
1293  {
1294  ERROR2 (error, ER_SM_DOMAIN_NOT_FOUND, name, (domain_string ? domain_string : "unknown"));
1295  }
1296  }
1297  }
1298  }
1299 
1300  return error;
1301 }
1302 
1303 /*
1304  * smt_set_attribute_default() - Assigns the default value for an attribute.
1305  * If this is a shared or class attribute, it sets the current value
1306  * since these only have one value.
1307  * Need to have domain checking and constraint checking at this
1308  * level similar to that done in object.c when attribute values
1309  * are being assigned.
1310  * return: NO_ERROR on success, non-zero for ERROR
1311  * template(in/out): schema template
1312  * name(in): attribute name
1313  * class_attribute(in): non-zero if looking at class attributes
1314  * proposed_value(in): default value to assign
1315  * default_expr(in): default expression
1316  */
1317 
1318 int
1319 smt_set_attribute_default (SM_TEMPLATE * template_, const char *name, int class_attribute, DB_VALUE * proposed_value,
1320  DB_DEFAULT_EXPR * default_expr)
1321 {
1322  int error = NO_ERROR;
1323  SM_ATTRIBUTE *att;
1324  DB_VALUE *value;
1325  TP_DOMAIN_STATUS status;
1326  char real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
1327 
1328  sm_downcase_name (name, real_name, SM_MAX_IDENTIFIER_LENGTH);
1329  name = real_name;
1330 
1331  error = smt_find_attribute (template_, name, class_attribute, &att);
1332  if (error == NO_ERROR)
1333  {
1334  if ((att->type->id == DB_TYPE_BLOB || att->type->id == DB_TYPE_CLOB) && proposed_value
1335  && !DB_IS_NULL (proposed_value))
1336  {
1337  ERROR1 (error, ER_SM_DEFAULT_NOT_ALLOWED, att->type->name);
1338  return error;
1339  }
1340  else if (proposed_value && DB_IS_NULL (proposed_value)
1341  && (default_expr == NULL || default_expr->default_expr_type == DB_DEFAULT_NONE)
1342  && (att->flags & SM_ATTFLAG_PRIMARY_KEY))
1343  {
1344  ERROR1 (error, ER_CANNOT_HAVE_PK_DEFAULT_NULL, name);
1345  return error;
1346  }
1347 
1348  value = proposed_value;
1349  status = tp_domain_check (att->domain, value, TP_EXACT_MATCH);
1350  if (status != DOMAIN_COMPATIBLE)
1351  {
1352  /* coerce it if we can */
1353  value = pr_make_ext_value ();
1354  if (value == NULL)
1355  {
1356  assert (er_errid () != NO_ERROR);
1357  error = er_errid ();
1358  goto end;
1359  }
1360 
1361  status = tp_value_cast (proposed_value, value, att->domain, false);
1362  /* value is freed at the bottom */
1363  }
1364  if (status != DOMAIN_COMPATIBLE)
1365  {
1366  ERROR1 (error, ER_OBJ_DOMAIN_CONFLICT, att->header.name);
1367  }
1368  else
1369  {
1370  /* check a subset of the integrity constraints, we can't check for NOT NULL or unique here */
1371 
1372  if (value != NULL && tp_check_value_size (att->domain, value) != DOMAIN_COMPATIBLE)
1373  {
1374  /* need an error message that isn't specific to "string" types */
1375  ERROR2 (error, ER_OBJ_STRING_OVERFLOW, att->header.name, att->domain->precision);
1376  }
1377  else
1378  {
1380  pr_clone_value (value, &att->default_value.value);
1381  if (default_expr == NULL)
1382  {
1384  }
1385  else
1386  {
1388  }
1389 
1390  /* if there wasn't an previous original value, take this one. This can only happen for new templates OR
1391  * if this is a new attribute that was added during this template OR if this is the first time setting a
1392  * default value to the attribute. This should be handled by using candidates in the template and storing
1393  * an extra bit field in the candidate structure. See the comment above sm_attribute for more information
1394  * about "original_value". */
1395  if (att->flags & SM_ATTFLAG_NEW)
1396  {
1397  error = smt_set_attribute_orig_default_value (att, value, default_expr);
1398  }
1399  }
1400  }
1401 
1402  /* free the coerced value if any */
1403  if (value != proposed_value)
1404  {
1405  pr_free_ext_value (value);
1406  }
1407  }
1408 
1409 end:
1410  return error;
1411 }
1412 
1413 /*
1414  * smt_set_attribute_orig_default_value() - Sets the original default value of the attribute.
1415  * No domain checking is performed.
1416  * return: void
1417  * att(in/out): attribute
1418  * new_orig_value(in): original value to set
1419  * default_expr(in): default expression
1420  *
1421  * Note : This function modifies the initial default value of the attribute.
1422  * The initial default value is the default value assigned when adding
1423  * the attribute. The default value of attribute may change after its
1424  * creation (or after it was added), but the initial value remains
1425  * unchanged (until attribute is dropped).
1426  * The (current) default value is stored as att->value; the initial
1427  * default value is stored as att->original_value.
1428  */
1429 
1430 static int
1432 {
1433  assert (att != NULL);
1434  assert (new_orig_value != NULL);
1435 
1437  pr_clone_value (new_orig_value, &att->default_value.original_value);
1438 
1439  if (default_expr == NULL)
1440  {
1442  return NO_ERROR;
1443  }
1444 
1445  return classobj_copy_default_expr (&att->default_value.default_expr, default_expr);
1446 }
1447 
1448 /*
1449  * smt_set_attribute_on_update() - Sets the on update default expr of an attribute.
1450  * No domain checking is performed.
1451  * return: NO_ERROR on success, non-zero for ERROR
1452  * template(in/out): schema template
1453  * name(in): attribute name
1454  * class_attribute(in): non-zero if looking at class attributes
1455  * on_update(in): on update default expression
1456  */
1457 int
1458 smt_set_attribute_on_update (SM_TEMPLATE * template_, const char *name, int class_attribute,
1459  DB_DEFAULT_EXPR_TYPE on_update)
1460 {
1461  int error = NO_ERROR;
1462  SM_ATTRIBUTE *att;
1463 
1464  error = smt_find_attribute (template_, name, class_attribute, &att);
1465  if (error != NO_ERROR)
1466  {
1467  return error;
1468  }
1469 
1470  att->on_update_default_expr = on_update;
1471  return NO_ERROR;
1472 }
1473 
1474 /*
1475  * smt_drop_constraint_from_property() - Drop the named constraint from the
1476  * template property list.
1477  * return: NO_ERROR on success, non-zero for ERROR
1478  * template(in/out): schema template
1479  * constraint_name(in): constraint name
1480  * constraint(in):
1481  */
1482 
1483 static int
1484 smt_drop_constraint_from_property (SM_TEMPLATE * template_, const char *constraint_name, SM_ATTRIBUTE_FLAG constraint)
1485 {
1486  int error = NO_ERROR;
1487  DB_VALUE oldval, newval;
1488  DB_SEQ *seq = NULL;
1489  const char *prop_type;
1490 
1492  {
1493  return NO_ERROR;
1494  }
1495 
1496  db_make_null (&oldval);
1497  db_make_null (&newval);
1498 
1499  prop_type = SM_MAP_CONSTRAINT_ATTFLAG_TO_PROPERTY (constraint);
1500 
1501  if (classobj_get_prop (template_->properties, prop_type, &oldval) > 0)
1502  {
1503  seq = db_get_set (&oldval);
1504 
1505  if (!classobj_drop_prop (seq, constraint_name))
1506  {
1507  ERROR1 (error, ER_SM_CONSTRAINT_NOT_FOUND, constraint_name);
1508  }
1509 
1510  db_make_sequence (&newval, seq);
1511  classobj_put_prop (template_->properties, prop_type, &newval);
1512  }
1513  else
1514  {
1515  ERROR1 (error, ER_SM_CONSTRAINT_NOT_FOUND, constraint_name);
1516  }
1517 
1518  pr_clear_value (&oldval);
1519  pr_clear_value (&newval);
1520 
1521  return error;
1522 }
1523 
1524 /*
1525  * smt_add_constraint_to_property() - Add the named constraint to the
1526  * template property list
1527  * return: NO_ERROR on success, non-zero for ERROR
1528  * template(in/out): schema template
1529  * type(in):
1530  * constraint_name(in): constraint name
1531  * atts(in):
1532  * asc_desc(in): asc/desc info list
1533  * attr_prefix_length(in):
1534  * fk_info(in):
1535  * shared_cons_name(in):
1536  * filter_index(in):
1537  * function_index(in)
1538  * comment(in):
1539  */
1540 static int
1541 smt_add_constraint_to_property (SM_TEMPLATE * template_, SM_CONSTRAINT_TYPE type, const char *constraint_name,
1542  SM_ATTRIBUTE ** atts, const int *asc_desc, const int *attr_prefix_length,
1543  SM_FOREIGN_KEY_INFO * fk_info, char *shared_cons_name, SM_PREDICATE_INFO * filter_index,
1544  SM_FUNCTION_INFO * function_index, const char *comment, SM_INDEX_STATUS index_status)
1545 {
1546  int error = NO_ERROR;
1547  DB_VALUE cnstr_val;
1548  const char *constraint = classobj_map_constraint_to_property (type);
1549 
1550  db_make_null (&cnstr_val);
1551 
1552  /*
1553  * Check if the constraint already exists. Skip it if we have an online index building done.
1554  */
1555  if (classobj_find_prop_constraint (template_->properties, constraint, constraint_name, &cnstr_val))
1556  {
1557  ERROR1 (error, ER_SM_CONSTRAINT_EXISTS, constraint_name);
1558  goto end;
1559  }
1560 
1561  if (classobj_put_index (&template_->properties, type, constraint_name, atts, asc_desc, attr_prefix_length, NULL,
1562  filter_index, fk_info, shared_cons_name, function_index, comment, index_status, true)
1563  != NO_ERROR)
1564  {
1565  ASSERT_ERROR_AND_SET (error);
1566  }
1567 
1568 end:
1569  pr_clear_value (&cnstr_val);
1570 
1571  return error;
1572 }
1573 
1574 /*
1575  * smt_check_foreign_key()
1576  * return: NO_ERROR on success, non-zero for ERROR
1577  * template(in): schema template
1578  * constraint_name(in): constraint name
1579  * atts(in):
1580  * n_atts(in):
1581  * fk_info(in/out):
1582  */
1583 static int
1584 smt_check_foreign_key (SM_TEMPLATE * template_, const char *constraint_name, SM_ATTRIBUTE ** atts, int n_atts,
1585  SM_FOREIGN_KEY_INFO * fk_info)
1586 {
1587  int error = NO_ERROR;
1588  MOP ref_clsop = NULL;
1589  SM_CLASS *ref_cls;
1590  SM_CLASS_CONSTRAINT *pk, *temp_cons = NULL;
1591  SM_ATTRIBUTE *tmp_attr, *ref_attr;
1592  int n_ref_atts, i, j;
1593  bool found;
1594  const char *tmp, *ref_cls_name = NULL;
1595 
1596  if (template_->op == NULL && intl_identifier_casecmp (template_->name, fk_info->ref_class) == 0)
1597  {
1598  error = classobj_make_class_constraints (template_->properties, template_->attributes, &temp_cons);
1599  if (error != NO_ERROR)
1600  {
1601  return error;
1602  }
1603 
1604  pk = classobj_find_cons_primary_key (temp_cons);
1605  if (pk == NULL)
1606  {
1607  ERROR1 (error, ER_FK_REF_CLASS_HAS_NOT_PK, fk_info->ref_class);
1608  goto err;
1609  }
1610 
1611  OID_SET_NULL (&fk_info->ref_class_oid);
1612  BTID_SET_NULL (&fk_info->ref_class_pk_btid);
1613  ref_cls_name = template_->name;
1614  }
1615  else
1616  {
1617  ref_clsop = sm_find_class (fk_info->ref_class);
1618 
1619  if (ref_clsop == NULL)
1620  {
1621  ERROR1 (error, ER_FK_UNKNOWN_REF_CLASSNAME, fk_info->ref_class);
1622  return error;
1623  }
1624 
1625  error = au_fetch_class (ref_clsop, &ref_cls, AU_FETCH_READ, AU_SELECT);
1626  if (error != NO_ERROR)
1627  {
1628  return error;
1629  }
1630 
1631  pk = classobj_find_class_primary_key (ref_cls);
1632  if (pk == NULL)
1633  {
1634  ERROR1 (error, ER_FK_REF_CLASS_HAS_NOT_PK, fk_info->ref_class);
1635  return error;
1636  }
1637 
1638  fk_info->ref_class_oid = *(ws_oid (ref_clsop));
1639  fk_info->ref_class_pk_btid = pk->index_btid;
1640  ref_cls_name = sm_ch_name ((MOBJ) ref_cls);
1641  }
1642 
1643  /* check pk'size and fk's size */
1644  for (i = 0; pk->attributes[i]; i++)
1645  {
1646  ;
1647  }
1648 
1649  if (i != n_atts)
1650  {
1651  ERROR2 (error, ER_FK_NOT_MATCH_KEY_COUNT, constraint_name, pk->name);
1652  goto err;
1653  }
1654 
1655  if (fk_info->ref_attrs)
1656  {
1657  n_ref_atts = 0;
1658 
1659  while (fk_info->ref_attrs[n_ref_atts] != NULL)
1660  {
1661  n_ref_atts++;
1662  }
1663 
1664  if (n_ref_atts != n_atts)
1665  {
1666  ERROR2 (error, ER_FK_NOT_MATCH_KEY_COUNT, constraint_name, pk->name);
1667  goto err;
1668  }
1669  }
1670 
1671  for (i = 0; pk->attributes[i]; i++)
1672  {
1673  found = false;
1674 
1675  if (fk_info->ref_attrs != NULL)
1676  {
1677  for (j = 0; fk_info->ref_attrs[j]; j++)
1678  {
1679  if (template_->op == NULL && temp_cons)
1680  {
1681  error = smt_find_attribute (template_, fk_info->ref_attrs[j], false, &ref_attr);
1682  if (error != NO_ERROR)
1683  {
1684  goto err;
1685  }
1686  }
1687  else
1688  {
1689  ref_attr = classobj_find_attribute (ref_cls, fk_info->ref_attrs[j], 0);
1690  if (ref_attr == NULL)
1691  {
1692  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, fk_info->ref_attrs[j]);
1693  goto err;
1694  }
1695  }
1696 
1697  if (pk->attributes[i]->id == ref_attr->id)
1698  {
1699  found = true;
1700  break;
1701  }
1702  }
1703 
1704  if (!found)
1705  {
1706  ERROR2 (error, ER_FK_NOT_HAVE_PK_MEMBER, constraint_name, pk->attributes[i]->header.name);
1707  goto err;
1708  }
1709 
1710  if (ref_attr->type->id != atts[j]->type->id
1711  || (TP_TYPE_HAS_COLLATION (ref_attr->type->id)
1712  && TP_DOMAIN_COLLATION (ref_attr->domain) != TP_DOMAIN_COLLATION (atts[j]->domain)))
1713  {
1714  ERROR2 (error, ER_FK_HAS_DEFFERENT_TYPE_WITH_PK, atts[j]->header.name, ref_attr->header.name);
1715  goto err;
1716  }
1717 
1718  if (i != j)
1719  {
1720  tmp_attr = atts[i];
1721  atts[i] = atts[j];
1722  atts[j] = tmp_attr;
1723 
1724  tmp = fk_info->ref_attrs[i];
1725  fk_info->ref_attrs[i] = fk_info->ref_attrs[j];
1726  fk_info->ref_attrs[j] = tmp;
1727  }
1728 
1729  }
1730  else
1731  {
1732  if (pk->attributes[i]->type->id != atts[i]->type->id
1733  || (TP_TYPE_HAS_COLLATION (atts[i]->type->id)
1734  && TP_DOMAIN_COLLATION (pk->attributes[i]->domain) != TP_DOMAIN_COLLATION (atts[i]->domain)))
1735  {
1736  ERROR2 (error, ER_FK_HAS_DEFFERENT_TYPE_WITH_PK, atts[i]->header.name, pk->attributes[i]->header.name);
1737  goto err;
1738  }
1739  }
1740  }
1741 
1742  fk_info->name = (char *) constraint_name;
1743 
1744 err:
1745  if (temp_cons)
1746  {
1747  classobj_free_class_constraints (temp_cons);
1748  }
1749 
1750  return error;
1751 }
1752 
1753 /*
1754  * smt_drop_constraint() - Drops the integrity constraint flags for an attribute.
1755  * return: NO_ERROR on success, non-zero for ERROR
1756  * template(in/out): schema template
1757  * att_names(in): array of attribute names
1758  * constraint_name(in): Constraint name.
1759  * class_attribute(in): non-zero if we're looking for class attributes
1760  * constraint(in): constraint identifier
1761  */
1762 
1763 int
1764 smt_drop_constraint (SM_TEMPLATE * template_, const char **att_names, const char *constraint_name, int class_attribute,
1765  SM_ATTRIBUTE_FLAG constraint)
1766 {
1767  int error = NO_ERROR;
1768  SM_ATTRIBUTE *not_null_attr[1], *pk_attr;
1769  SM_CLASS_CONSTRAINT *pk;
1770  int n_atts;
1771  MOP owner;
1772 
1773  if (!(SM_IS_ATTFLAG_UNIQUE_FAMILY_OR_FOREIGN_KEY (constraint) || constraint == SM_ATTFLAG_NON_NULL))
1774  {
1776  return error;
1777  }
1778 
1779  if (constraint == SM_ATTFLAG_PRIMARY_KEY)
1780  {
1781  char *fk_name = NULL;
1782 
1784  if (pk->fk_info && classobj_is_pk_referred (template_->op, pk->fk_info, true, &fk_name))
1785  {
1786  ERROR2 (error, ER_FK_CANT_DROP_PK_REFERRED, pk->name, fk_name);
1787  return error;
1788  }
1789  }
1790  else if (constraint == SM_ATTFLAG_NON_NULL)
1791  {
1792  n_atts = 0;
1793  if (att_names != NULL)
1794  {
1795  while (att_names[n_atts] != NULL)
1796  {
1797  n_atts++;
1798  }
1799  }
1800 
1801  if (n_atts != 1)
1802  {
1804  return error;
1805  }
1806  }
1807 
1808  owner = smt_find_owner_of_constraint (template_, constraint_name);
1809  if (owner == NULL)
1810  {
1811  assert (er_errid () != NO_ERROR);
1812  error = er_errid ();
1813  return error;
1814  }
1815 
1816  if (owner != template_->op && template_->partition == NULL)
1817  {
1818  /* it is inherited. */
1819  ERROR2 (error, ER_SM_INHERITED, constraint_name, sm_get_ch_name (owner));
1820  return error;
1821  }
1822 
1823  error = smt_drop_constraint_from_property (template_, constraint_name, constraint);
1824 
1825  if (error == NO_ERROR)
1826  {
1827  if (constraint == SM_ATTFLAG_PRIMARY_KEY)
1828  {
1829  for (pk_attr = template_->attributes; pk_attr != NULL; pk_attr = (SM_ATTRIBUTE *) pk_attr->header.next)
1830  {
1831  if (pk_attr->flags & SM_ATTFLAG_PRIMARY_KEY)
1832  {
1833  pk_attr->flags &= ~SM_ATTFLAG_PRIMARY_KEY;
1834  pk_attr->flags &= ~SM_ATTFLAG_NON_NULL;
1835  }
1836  }
1837  }
1838  else if (constraint == SM_ATTFLAG_NON_NULL)
1839  {
1840  error = smt_find_attribute (template_, att_names[0], class_attribute, &not_null_attr[0]);
1841 
1842  if (error == NO_ERROR)
1843  {
1844  if (not_null_attr[0]->flags & constraint)
1845  {
1846  not_null_attr[0]->flags &= ~constraint;
1847  }
1848  else
1849  {
1850  ERROR1 (error, ER_SM_CONSTRAINT_NOT_FOUND, "NON_NULL");
1851  }
1852  }
1853  }
1854  }
1855 
1856  return error;
1857 }
1858 
1859 /*
1860  * smt_check_index_exist() - Check index is duplicated.
1861  * return: NO_ERROR on success, non-zero for ERROR
1862  * template(in/out): schema template
1863  * out_shared_cons_name(out):
1864  * constraint_type: constraint type
1865  * constraint_name(in): Constraint name.
1866  * att_names(in): array of attribute names
1867  * asc_desc(in): asc/desc info list
1868  * filter_index(in): filter index info
1869  * function_index(in): function index info
1870  */
1871 int
1872 smt_check_index_exist (SM_TEMPLATE * template_, char **out_shared_cons_name, DB_CONSTRAINT_TYPE constraint_type,
1873  const char *constraint_name, const char **att_names, const int *asc_desc,
1874  const SM_PREDICATE_INFO * filter_index, const SM_FUNCTION_INFO * function_index)
1875 {
1876  int error = NO_ERROR;
1877  SM_CLASS *class_;
1878  SM_CLASS_CONSTRAINT *temp_cons = NULL;
1879  SM_CLASS_CONSTRAINT *check_cons;
1880 
1881  if (!DB_IS_CONSTRAINT_INDEX_FAMILY (constraint_type))
1882  {
1883  return NO_ERROR;
1884  }
1885 
1886  if (template_->op != NULL)
1887  {
1888  error = au_fetch_class (template_->op, &class_, AU_FETCH_READ, AU_INDEX);
1889  if (error != NO_ERROR)
1890  {
1891  return error;
1892  }
1893 
1894  check_cons = class_->constraints;
1895  }
1896  else
1897  {
1898  error = classobj_make_class_constraints (template_->properties, template_->attributes, &check_cons);
1899  if (error != NO_ERROR)
1900  {
1901  return error;
1902  }
1903 
1904  temp_cons = check_cons;
1905  }
1906 
1907  error =
1908  classobj_check_index_exist (check_cons, out_shared_cons_name, template_->name, constraint_type, constraint_name,
1909  att_names, asc_desc, filter_index, function_index);
1910 
1911  if (temp_cons != NULL)
1912  {
1913  classobj_free_class_constraints (temp_cons);
1914  }
1915 
1916  return error;
1917 }
1918 
1919 /*
1920  * smt_add_constraint() - Adds the integrity constraint flags for an attribute.
1921  * return: NO_ERROR on success, non-zero for ERROR
1922  * template(in/out): schema template
1923  * constraint_type(in): constraint type
1924  * constraint_name(in): Constraint name.
1925  * att_names(in): array of attribute names
1926  * attrs_prefix_length(in): prefix length for each of the index attributes
1927  * asc_desc(in): asc/desc info list
1928  * class_attribute(in): non-zero if we're looking for class attributes
1929  * fk_info(in): foreign key information
1930  * filter_index(in): filter index info
1931  * function_index(in): function index info
1932  * comment(in): constraint comment
1933  * index_status(in):
1934  */
1935 int
1936 smt_add_constraint (SM_TEMPLATE * template_, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name,
1937  const char **att_names, const int *asc_desc, const int *attrs_prefix_length, int class_attribute,
1938  SM_FOREIGN_KEY_INFO * fk_info, SM_PREDICATE_INFO * filter_index, SM_FUNCTION_INFO * function_index,
1939  const char *comment, SM_INDEX_STATUS index_status)
1940 {
1941  int error = NO_ERROR;
1942  SM_ATTRIBUTE **atts = NULL;
1943  int i, j, n_atts, atts_size;
1944  char *shared_cons_name = NULL;
1945  SM_ATTRIBUTE_FLAG constraint;
1946  bool has_nulls = false;
1947  bool is_secondary_index = false;
1948 
1949  assert (template_ != NULL);
1950 
1951  error = smt_check_index_exist (template_, &shared_cons_name, constraint_type, constraint_name, att_names,
1952  asc_desc, filter_index, function_index);
1953  if (error != NO_ERROR)
1954  {
1955  goto error_return;
1956  }
1957 
1958  constraint = SM_MAP_CONSTRAINT_TO_ATTFLAG (constraint_type);
1959  is_secondary_index = (constraint_type == DB_CONSTRAINT_INDEX || constraint_type == DB_CONSTRAINT_REVERSE_INDEX);
1960 
1961  n_atts = 0;
1962  if (att_names != NULL)
1963  {
1964  while (att_names[n_atts] != NULL)
1965  {
1966  n_atts++;
1967  }
1968  }
1969 
1970  if (n_atts == 0)
1971  {
1973  goto error_return;
1974  }
1975 
1976  /* if primary key shares index with other constraint, it is neccessary to check whether the attributs do not have
1977  * null value. e.g. primary key shares index with unique constraint. Because unique constraint allows null value, we
1978  * can not just use the index simply. template_->op == NULL, it means this is a create statement, the class has not
1979  * yet existed. Obviously, there is no data in the class at that time! So we skip to test NULL value for primary
1980  * key. */
1981  if (constraint_type == DB_CONSTRAINT_PRIMARY_KEY && shared_cons_name != NULL && template_->op != NULL)
1982  {
1983  for (i = 0; att_names[i] != NULL; i++)
1984  {
1985  assert (att_names[i] != NULL);
1986  error = do_check_rows_for_null (template_->op, att_names[i], &has_nulls);
1987  if (error != NO_ERROR)
1988  {
1989  goto error_return;
1990  }
1991 
1992  if (has_nulls)
1993  {
1994  error = ER_SM_ATTR_NOT_NULL;
1995  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, att_names[i]);
1996  goto error_return;
1997  }
1998  }
1999  }
2000 
2001  atts_size = (n_atts + 1) * (int) sizeof (SM_ATTRIBUTE *);
2002  atts = (SM_ATTRIBUTE **) malloc (atts_size);
2003  if (atts == NULL)
2004  {
2006 
2007  error = ER_OUT_OF_VIRTUAL_MEMORY;
2008  goto error_return;
2009  }
2010 
2011  for (i = 0; i < n_atts && error == NO_ERROR; i++)
2012  {
2013  error = smt_find_attribute (template_, att_names[i], class_attribute, &atts[i]);
2014  if (error == ER_SM_INHERITED_ATTRIBUTE)
2015  {
2016  if (is_secondary_index)
2017  {
2018  // secondary indexes are allowed on an inherited column
2019  assert (atts[i] != NULL);
2020 
2021  er_clear ();
2022  error = NO_ERROR;
2023  }
2024  }
2025 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
2026  else if (error == NO_ERROR && SM_IS_ATTFLAG_INDEX_FAMILY (constraint))
2027  {
2028  /* prevent to create index on TEXT attribute */
2029  if (sm_has_text_domain (atts[i], 0))
2030  {
2031  if (strstr (constraint_name, TEXT_CONSTRAINT_PREFIX))
2032  {
2034  }
2035  }
2036  }
2037 #endif /* ENABLE_UNUSED_FUNCTION */
2038  }
2039  atts[i] = NULL;
2040 
2041  if (error != NO_ERROR)
2042  {
2043  goto error_return;
2044  }
2045 
2046  /* check that there are no duplicate attr defs in given list */
2047  for (i = 0; i < n_atts && error == NO_ERROR; i++)
2048  {
2049  for (j = i + 1; j < n_atts; j++)
2050  {
2051  /* can not check attr-id, because is not yet assigned */
2052  if (intl_identifier_casecmp (atts[i]->header.name, atts[j]->header.name) == 0)
2053  {
2054  ERROR1 (error, ER_SM_INDEX_ATTR_DUPLICATED, atts[i]->header.name);
2055  }
2056  }
2057  }
2058 
2059  if (error != NO_ERROR)
2060  {
2061  goto error_return;
2062  }
2063 
2064  if (is_secondary_index)
2065  {
2066  for (i = 0; atts[i] != NULL; i++)
2067  {
2068  DB_TYPE type = atts[i]->type->id;
2069 
2070  if (!tp_valid_indextype (type))
2071  {
2072  error = ER_SM_INVALID_INDEX_TYPE;
2073  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, pr_type_name (type));
2074  break;
2075  }
2076  else if (attrs_prefix_length && attrs_prefix_length[i] >= 0)
2077  {
2078  if (!TP_IS_CHAR_TYPE (type) && !TP_IS_BIT_TYPE (type))
2079  {
2081  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, pr_type_name (type));
2082  break;
2083  }
2084  else if (((long) atts[i]->domain->precision) < attrs_prefix_length[i])
2085  {
2087  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_INVALID_PREFIX_LENGTH, 1, attrs_prefix_length[i]);
2088  break;
2089  }
2090  }
2091  }
2092  }
2093 
2094  if (error != NO_ERROR)
2095  {
2096  goto error_return;
2097  }
2098 
2099  /*
2100  * Process constraint
2101  */
2102  if (SM_IS_ATTFLAG_INDEX_FAMILY (constraint))
2103  {
2104  /* Check possible errors:
2105  * - We do not allow UNIQUE constraints/INDEXES on any attribute of a virtual class.
2106  * - We do not allow UNIQUE constraints/INDEXES on class|shared attributes.
2107  * - We only allow unique constraints on indexable data types.
2108  */
2109  if (template_->class_type != SM_CLASS_CT)
2110  {
2111  ERROR0 (error, ER_SM_UNIQUE_ON_VCLASS);
2112  goto error_return;
2113  }
2114 
2115  for (i = 0; i < n_atts; i++)
2116  {
2117  if (atts[i]->header.name_space == ID_SHARED_ATTRIBUTE || class_attribute)
2118  {
2119  if (constraint == SM_ATTFLAG_FOREIGN_KEY)
2120  {
2121  ERROR2 (error, ER_FK_CANT_ON_SHARED_ATTRIBUTE, constraint_name, atts[i]->header.name);
2122  }
2123  else
2124  {
2125  ERROR1 (error, ER_SM_INDEX_ON_SHARED, att_names[i]);
2126  }
2127  goto error_return;
2128  }
2129 
2130  if (!tp_valid_indextype (atts[i]->type->id))
2131  {
2132  if (SM_IS_ATTFLAG_UNIQUE_FAMILY (constraint))
2133  {
2134  ERROR2 (error, ER_SM_INVALID_UNIQUE_TYPE, atts[i]->type->name,
2135  SM_GET_CONSTRAINT_STRING (constraint_type));
2136  }
2137  else
2138  {
2139  assert (constraint == SM_ATTFLAG_INDEX || constraint == SM_ATTFLAG_REVERSE_INDEX
2140  || constraint == SM_ATTFLAG_FOREIGN_KEY);
2141  ERROR1 (error, ER_SM_INVALID_INDEX_TYPE, atts[i]->type->name);
2142  }
2143  goto error_return;
2144  }
2145  }
2146 
2147  if (constraint == SM_ATTFLAG_FOREIGN_KEY)
2148  {
2149  error = smt_check_foreign_key (template_, constraint_name, atts, n_atts, fk_info);
2150  if (error != NO_ERROR)
2151  {
2152  goto error_return;
2153  }
2154  }
2155  else
2156  {
2157  assert (fk_info == NULL);
2158  }
2159 
2160  /* Add the constraint. */
2161  error = smt_add_constraint_to_property (template_, SM_MAP_INDEX_ATTFLAG_TO_CONSTRAINT (constraint),
2162  constraint_name, atts, asc_desc, attrs_prefix_length, fk_info,
2163  shared_cons_name, filter_index, function_index, comment, index_status);
2164  if (error != NO_ERROR)
2165  {
2166  goto error_return;
2167  }
2168 
2169  if (constraint == SM_ATTFLAG_PRIMARY_KEY)
2170  {
2171  for (i = 0; i < n_atts; i++)
2172  {
2173  atts[i]->flags |= SM_ATTFLAG_PRIMARY_KEY;
2174  atts[i]->flags |= SM_ATTFLAG_NON_NULL;
2175  }
2176  }
2177  }
2178  else if (constraint == SM_ATTFLAG_NON_NULL)
2179  {
2180  /*
2181  * We do not support NOT NULL constraints for;
2182  * - normal (not class and shared) attributes of virtual classes
2183  * - multiple attributes
2184  * - class attributes without default value
2185  */
2186  if (n_atts != 1)
2187  {
2189  }
2190  else if (template_->class_type != SM_CLASS_CT && atts[0]->header.name_space == ID_ATTRIBUTE)
2191  {
2193  }
2194  else if (class_attribute && DB_IS_NULL (&(atts[0]->default_value.value)))
2195  {
2197  }
2198  else if (atts[0]->type->id == DB_TYPE_BLOB || atts[0]->type->id == DB_TYPE_CLOB)
2199  {
2200  ERROR1 (error, ER_SM_NOT_NULL_NOT_ALLOWED, atts[0]->type->name);
2201  }
2202  else
2203  {
2204  if (atts[0]->flags & constraint)
2205  {
2206  ERROR1 (error, ER_SM_CONSTRAINT_EXISTS, "NON_NULL");
2207  }
2208  else
2209  {
2210  atts[0]->flags |= constraint;
2211  }
2212  }
2213  }
2214  else
2215  {
2216  /* Unknown constraint type */
2218  }
2219 
2220 error_return:
2221  if (atts != NULL)
2222  {
2223  free_and_init (atts);
2224  }
2225 
2226  if (shared_cons_name != NULL)
2227  {
2228  free_and_init (shared_cons_name);
2229  }
2230 
2231  return (error);
2232 }
2233 
2234 /* TEMPLATE METHOD FUNCTIONS */
2235 /*
2236  * smt_add_method_any() - This will add an instance method or class method to
2237  * a template. It would be nice to merge this with smt_add_attribyte_any but
2238  * the argument lists are slightly different so keep them separate
2239  * for now.
2240  * NOTE: The original implementation was designed to allow
2241  * multiple method signatures each with their own unique function
2242  * name. This feature has been postponed indefinately because of the
2243  * complexity added to the interpreter. Because of this, the method
2244  * structures are a bit more complicated than necessary but the partial
2245  * support for multiple signatures has been left in for future
2246  * expansion.
2247  * return: NO_ERROR on success, non-zero for ERROR
2248  * template(in/out): schema template
2249  * name(in): method name
2250  * function(in): implementation function name
2251  * namespace(in): class or insance name_space identifier
2252  */
2253 
2254 int
2255 smt_add_method_any (SM_TEMPLATE * template_, const char *name, const char *function, SM_NAME_SPACE name_space)
2256 {
2257  int error = NO_ERROR;
2258  SM_METHOD *method;
2259  SM_METHOD_SIGNATURE *sig;
2260  char iname[SM_MAX_IDENTIFIER_LENGTH * 2 + 2];
2261  SM_METHOD **methlist = NULL;
2262  char realname[SM_MAX_IDENTIFIER_LENGTH];
2263 
2264  if (!sm_check_name (name))
2265  {
2266  ASSERT_ERROR_AND_SET (error);
2267  return error;
2268  }
2269 
2270  sm_downcase_name (name, realname, SM_MAX_IDENTIFIER_LENGTH);
2271  name = realname;
2272 
2273  if (name_space == ID_CLASS || name_space == ID_CLASS_METHOD)
2274  {
2275  methlist = &template_->class_methods;
2276  error = check_namespace (template_, name, true);
2277  }
2278  else
2279  {
2280  methlist = &template_->methods;
2281  error = check_namespace (template_, name, false);
2282  }
2283 
2284  if (error != NO_ERROR)
2285  {
2286  return error;
2287  }
2288 
2289  if (methlist != NULL)
2290  {
2291  method = (SM_METHOD *) SM_FIND_NAME_IN_COMPONENT_LIST (*methlist, name);
2292  if (method == NULL)
2293  {
2294  method = classobj_make_method (name, name_space);
2295  if (method == NULL)
2296  {
2297  ASSERT_ERROR_AND_SET (error);
2298  return error;
2299  }
2300 
2301  method->class_mop = template_->op;
2302  WS_LIST_APPEND (methlist, method);
2303  }
2304 
2305  /* THESE FOUR LINES ENFORCE THE SINGLE SIGNATURE RESTRICTION */
2306  if (method->signatures != NULL)
2307  {
2308  ERROR2 (error, ER_SM_SIGNATURE_EXISTS, name, function);
2309  return error;
2310  }
2311 
2312  /* NEED TO CHECK FOR IDENTIFIER LENGTH OVERFLOW !!! */
2313 
2314  if (function != NULL)
2315  {
2316  sprintf (iname, "%s", function);
2317  }
2318  else
2319  {
2320  if (template_->name != NULL)
2321  {
2322  sprintf (iname, "%s_%s", template_->name, name);
2323  }
2324  else if (template_->op != NULL)
2325  {
2326  sprintf (iname, "%s_%s", sm_get_ch_name (template_->op), name);
2327  }
2328  else
2329  {
2330  /* this should be an error */
2331  sprintf (iname, "%s_%s", "unknown_class", name);
2332  }
2333  }
2334 
2335  /* implementation names are case sensitive */
2336  sig = (SM_METHOD_SIGNATURE *) NLIST_FIND (method->signatures, iname);
2337  if (sig != NULL)
2338  {
2339  ERROR2 (error, ER_SM_SIGNATURE_EXISTS, name, function);
2340  return error;
2341  }
2342 
2343  sig = classobj_make_method_signature (iname);
2344  if (sig == NULL)
2345  {
2346  ASSERT_ERROR_AND_SET (error);
2347  return error;
2348  }
2349  WS_LIST_APPEND (&method->signatures, sig);
2350  }
2351 
2352  return error;
2353 }
2354 
2355 /*
2356  * smt_add_method()
2357  * smt_add_class_method() - These are type specific functions
2358  * for adding methods. I would prefer callers convert to the
2359  * smt_add_method_any style but this will be a gradual change.
2360  * return: NO_ERROR on success, non-zero for ERROR
2361  * template(in/out): schema template
2362  * name(in): method name
2363  * function(in): method implementation function
2364  */
2365 
2366 int
2367 smt_add_method (SM_TEMPLATE * template_, const char *name, const char *function)
2368 {
2369  return (smt_add_method_any (template_, name, function, ID_METHOD));
2370 }
2371 
2372 int
2373 smt_add_class_method (SM_TEMPLATE * template_, const char *name, const char *function)
2374 {
2375  return (smt_add_method_any (template_, name, function, ID_CLASS_METHOD));
2376 }
2377 
2378 /*
2379  * smt_change_method_implementation() - This changes the name of the function
2380  * that implements a method.
2381  * NOTE: This is written with the assumption that methods do NOT
2382  * have multiple signatures. This is currently the case but if
2383  * we extend this in the future, we will need another
2384  * mechanism to identify the implementation that needs to change.
2385  * return: NO_ERROR on success, non-zero for ERROR
2386  * template(in/out): schema template
2387  * name(in): method name
2388  * class_method(in): non-zero if looking at class methods
2389  * function(in): method implementation function
2390  */
2391 
2392 int
2393 smt_change_method_implementation (SM_TEMPLATE * template_, const char *name, int class_method, const char *function)
2394 {
2395  int error = NO_ERROR;
2396  SM_METHOD *method, *method_list;
2397  const char *current;
2398 
2399  method_list = (class_method ? template_->class_methods : template_->methods);
2400  method = (SM_METHOD *) SM_FIND_NAME_IN_COMPONENT_LIST (method_list, name);
2401 
2402  if (method == NULL)
2403  {
2404  ERROR1 (error, ER_SM_METHOD_NOT_FOUND, name);
2405  return error;
2406  }
2407 
2408  if (method->signatures == NULL)
2409  {
2410  ERROR2 (error, ER_SM_SIGNATURE_NOT_FOUND, name, function);
2411  return error;
2412  }
2413 
2414  if (method->signatures->next != NULL)
2415  {
2416  ERROR1 (error, ER_SM_MULTIPLE_SIGNATURES, name);
2417  return error;
2418  }
2419 
2420  current = method->signatures->function_name;
2421  method->signatures->function_name = ws_copy_string (function);
2422  if (method->signatures->function_name == NULL)
2423  {
2424  ASSERT_ERROR_AND_SET (error);
2425  // fall through
2426  }
2427  ws_free_string (current);
2428 
2429  /* If this method has been called, we need to invalidate it so that dynamic linking will be invoked to
2430  * get the new resolution. Remember to do both the "real" one and the cache. */
2431  method->function = NULL;
2432  method->signatures->function = NULL;
2433 
2434  return error;
2435 }
2436 
2437 /*
2438  * smt_assign_argument_domain() - This is used to assign a basic domain to a
2439  * method argument. If there is already a domain specified for the argument
2440  * it will be replaced. If the domain argument is NULL, any existing
2441  * domain information for the argument will be removed.
2442  * return: NO_ERROR on success, non-zero for ERROR
2443  * template(in/out): schema template
2444  * name(in): method name
2445  * class_method(in): non-zero if operating on class method
2446  * implementation(in): method implementation function
2447  * index(in): argument index
2448  * domain_string(in): argument domain name
2449  * domain(in): domain structure
2450  */
2451 
2452 int
2453 smt_assign_argument_domain (SM_TEMPLATE * template_, const char *name, int class_method, const char *implementation,
2454  int index, const char *domain_string, DB_DOMAIN * domain)
2455 {
2456  int error = NO_ERROR;
2457  SM_METHOD *method;
2458  SM_METHOD_SIGNATURE *sig;
2459  SM_METHOD_ARGUMENT *arg;
2460 
2461  error = find_argument (template_, name, class_method, implementation, index, true, &method, &sig, &arg);
2462  if (error != NO_ERROR)
2463  {
2464  return error;
2465  }
2466 
2467  if (domain_string == NULL && domain == NULL)
2468  {
2469  /* no domain given, reset the domain list */
2470  arg->domain = NULL;
2471  }
2472  else
2473  {
2474  error = get_domain (template_, domain_string, &domain);
2475  if (error != NO_ERROR)
2476  {
2477  return error;
2478  }
2479 
2480  if (domain != NULL)
2481  {
2482  if (arg->type != NULL && arg->type != domain->type)
2483  {
2484  /* changing the domain, automatically reset the domain list */
2485  arg->domain = NULL;
2486  }
2487  arg->type = domain->type;
2488  arg->domain = domain;
2489  }
2490  }
2491 
2492  return error;
2493 }
2494 
2495 /*
2496  * smt_add_set_argument_domain() - This adds domain information to a method
2497  * argument whose basic type is one of the set types.
2498  * return: NO_ERROR on success, non-zero for ERROR
2499  * template(in/out): schema template
2500  * name(in): method name
2501  * class_method(in): non-zero if operating on class method
2502  * implementation(in): method implementation function
2503  * index(in): argument index
2504  * domain_string(in): domain name of set element
2505  * domain(in): domain structure
2506  */
2507 
2508 int
2509 smt_add_set_argument_domain (SM_TEMPLATE * template_, const char *name, int class_method, const char *implementation,
2510  int index, const char *domain_string, DB_DOMAIN * domain)
2511 {
2512  int error = NO_ERROR;
2513  SM_METHOD *method;
2514  SM_METHOD_SIGNATURE *sig;
2515  SM_METHOD_ARGUMENT *arg;
2516 
2517  error = get_domain (template_, domain_string, &domain);
2518  if (error != NO_ERROR)
2519  {
2520  return error;
2521  }
2522 
2523  if (domain == NULL)
2524  {
2525  ERROR2 (error, ER_SM_DOMAIN_NOT_FOUND, name, (domain_string ? domain_string : "unknown"));
2526  return error;
2527  }
2528 
2529  error = find_argument (template_, name, class_method, implementation, index, false, &method, &sig, &arg);
2530  if (error != NO_ERROR)
2531  {
2532  return error;
2533  }
2534 
2535  if (arg->domain == NULL || !pr_is_set_type (TP_DOMAIN_TYPE (arg->domain)))
2536  {
2537  ERROR2 (error, ER_SM_ARG_DOMAIN_NOT_A_SET, name, index);
2538  return error;
2539  }
2540 
2541  error = tp_domain_add (&arg->domain->setdomain, domain);
2542 
2543  return error;
2544 }
2545 
2546 /* TEMPLATE RENAME FUNCTIONS */
2547 
2548 /*
2549  * smt_rename_any() - Renames a component (attribute or method).
2550  * This is semantically different than just dropping the component
2551  * and re-adding it since the internal ID number assigned
2552  * to the component must remain the same after the rename.
2553  * return: NO_ERROR on success, non-zero for ERROR
2554  * template(in/out): schema template
2555  * name(in): attribute or method name
2556  * class_namespace(in): non-zero of looking for class components
2557  * new_name(in): new name of component
2558  */
2559 
2560 int
2561 smt_rename_any (SM_TEMPLATE * template_, const char *name, const bool class_namespace, const char *new_name)
2562 {
2563  int error = NO_ERROR;
2564  SM_COMPONENT *comp;
2565  char real_new_name[SM_MAX_IDENTIFIER_LENGTH];
2566 
2567  if (!sm_check_name (name) || !sm_check_name (new_name))
2568  {
2569  ASSERT_ERROR_AND_SET (error);
2570  return error;
2571  }
2572 
2573  sm_downcase_name (new_name, real_new_name, SM_MAX_IDENTIFIER_LENGTH);
2574  new_name = real_new_name;
2575 
2576  /* find the named component */
2577  error = find_any (template_, name, class_namespace, &comp);
2578  if (error != NO_ERROR)
2579  {
2580  return error;
2581  }
2582 
2583  if (comp->name_space == ID_ATTRIBUTE || comp->name_space == ID_SHARED_ATTRIBUTE
2584  || comp->name_space == ID_CLASS_ATTRIBUTE)
2585  {
2586  SM_ATTRIBUTE *att;
2587 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
2588  error = smt_find_attribute (template_, comp->name, (comp->name_space == ID_CLASS_ATTRIBUTE ? 1 : 0), &att);
2589  if (error == NO_ERROR)
2590  {
2591  if (sm_has_text_domain (att, 0))
2592  {
2593  /* prevent to rename attribute */
2595  }
2596  }
2597 #else /* ENABLE_UNUSED_FUNCTION */
2598  error = smt_find_attribute (template_, comp->name, (comp->name_space == ID_CLASS_ATTRIBUTE ? 1 : 0), &att);
2599 #endif /* ENABLE_UNUSED_FUNCTION */
2600  if (error != NO_ERROR)
2601  {
2602  return error;
2603  }
2604  }
2605 
2606  /* check for collisions on the new name */
2607  error = check_namespace (template_, new_name, class_namespace);
2608  if (error != NO_ERROR)
2609  {
2610  return error;
2611  }
2612 
2613  ws_free_string (comp->name);
2614  comp->name = ws_copy_string (new_name);
2615  if (comp->name == NULL)
2616  {
2617  ASSERT_ERROR_AND_SET (error);
2618  return error;
2619  }
2620 
2621  return error;
2622 }
2623 
2624 #if defined (ENABLE_RENAME_CONSTRAINT)
2625 /*
2626  * rename_constraint() - Renames a constraint.
2627  * return: NO_ERROR on success, non-zero for ERROR
2628  * ctemplate(in/out): schema template
2629  * sm_cons(in/out) : list of constraints
2630  * old_name(in): old name of constraint
2631  * new_name(in): new name of constraint
2632  * element_type(in): type of constraint
2633  */
2634 
2635 static int
2636 rename_constraint (SM_TEMPLATE * ctemplate, SM_CLASS_CONSTRAINT * sm_cons, const char *old_name, const char *new_name,
2637  SM_CONSTRAINT_FAMILY element_type)
2638 {
2639  int error = NO_ERROR;
2640  DB_CONSTRAINT_TYPE ctype;
2642  SM_CLASS_CONSTRAINT *existing_con = NULL;
2643  const char *property_type = NULL;
2644  char *norm_new_name = NULL;
2645  MOP ref_clsop;
2646  BTID *btid = NULL;
2647 
2648  assert (ctemplate != NULL);
2649  assert (sm_cons != NULL);
2650 
2651  sm_constraint = classobj_find_constraint_by_name (sm_cons, old_name);
2652  if (sm_constraint == NULL)
2653  {
2655  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2656  goto error_exit;
2657  }
2658  btid = &sm_constraint->index_btid;
2659 
2660  switch (element_type)
2661  {
2662  case SM_CONSTRAINT_NAME: /* "*U", "*RU", "*P", "*FK" */
2663  if (!SM_IS_CONSTRAINT_EXCEPT_INDEX_FAMILY (sm_constraint->type))
2664  {
2666  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2667  goto error_exit;
2668  }
2669  break;
2670  case SM_INDEX_NAME: /* "*U", "*I", "*RU", "*RI" */
2671  if (!SM_IS_INDEX_FAMILY (sm_constraint->type))
2672  {
2674  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2675  goto error_exit;
2676  }
2677  break;
2678  default:
2680  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2681  goto error_exit;
2682  break;
2683  }
2684 
2685  ctype = db_constraint_type (sm_constraint);
2686 
2687  norm_new_name = sm_produce_constraint_name (ctemplate->name, ctype, NULL, NULL, new_name);
2688  if (norm_new_name == NULL)
2689  {
2690  assert (er_errid () != NO_ERROR);
2691  error = er_errid ();
2692  assert (error != NO_ERROR);
2693  goto error_exit;
2694  }
2695 
2696  /* check norm_new_name uniqueness */
2697  existing_con = classobj_find_constraint_by_name (sm_cons, norm_new_name);
2698  if (existing_con)
2699  {
2700  ERROR2 (error, ER_SM_INDEX_EXISTS, ctemplate->name, existing_con->name);
2701  goto error_exit;
2702  }
2703 
2704  property_type = classobj_map_constraint_to_property (sm_constraint->type);
2705 
2706  error = classobj_rename_constraint (ctemplate->properties, property_type, old_name, norm_new_name);
2707  if (error != NO_ERROR)
2708  {
2709  goto error_exit;
2710  }
2711 
2712  /* Rename foreign key ref in owner table. */
2713  if (sm_constraint->type == SM_CONSTRAINT_FOREIGN_KEY)
2714  {
2715  ref_clsop = ws_mop (&(sm_constraint->fk_info->ref_class_oid), NULL);
2716  if (ctemplate->op == ref_clsop)
2717  {
2718  /* Class references to itself. The below rename FK ref in properties of this class. */
2719  error = classobj_rename_foreign_key_ref (&(ctemplate->properties), btid, old_name, new_name);
2720  }
2721  else
2722  {
2723  /* Class references to another one (owner class). The below rename FK ref in owner class and update the owner
2724  * class. */
2725  error = sm_rename_foreign_key_ref (ref_clsop, btid, old_name, new_name);
2726  }
2727 
2728  if (error != NO_ERROR)
2729  {
2730  goto error_exit;
2731  }
2732  }
2733 
2734 end:
2735  if (norm_new_name)
2736  {
2737  free_and_init (norm_new_name);
2738  }
2739  return error;
2740 
2741 error_exit:
2742  goto end;
2743 }
2744 
2745 /*
2746  * rename_constraints_partitioned_class () - This function renames
2747  * constraints in sub-classes(partition classes).
2748  * return: NO_ERROR on success, non-zero for ERROR
2749  * ctemplate(in): sm_template of the super class (partition class)
2750  * old_name(in): old name of constraint
2751  * new_name(in): new name of constraint
2752  * element_type(in): type of constraint
2753  */
2754 static int
2755 rename_constraints_partitioned_class (SM_TEMPLATE * ctemplate, const char *old_name, const char *new_name,
2756  SM_CONSTRAINT_FAMILY element_type)
2757 {
2758  int error = NO_ERROR;
2759  int i, is_partition = 0;
2760  MOP *sub_partitions = NULL;
2761  SM_TEMPLATE *sub_ctemplate = NULL;
2762  SM_CLASS_CONSTRAINT *sm_cons = NULL;
2763 
2764  assert (ctemplate != NULL);
2765 
2766  error = sm_partitioned_class_type (ctemplate->op, &is_partition, NULL, &sub_partitions);
2767  if (error != NO_ERROR)
2768  {
2769  goto error_exit;
2770  }
2771 
2772  if (is_partition == DB_PARTITION_CLASS)
2773  {
2775  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2776  goto error_exit;
2777  }
2778  else if (is_partition == DB_NOT_PARTITIONED_CLASS)
2779  {
2780  goto end;
2781  }
2782 
2783  assert (is_partition == DB_PARTITIONED_CLASS);
2784 
2785  for (i = 0; sub_partitions[i]; i++)
2786  {
2787  if (sm_exist_index (sub_partitions[i], old_name, NULL) != NO_ERROR)
2788  {
2789  continue;
2790  }
2791 
2792  sub_ctemplate = smt_edit_class_mop (sub_partitions[i], AU_INDEX);
2793  if (sub_ctemplate == NULL)
2794  {
2795  assert (er_errid () != NO_ERROR);
2796  error = er_errid ();
2797  assert (error != NO_ERROR);
2798  goto error_exit;
2799  }
2800 
2801  /* make a list of constraints that is included in the partitioned class. */
2802  error = classobj_make_class_constraints (sub_ctemplate->properties, sub_ctemplate->attributes, &sm_cons);
2803  if (error != NO_ERROR)
2804  {
2805  goto error_exit;
2806  }
2807 
2808  if (sm_cons == NULL)
2809  {
2811  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2812  goto error_exit;
2813  }
2814 
2815  error = rename_constraint (sub_ctemplate, sm_cons, old_name, new_name, element_type);
2816  if (error != NO_ERROR)
2817  {
2818  goto error_exit;
2819  }
2820 
2821  if (sm_cons)
2822  {
2824  sm_cons = NULL;
2825  }
2826 
2827  /* classobj_free_template() is included in sm_update_class() */
2828  error = sm_update_class (sub_ctemplate, NULL);
2829  if (error != NO_ERROR)
2830  {
2831  /* Even though sm_update() did not return NO_ERROR, sub_ctemplate is already freed */
2832  sub_ctemplate = NULL;
2833  goto error_exit;
2834  }
2835  }
2836 
2837 end:
2838  if (sub_partitions != NULL)
2839  {
2840  free_and_init (sub_partitions);
2841  }
2842  return error;
2843 
2844 error_exit:
2845  if (sm_cons)
2846  {
2848  }
2849  if (sub_ctemplate != NULL)
2850  {
2851  /* smt_quit() always returns NO_ERROR */
2852  smt_quit (sub_ctemplate);
2853  }
2854  goto end;
2855 }
2856 
2857 /*
2858  * smt_rename_constraint() - This function renames constraints in
2859  * sm_template.
2860  * return: NO_ERROR on success, non-zero for ERROR
2861  * ctemplate(in): sm_template of the class
2862  * old_name(in): old name of constraint
2863  * new_name(in): new name of constraint
2864  * element_type(in): type of constraint
2865  */
2866 
2867 int
2868 smt_rename_constraint (SM_TEMPLATE * ctemplate, const char *old_name, const char *new_name,
2869  SM_CONSTRAINT_FAMILY element_type)
2870 {
2871  int error = NO_ERROR;
2872  SM_CLASS_CONSTRAINT *sm_cons = NULL;
2874  int is_global = 0;
2875  MOP owner;
2876 
2877  assert (ctemplate != NULL);
2878 
2879  owner = smt_find_owner_of_constraint (ctemplate, old_name);
2880  if (owner == NULL)
2881  {
2882  assert (er_errid () != NO_ERROR);
2883  error = er_errid ();
2884  return error;
2885  }
2886 
2887  if (owner != ctemplate->op)
2888  {
2889  /* it is inherited. */
2890  ERROR2 (error, ER_SM_INHERITED, old_name, sm_get_ch_name (owner));
2891  return error;
2892  }
2893 
2894  error = classobj_make_class_constraints (ctemplate->properties, ctemplate->attributes, &sm_cons);
2895  if (error != NO_ERROR)
2896  {
2897  goto error_exit;
2898  }
2899 
2900  if (sm_cons == NULL)
2901  {
2903  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2904  goto error_exit;
2905  }
2906 
2907  sm_constraint = classobj_find_constraint_by_name (sm_cons, old_name);
2908  if (sm_constraint == NULL)
2909  {
2911  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
2912  goto error_exit;
2913  }
2914 
2915  error = sm_is_global_only_constraint (ctemplate->op, sm_constraint, &is_global, ctemplate);
2916  if (error != NO_ERROR)
2917  {
2918  goto error_exit;
2919  }
2920 
2921  /* The global constraint is not included in the partitioned class. */
2922  if (is_global == 0)
2923  {
2924  error = rename_constraints_partitioned_class (ctemplate, old_name, new_name, element_type);
2925  if (error != NO_ERROR)
2926  {
2927  goto error_exit;
2928  }
2929  }
2930 
2931  error = rename_constraint (ctemplate, sm_cons, old_name, new_name, element_type);
2932  if (error != NO_ERROR)
2933  {
2934  goto error_exit;
2935  }
2936 
2937 end:
2938  if (sm_cons)
2939  {
2941  }
2942 
2943  return error;
2944 
2945  /* in order to show explicitly the error */
2946 error_exit:
2947  goto end;
2948 }
2949 #endif /* ENABLE_RENAME_CONSTRAINT */
2950 
2951 /*
2952  * change_constraints_comment_partitioned_class ()
2953  * - This function changes constraints comment in sub-classes(partition classes).
2954  * return: NO_ERROR on success, non-zero for ERROR
2955  * obj(in): database object of the super class (partition class)
2956  * index_name(in): then name of constraint
2957  * comment(in): the comment of constraint
2958  */
2959 static int
2960 change_constraints_comment_partitioned_class (MOP obj, const char *index_name, const char *comment)
2961 {
2962  int error = NO_ERROR;
2963  int i, is_partition = 0;
2964  MOP *sub_partitions = NULL;
2965  SM_TEMPLATE *ctemplate = NULL;
2966  SM_CLASS_CONSTRAINT *cons;
2967 
2968  error = sm_partitioned_class_type (obj, &is_partition, NULL, &sub_partitions);
2969  if (error != NO_ERROR)
2970  {
2971  goto error_exit;
2972  }
2973 
2974  if (is_partition == DB_PARTITION_CLASS)
2975  {
2977  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
2978  goto error_exit;
2979  }
2980  else if (is_partition == DB_NOT_PARTITIONED_CLASS)
2981  {
2982  goto end;
2983  }
2984 
2985  assert (is_partition == DB_PARTITIONED_CLASS);
2986 
2987  for (i = 0; sub_partitions[i]; i++)
2988  {
2989  ctemplate = smt_edit_class_mop (sub_partitions[i], AU_INDEX);
2990  if (ctemplate == NULL)
2991  {
2992  error = er_errid ();
2993  assert (error != NO_ERROR);
2994  goto error_exit;
2995  }
2996 
2997  cons = smt_find_constraint (ctemplate, index_name);
2998  if (cons == NULL)
2999  {
3000  ASSERT_ERROR_AND_SET (error);
3001  goto error_exit;
3002  }
3003 
3004  error = classobj_change_constraint_comment (ctemplate->properties, cons, comment);
3005  if (error != NO_ERROR)
3006  {
3007  goto error_exit;
3008  }
3009 
3010  /* classobj_free_template() is included in sm_update_class() */
3011  error = sm_update_class (ctemplate, NULL);
3012  if (error != NO_ERROR)
3013  {
3014  /* Even though sm_update() did not return NO_ERROR, ctemplate is already freed */
3015  ctemplate = NULL;
3016  goto error_exit;
3017  }
3018  }
3019 
3020 end:
3021  if (sub_partitions != NULL)
3022  {
3023  free_and_init (sub_partitions);
3024  }
3025  return error;
3026 
3027 error_exit:
3028  if (ctemplate != NULL)
3029  {
3030  /* smt_quit() always returns NO_ERROR */
3031  smt_quit (ctemplate);
3032  }
3033  goto end;
3034 }
3035 
3036 /*
3037  * smt_change_constraint_comment() - This function change comment of index/constraints in sm_template.
3038  * return: NO_ERROR on success, non-zero for ERROR
3039  * ctemplate(in): sm_template of the class
3040  * index_name(in): the name of constraint
3041  * comment(in): new comment of constraint
3042  */
3043 int
3044 smt_change_constraint_comment (SM_TEMPLATE * ctemplate, const char *index_name, const char *comment)
3045 {
3046  SM_CLASS_CONSTRAINT *cons = NULL;
3047  int error = NO_ERROR;
3048 
3049  assert (ctemplate != NULL && ctemplate->op != NULL);
3050 
3051  cons = smt_find_constraint (ctemplate, index_name);
3052  if (cons == NULL)
3053  {
3054  ASSERT_ERROR_AND_SET (error);
3055  return error;
3056  }
3057 
3058  error = change_constraints_comment_partitioned_class (ctemplate->op, index_name, comment);
3059  if (error != NO_ERROR)
3060  {
3061  goto error_exit;
3062  }
3063 
3064  error = classobj_change_constraint_comment (ctemplate->properties, cons, comment);
3065  if (error != NO_ERROR)
3066  {
3067  goto error_exit;
3068  }
3069 
3070 end:
3071  return error;
3072 
3073  /* in order to show explicitly the error */
3074 error_exit:
3075  goto end;
3076 }
3077 
3078 /* TEMPLATE DELETION FUNCTIONS */
3079 
3080 /*
3081  * check_alias_delete() - Work function for smt_delete_any.
3082  * Here when a component of the given name could not be found.
3083  * Check to see if there are any alias resolutions with the
3084  * name and if so, remove the resolution. Since an alias cannot have
3085  * the same name as a normal component, this means that smt_delete_any
3086  * can be used to remove resolution aliases as well.
3087  * The error code will already have been set here, if an alias is found,
3088  * set it back to NO_ERROR.
3089  * return: NO_ERROR on success, non-zero for ERROR
3090  * template(in): schema template
3091  * name(in): component name
3092  * name_space(in): class or instance name_space identifier
3093  * error(in): current error code (may be changed to NO_ERROR)
3094  */
3095 
3096 static int
3097 check_alias_delete (SM_TEMPLATE * template_, const char *name, SM_NAME_SPACE name_space, int error)
3098 {
3099  SM_RESOLUTION **reslist, *res;
3100 
3101  if (name_space == ID_INSTANCE)
3102  {
3103  reslist = &template_->resolutions;
3104  }
3105  else
3106  {
3107  reslist = &template_->class_resolutions;
3108  }
3109 
3110  res = find_alias (*reslist, name, name_space);
3111  if (res != NULL)
3112  {
3113  WS_LIST_REMOVE (reslist, res);
3115  /* reset the error since we'll drop the alias instead */
3116  error = NO_ERROR;
3117  }
3118 
3119  return error;
3120 }
3121 
3122 /*
3123  * smt_delete_any() - This is the primary function for deletion of all types of
3124  * attributes, methods and resolution aliases from a template.
3125  * It can be used to delete specific component types by passing
3126  * the specific name_space identifiers (ID_ATTRIBUTE etc.) or it can
3127  * be used for the broader namespaces (ID_INSTANCE, ID_CLASS) to delete
3128  * any sort of component. The attribute that is a member of primary key
3129  * can't be deleted.
3130  * return: NO_ERROR on success, non-zero for ERROR
3131  * template(in/out): schema template
3132  * name(in): component name
3133  * name_space(in): component name_space identifier
3134  */
3135 
3136 int
3137 smt_delete_any (SM_TEMPLATE * template_, const char *name, SM_NAME_SPACE name_space)
3138 {
3139  int error = NO_ERROR;
3140  SM_ATTRIBUTE *att;
3141  SM_METHOD *method;
3142  SM_COMPONENT *thing;
3143 
3144  switch (name_space)
3145  {
3146  case ID_ATTRIBUTE:
3147  error = smt_find_attribute (template_, name, false, &att);
3148  if (error == NO_ERROR)
3149  {
3151  {
3152  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, name);
3153  }
3154  else
3155  {
3156  if (att->flags & SM_ATTFLAG_PRIMARY_KEY)
3157  {
3159  }
3160  else
3161  {
3162  WS_LIST_REMOVE (&template_->attributes, att);
3164  }
3165  }
3166  }
3167  else
3168  {
3169  error = check_alias_delete (template_, name, ID_INSTANCE, error);
3170  }
3171  break;
3172 
3173  case ID_SHARED_ATTRIBUTE:
3174  error = smt_find_attribute (template_, name, false, &att);
3175  if (error == NO_ERROR)
3176  {
3178  {
3179  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, name);
3180  }
3181  else
3182  {
3183  WS_LIST_REMOVE (&template_->attributes, att);
3185  }
3186  }
3187  else
3188  {
3189  error = check_alias_delete (template_, name, ID_INSTANCE, error);
3190  }
3191  break;
3192 
3193  case ID_CLASS_ATTRIBUTE:
3194  error = smt_find_attribute (template_, name, true, &att);
3195  if (error == NO_ERROR)
3196  {
3197  WS_LIST_REMOVE (&template_->class_attributes, att);
3199  }
3200  else
3201  {
3202  error = check_alias_delete (template_, name, ID_CLASS, error);
3203  }
3204  break;
3205 
3206  case ID_METHOD:
3207  error = find_method (template_, name, false, &method);
3208  if (error == NO_ERROR)
3209  {
3210  WS_LIST_REMOVE (&template_->methods, method);
3211  classobj_free_method (method);
3212  }
3213  else
3214  {
3215  error = check_alias_delete (template_, name, ID_INSTANCE, error);
3216  }
3217  break;
3218 
3219  case ID_CLASS_METHOD:
3220  error = find_method (template_, name, true, &method);
3221  if (error == NO_ERROR)
3222  {
3223  WS_LIST_REMOVE (&template_->class_methods, method);
3224  classobj_free_method (method);
3225  }
3226  else
3227  {
3228  error = check_alias_delete (template_, name, ID_CLASS, error);
3229  }
3230  break;
3231 
3232  case ID_INSTANCE:
3233  /* look at both attributes and methods for a name match */
3234  error = find_any (template_, name, false, &thing);
3235  if (error == NO_ERROR)
3236  {
3237  if (thing->name_space == ID_METHOD)
3238  {
3239  method = (SM_METHOD *) thing;
3240  WS_LIST_REMOVE (&template_->methods, method);
3241  classobj_free_method (method);
3242  }
3243  else if (thing->name_space == ID_ATTRIBUTE || thing->name_space == ID_SHARED_ATTRIBUTE)
3244  {
3245  att = (SM_ATTRIBUTE *) thing;
3246  if (att->flags & SM_ATTFLAG_PRIMARY_KEY)
3247  {
3249  }
3250  else
3251  {
3252  WS_LIST_REMOVE (&template_->attributes, att);
3254  }
3255  }
3256  }
3257  else
3258  {
3259  error = check_alias_delete (template_, name, ID_INSTANCE, error);
3260  }
3261  break;
3262 
3263  case ID_CLASS:
3264  /* look at both attributes and methods for a name match */
3265  error = find_any (template_, name, true, &thing);
3266  if (error == NO_ERROR)
3267  {
3268  if (thing->name_space == ID_CLASS_METHOD)
3269  {
3270  method = (SM_METHOD *) thing;
3271  WS_LIST_REMOVE (&template_->class_methods, method);
3272  classobj_free_method (method);
3273  }
3274  else if (thing->name_space == ID_CLASS_ATTRIBUTE)
3275  {
3276  att = (SM_ATTRIBUTE *) thing;
3277  WS_LIST_REMOVE (&template_->class_attributes, att);
3279  }
3280  }
3281  else
3282  {
3283  error = check_alias_delete (template_, name, ID_CLASS, error);
3284  }
3285  break;
3286 
3287  default:
3289  break;
3290  }
3291 
3292  return error;
3293 }
3294 
3295 #if defined(ENABLE_UNUSED_FUNCTION)
3296 /*
3297  * smt_delete()
3298  * smt_class_delete() - These are type specific deletion functions.
3299  * They all call smt_delete_any with appropriate arguments.
3300  * return: NO_ERROR on success, non-zero for ERROR
3301  * template(in/out): schema template
3302  * name(in): component name
3303  */
3304 
3305 int
3306 smt_delete (SM_TEMPLATE * template_, const char *name)
3307 {
3308  return (smt_delete_any (template_, name, ID_INSTANCE));
3309 }
3310 
3311 int
3312 smt_class_delete (SM_TEMPLATE * template_, const char *name)
3313 {
3314  return (smt_delete_any (template_, name, ID_CLASS));
3315 }
3316 #endif /* ENABLE_UNUSED_FUNCTION */
3317 
3318 /* TEMPLATE SUPERCLASS FUNCTIONS */
3319 /*
3320  * smt_add_super() - Adds a super class to the class being edited.
3321  * The checking for complex hierarchy cycles is not done here but deferred
3322  * until sm_update_class. This is because the check may be fairly
3323  * complex and require a lot of locks.
3324  * return: NO_ERROR on success, non-zero for ERROR
3325  * template(in/out): schema template
3326  * super_class(in): super class to add
3327  */
3328 
3329 int
3330 smt_add_super (SM_TEMPLATE * template_, MOP super_class)
3331 {
3332  int error = NO_ERROR;
3333 
3334  if (ml_find (template_->inheritance, super_class))
3335  {
3337  }
3338  else if ((template_->op != NULL) && (template_->op == super_class))
3339  {
3341  }
3342  else
3343  {
3344  if (template_->class_type == SM_CLASS_CT)
3345  {
3346  int is_class = 0;
3347 
3348  is_class = db_is_class (super_class);
3349  if (is_class < 0)
3350  {
3351  error = is_class;
3352  }
3353  else if (!is_class)
3354  {
3355  ERROR2 (error, ER_SM_INCOMPATIBLE_SUPER_CLASS, db_get_class_name (super_class), template_->name);
3356  }
3357  }
3358  if (error == NO_ERROR)
3359  {
3360  if (template_->class_type == SM_VCLASS_CT)
3361  {
3362  int is_vclass = 0;
3363 
3364  is_vclass = db_is_vclass (super_class);
3365  if (is_vclass < 0)
3366  {
3367  error = is_vclass;
3368  }
3369  if (!is_vclass)
3370  {
3371  ERROR2 (error, ER_SM_INCOMPATIBLE_SUPER_CLASS, db_get_class_name (super_class), template_->name);
3372  }
3373  }
3374  if (error == NO_ERROR)
3375  {
3376  error = ml_append (&template_->inheritance, super_class, NULL);
3377  }
3378  }
3379  }
3380 
3381  return error;
3382 }
3383 
3384 /*
3385  * smt_delete_super() - Remove a super class from the class being edited.
3386  * The class loses the definitions of the superclass and any super classes
3387  * of the dropped superclass.
3388  * return: NO_ERROR on success, non-zero for ERROR
3389  * template(in/out): schema template
3390  * super_class(in): super class to drop
3391  */
3392 
3393 int
3394 smt_delete_super (SM_TEMPLATE * template_, MOP super_class)
3395 {
3396  int error = NO_ERROR;
3397 
3398  if (!ml_remove (&template_->inheritance, super_class))
3399  {
3400  ERROR0 (error, ER_SM_SUPER_NOT_FOUND);
3401  }
3402 
3403  return error;
3404 }
3405 
3406 /*
3407  * smt_delete_super_connect() - This removes a super class from the class being
3408  * edited but in addition automatically connects any super classes of
3409  * the dropped class to the class being edited.
3410  * return: NO_ERROR on success, non-zero for ERROR
3411  * template(in/out): schema template
3412  * super_class(in): super class to drop
3413  */
3414 
3415 int
3416 smt_delete_super_connect (SM_TEMPLATE * template_, MOP super_class)
3417 {
3418  int error = NO_ERROR;
3419  SM_CLASS *class_;
3420  DB_OBJLIST *s;
3421 
3422  if (!ml_remove (&template_->inheritance, super_class))
3423  {
3424  ERROR0 (error, ER_SM_SUPER_NOT_FOUND);
3425  }
3426  else
3427  {
3428  /* connect all of the super supers and install its resolutions */
3429  if ((error = au_fetch_class (super_class, &class_, AU_FETCH_WRITE, AU_SELECT)) == NO_ERROR)
3430  {
3431  /* add super supers */
3432  for (s = class_->inheritance; s != NULL && !error; s = s->next)
3433  {
3434  error = ml_append (&template_->inheritance, s->op, NULL);
3435  }
3436 
3437  /* It is unclear what the semantics of inheriting resolutions are force the user to respecify resolutions for
3438  * conflicts on super supers */
3439  }
3440  }
3441 
3442  return error;
3443 }
3444 
3445 /* TEMPLATE METHOD FILE FUNCTIONS */
3446 
3447 /*
3448  * smt_add_method_file() - Adds a method file name to a template.
3449  * The name must be a valid operating system path name and will be
3450  * passed to the "ld" function by the dymanic linker.
3451  * return: NO_ERROR on success, non-zero for ERROR
3452  * template(in/out): schema template
3453  * filename(in): method file name
3454  */
3455 
3456 int
3457 smt_add_method_file (SM_TEMPLATE * template_, const char *filename)
3458 {
3459  int error = NO_ERROR;
3460  SM_METHOD_FILE *mfile;
3461 
3462  /* should be detecting use of an inherited file and return an error ! */
3463 
3464  /* method file names are case sensitive */
3465  if (NLIST_FIND (template_->method_files, filename) == NULL)
3466  {
3467  mfile = classobj_make_method_file (filename);
3468  if (mfile == NULL)
3469  {
3470  assert (er_errid () != NO_ERROR);
3471  return er_errid ();
3472  }
3473  mfile->class_mop = template_->op;
3474  WS_LIST_APPEND (&template_->method_files, mfile);
3475  }
3476 
3477  return error;
3478 }
3479 
3480 /*
3481  * smt_reset_method_files() - Clear the method file list of a template.
3482  * Useful if the method file list is to be completely re-defined.
3483  * return: NO_ERROR on success, non-zero for ERROR
3484  * template(in/out): schema template
3485  */
3486 
3487 int
3489 {
3490  int error = NO_ERROR;
3491 
3493  template_->method_files = NULL;
3494 
3495  return error;
3496 }
3497 
3498 /*
3499  * smt_drop_method_file() - Removes a method file from a template.
3500  * return: NO_ERROR on success, non-zero for ERROR
3501  * template(in/out): schema template
3502  * name(in): method file name
3503  */
3504 
3505 int
3506 smt_drop_method_file (SM_TEMPLATE * template_, const char *name)
3507 {
3508  int error = NO_ERROR;
3509  SM_METHOD_FILE *file, *prev, *found;
3510 
3511  for (file = template_->method_files, prev = NULL, found = NULL; file != NULL && found == NULL; file = file->next)
3512  {
3513  if (strcmp (file->name, name) == 0)
3514  {
3515  found = file;
3516  }
3517  else
3518  {
3519  prev = file;
3520  }
3521  }
3522 
3523  if (found == NULL)
3524  {
3526  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, name);
3527  }
3528  else
3529  {
3530  if (prev == NULL)
3531  {
3532  template_->method_files = found->next;
3533  }
3534  else
3535  {
3536  prev->next = found->next;
3537  }
3538  classobj_free_method_file (found);
3539  }
3540 
3541  return error;
3542 }
3543 
3544 /*
3545  * smt_rename_method_file() - Drops the old file name and adds new in its place
3546  * return: NO_ERROR on success, non-zero for ERROR
3547  * template(in/out): schema template
3548  * old_name(in): old method file name
3549  * new_name(in): new method file name
3550  */
3551 
3552 int
3553 smt_rename_method_file (SM_TEMPLATE * template_, const char *old_name, const char *new_name)
3554 {
3555  int error = NO_ERROR;
3556  SM_METHOD_FILE *file, *prev, *found;
3557 
3558  for (file = template_->method_files, prev = NULL, found = NULL; file != NULL && found == NULL; file = file->next)
3559  {
3560  if (strcmp (file->name, old_name) == 0)
3561  {
3562  found = file;
3563  }
3564  else
3565  {
3566  prev = file;
3567  }
3568  }
3569 
3570  if (found == NULL)
3571  {
3573  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, old_name);
3574  }
3575  else
3576  {
3577  ws_free_string (found->name);
3578  found->name = ws_copy_string (new_name);
3579  if (found->name == NULL)
3580  {
3581  assert (er_errid () != NO_ERROR);
3582  error = er_errid ();
3583  }
3584  }
3585 
3586  return error;
3587 }
3588 
3589 /*
3590  * smt_set_loader_commands() - This is used to add a "command" string for the
3591  * dynamic loader. This is passed in the command line to the call to "ld".
3592  * It is intended to hold things like common library lists or other
3593  * linker flags necessary for linking with the method files for a
3594  * class.
3595  * return: NO_ERROR on success, non-zero for ERROR
3596  * template(in/out): schema template
3597  * commands(in): string of commands to the dynamic loader
3598  */
3599 
3600 int
3601 smt_set_loader_commands (SM_TEMPLATE * template_, const char *commands)
3602 {
3603  ws_free_string (template_->loader_commands);
3604  template_->loader_commands = ws_copy_string (commands);
3605 
3606  return NO_ERROR;
3607 }
3608 
3609 /* TEMPLATE RESOLUTION FUNCTIONS */
3610 /*
3611  * check_resolution_name() - Work function for add_resolution, could be used
3612  * in other places as well. This makes sure that a class has an attribute
3613  * or method with the given name.
3614  * return: non-zero if name was found
3615  * classmop(in): class that must have named thing
3616  * name(in): the name to look for
3617  * class_name(in): identifies class names or instance names
3618  */
3619 
3620 static int
3621 check_resolution_name (MOP classmop, const char *name, int class_name)
3622 {
3623  SM_CLASS *class_;
3624  SM_COMPONENT *thing;
3625 
3626  thing = NULL;
3627  if (au_fetch_class (classmop, &class_, AU_FETCH_READ, AU_SELECT) == NO_ERROR)
3628  {
3629  thing = classobj_find_component (class_, name, class_name);
3630  }
3631 
3632  return ((thing == NULL) ? 0 : 1);
3633 }
3634 
3635 /*
3636  * check_local_definition() - Work function for add_resolution. Check to see
3637  * if there are any locally defined components (attributes or methods)
3638  * that must override the use of any resolution specifiers that reference
3639  * an inherited component with the same name.
3640  * e.g. you can't say "inherit x from foo"
3641  * if there is already a definition for attribute x in subclass being
3642  * editined. Local definitions always take precidence over inherited
3643  * definitions.
3644  * return: NO_ERROR on success, non-zero for ERROR
3645  * template(in): class definition template
3646  * name(in): component name
3647  * alias(in): optional alias name
3648  * namespace(in): component name_space
3649  */
3650 
3651 static int
3652 check_local_definition (SM_TEMPLATE * template_, const char *name, const char *alias, SM_NAME_SPACE name_space)
3653 {
3654  int error = NO_ERROR;
3655  SM_COMPONENT *comp;
3656  SM_NAME_SPACE rspace;
3657  int class_stuff;
3658 
3659  rspace = sm_resolution_space (name_space);
3660  class_stuff = (rspace == ID_CLASS) ? 1 : 0;
3661 
3662  if (alias == NULL)
3663  {
3664  comp = find_component (template_, name, class_stuff);
3665  if (comp != NULL)
3666  {
3667  /* Can't request inheritance of "name", it is defined locally in the class */
3669  return error;
3670  }
3671  }
3672  else
3673  {
3674  comp = find_component (template_, alias, class_stuff);
3675  if (comp != NULL)
3676  {
3677  /* Can't use "alias" as an alias for inherited component "name", there is already a locally defined component
3678  * with that name */
3679  ERROR2 (error, ER_SM_ALIAS_COMPONENT_EXISTS, alias, name);
3680  return error;
3681  }
3682  }
3683 
3684  return NO_ERROR;
3685 }
3686 
3687 /*
3688  * add_resolution() - Add a resolution specifier to a template.
3689  * return: NO_ERROR on success, non-zero for ERROR
3690  * template(in/out): schema template
3691  * super_class(in): super_class with conflicting component
3692  * name(in): name of conflicting component
3693  * alias(in): optional alias name (can be NULL)
3694  * namespace(in): class or instance name_space identifier
3695  */
3696 
3697 static int
3698 add_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, const char *alias, SM_NAME_SPACE name_space)
3699 {
3700  int error = NO_ERROR;
3701  SM_RESOLUTION **reslist, *res, *chosen, *prev_alias;
3702  char realname[SM_MAX_IDENTIFIER_LENGTH];
3703  char realalias[SM_MAX_IDENTIFIER_LENGTH];
3704 
3705  if (name == NULL)
3706  {
3708  return error;
3709  }
3710 
3711  /* hack, if the alias name is the same as the component name, get rid of it. The system won't allow aliases that
3712  * have the same name as an inherited component (i.e. you can't shadow with an alias). */
3713  if (alias != NULL && SM_COMPARE_NAMES (name, alias) == 0)
3714  {
3715  alias = NULL;
3716  }
3717 
3718  if (alias != NULL && !sm_check_name (alias))
3719  {
3720  assert (er_errid () != NO_ERROR);
3721  error = er_errid ();
3722  }
3723  else
3724  {
3725  sm_downcase_name (name, realname, SM_MAX_IDENTIFIER_LENGTH);
3726  name = realname;
3727 
3728  if (alias != NULL)
3729  {
3730  sm_downcase_name (alias, realalias, SM_MAX_IDENTIFIER_LENGTH);
3731  alias = realalias;
3732  }
3733 
3734  error = check_local_definition (template_, name, alias, name_space);
3735  if (error == NO_ERROR)
3736  {
3737 
3738  /* make sure the super class actually has a component with this name */
3739  if (!check_resolution_name (super_class, name, (name_space == ID_CLASS) ? 1 : 0))
3740  {
3741  /* need "attribute or method" not found */
3742  ERROR1 (error, ER_SM_ATTRIBUTE_NOT_FOUND, name);
3743  }
3744  else
3745  {
3746  if (name_space == ID_INSTANCE)
3747  {
3748  reslist = &template_->resolutions;
3749  }
3750  else
3751  {
3752  reslist = &template_->class_resolutions;
3753  }
3754 
3755  /* look for an explicit resolution from a this or a different class, place this in "chosen". also look
3756  * for an already existing alias on this component */
3757  chosen = NULL;
3758  prev_alias = NULL;
3759  for (res = *reslist; res != NULL; res = res->next)
3760  {
3761  if (SM_COMPARE_NAMES (res->name, name) == 0)
3762  {
3763  if (res->alias == NULL)
3764  {
3765  chosen = res;
3766  }
3767  else if (res->class_mop == super_class)
3768  {
3769  prev_alias = res;
3770  }
3771  }
3772  }
3773 
3774  if (alias != NULL)
3775  {
3776  /* we're trying to set up an alias */
3777  if (chosen != NULL && chosen->class_mop == super_class)
3778  {
3779  /* a resolution on this class previously existed without an alias, give it the specified alias */
3780  chosen->alias = ws_copy_string (alias);
3781  if (chosen->alias == NULL)
3782  {
3783  assert (er_errid () != NO_ERROR);
3784  error = er_errid ();
3785  }
3786  }
3787  else if (prev_alias != NULL)
3788  {
3789  /* a resolution on this class previously existed with an alias, replace the old alias with the
3790  * new one */
3791  db_ws_free ((char *) prev_alias->alias);
3792  prev_alias->alias = ws_copy_string (alias);
3793  if (prev_alias->alias == NULL)
3794  {
3795  assert (er_errid () != NO_ERROR);
3796  error = er_errid ();
3797  }
3798  }
3799  else
3800  {
3801  SM_RESOLUTION *res;
3802  res = classobj_make_resolution (super_class, name, alias, name_space);
3803  if (res == NULL)
3804  {
3805  assert (er_errid () != NO_ERROR);
3806  error = er_errid ();
3807  }
3808  /* we need to add a new entry with the alias */
3809  WS_LIST_APPEND (reslist, res);
3810  }
3811  }
3812  else
3813  {
3814  /* we're trying to make a specific attribute selection */
3815  if (chosen == NULL)
3816  {
3817  if (prev_alias == NULL)
3818  {
3819  SM_RESOLUTION *res;
3820  res = classobj_make_resolution (super_class, name, alias, name_space);
3821  if (res == NULL)
3822  {
3823  assert (er_errid () != NO_ERROR);
3824  error = er_errid ();
3825  }
3826  /* we need to add a new entry */
3827  WS_LIST_APPEND (reslist, res);
3828  }
3829  else
3830  {
3831  /* remove the old alias */
3832  db_ws_free ((char *) prev_alias->alias);
3833  prev_alias->alias = NULL;
3834  }
3835  }
3836  else
3837  {
3838  /* change the chosen class */
3839  chosen->class_mop = super_class;
3840  if (prev_alias != NULL)
3841  {
3842  /* free the old alias */
3843  WS_LIST_REMOVE (reslist, prev_alias);
3844  classobj_free_resolution (prev_alias);
3845  }
3846  }
3847  }
3848  }
3849  }
3850  }
3851 
3852  return error;
3853 }
3854 
3855 /*
3856  * delete_resolution() - Removes a resolution from a template that matches
3857  * the supplied parameters.
3858  * return: NO_ERROR on success, non-zero for ERROR
3859  * template(in/out): schema template
3860  * super_class(in): class with resolution
3861  * name(in): component name of resolution
3862  * namespace(in): class or instance name_space identifier
3863  */
3864 
3865 static int
3866 delete_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, SM_NAME_SPACE name_space)
3867 {
3868  int error = NO_ERROR;
3869  SM_RESOLUTION **reslist, *res;
3870 
3871  if (name_space == ID_INSTANCE)
3872  {
3873  reslist = &template_->resolutions;
3874  }
3875  else
3876  {
3877  reslist = &template_->class_resolutions;
3878  }
3879 
3880  res = classobj_find_resolution (*reslist, super_class, name, name_space);
3881  if (res == NULL)
3882  {
3883  ERROR1 (error, ER_SM_RESOLUTION_NOT_FOUND, name);
3884  }
3885  else
3886  {
3887  WS_LIST_REMOVE (reslist, res);
3889  }
3890  return (error);
3891 }
3892 
3893 /*
3894  * smt_add_resolution()
3895  * smt_add_class_resolution() - Add a resolution to a template.
3896  * These are name_space specific functions that call add_resolution
3897  * to do the actual work.
3898  * return: NO_ERROR on success, non-zero for ERROR
3899  * template(in/out): schema template
3900  * super_class(in): super class with conflicting component
3901  * name(in): name of conflicting component
3902  * alias(in): optional alias name (can be NULL)
3903  */
3904 
3905 int
3906 smt_add_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, const char *alias)
3907 {
3908  return (add_resolution (template_, super_class, name, alias, ID_INSTANCE));
3909 }
3910 
3911 int
3912 smt_add_class_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name, const char *alias)
3913 {
3914  return (add_resolution (template_, super_class, name, alias, ID_CLASS));
3915 }
3916 
3917 /*
3918  * smt_delete_resolution()
3919  * smt_delete_class_resolution() - Removes the resolution specifier for a
3920  * component of a particular super class.
3921  * These are name_space specific functions that call delete_resolution
3922  * to do the actual work.
3923  * return: NO_ERROR on success, non-zero for ERROR
3924  * template(in/out): schema template
3925  * super_class(in): super class with conflicting component
3926  * name(in): name of conflicting component
3927  */
3928 
3929 int
3930 smt_delete_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name)
3931 {
3932  return delete_resolution (template_, super_class, name, ID_INSTANCE);
3933 }
3934 
3935 int
3936 smt_delete_class_resolution (SM_TEMPLATE * template_, MOP super_class, const char *name)
3937 {
3938  return delete_resolution (template_, super_class, name, ID_CLASS);
3939 }
3940 
3941 /* TEMPLATE POPULATE FUNCTIONS */
3942 /*
3943  * smt_add_query_spec() - Adds a query specification to a template.
3944  * return: NO_ERROR on success, non-zero for ERROR
3945  * template(in/out): schema template
3946  * specification(in): query specification
3947  */
3948 
3949 int
3950 smt_add_query_spec (SM_TEMPLATE * template_, const char *specification)
3951 {
3952  int error = NO_ERROR;
3953  SM_QUERY_SPEC *query_spec;
3954  SM_CLASS_TYPE ct;
3955 
3956  query_spec = classobj_make_query_spec (specification);
3957 
3958  if (query_spec == NULL)
3959  {
3960  assert (er_errid () != NO_ERROR);
3961  error = er_errid ();
3962  }
3963  else
3964  {
3965  ct = template_->class_type;
3966  if (ct == SM_VCLASS_CT)
3967  {
3968  WS_LIST_APPEND (&template_->query_spec, query_spec);
3969  }
3970  else
3971  {
3972  db_ws_free (query_spec);
3973  error = ER_SM_INVALID_CLASS;
3975  }
3976  }
3977 
3978  return error;
3979 }
3980 
3981 /*
3982  * smt_reset_query_spec() - Clears the query_spec list of a template.
3983  * return: NO_ERROR on success, non-zero for ERROR
3984  * template(in/out): schema template
3985  */
3986 
3987 int
3989 {
3990  int error = NO_ERROR;
3991 
3993  template_->query_spec = NULL;
3994 
3995  return error;
3996 }
3997 
3998 /*
3999  * smt_drop_query_spec() - Removes a query_spec from a template.
4000  * return: NO_ERROR on success, non-zero for ERROR
4001  * def(in/out): schema template
4002  * index(in): 1 relative index of query_spec specification to drop
4003  */
4004 
4005 int
4007 {
4008  int error = NO_ERROR;
4009  SM_QUERY_SPEC *file, *prev, *found;
4010  int i;
4011  char indexname[20];
4012 
4013  for (file = def->query_spec, prev = NULL, found = NULL, i = 1; file != NULL && found == NULL; file = file->next, i++)
4014  {
4015  if (index == i)
4016  {
4017  found = file;
4018  }
4019  else
4020  {
4021  prev = file;
4022  }
4023  }
4024 
4025  if (found == NULL)
4026  {
4028  sprintf (indexname, "%d", index);
4029  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, indexname);
4030  }
4031  else
4032  {
4033  if (prev == NULL)
4034  {
4035  def->query_spec = found->next;
4036  }
4037  else
4038  {
4039  prev->next = found->next;
4040  }
4041  classobj_free_query_spec (found);
4042  }
4043 
4044  return error;
4045 }
4046 
4047 /* VIRTUAL SCHEMA OPERATION TEMPLATE FUNCTIONS */
4048 /*
4049  * smt_def_typed_class() - Begin the definition of a new virtual class.
4050  * Creates an empty template. The class name is not registered at this
4051  * time. It will be registered during sm_update_class
4052  * return: template
4053  * name(in):
4054  * ct(in):
4055  */
4056 
4057 SM_TEMPLATE *
4058 smt_def_typed_class (const char *name, SM_CLASS_TYPE ct)
4059 {
4060  return def_class_internal (name, ct);
4061 }
4062 
4063 /*
4064  * smt_get_class_type() - Return the type of a class template
4065  * return: class type
4066  * template(in):
4067  */
4068 
4071 {
4072  return template_->class_type;
4073 }
4074 
4075 /*
4076  * smt_get_class_type() - Convenience function to return the type of class,
4077  * that is whether, a virtual class, component class or a view
4078  * return: class type
4079  * class(in):
4080  */
4081 
4084 {
4085  return class_->class_type;
4086 }
4087 
4088 /*
4089  * smt_change_query_spec()
4090  * return: NO_ERROR on success, non-zero for ERROR
4091  * def(in/out):
4092  * query(in):
4093  * index(in):
4094  */
4095 
4096 int
4097 smt_change_query_spec (SM_TEMPLATE * def, const char *query, const int index)
4098 {
4099  int error = NO_ERROR;
4100  SM_QUERY_SPEC *file, *prev, *found;
4101  int i;
4102  char indexname[20];
4103 
4104  for (file = def->query_spec, prev = NULL, found = NULL, i = 1; file != NULL && found == NULL; file = file->next, i++)
4105  {
4106  if (index == i)
4107  {
4108  found = file;
4109  }
4110  else
4111  {
4112  prev = file;
4113  }
4114  }
4115 
4116  if (found == NULL)
4117  {
4119  sprintf (indexname, "%d", index);
4120  er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, indexname);
4121  }
4122  else
4123  {
4124  if (prev == NULL)
4125  {
4126  def->query_spec = classobj_make_query_spec (query);
4127  if (def->query_spec == NULL)
4128  {
4129  assert (er_errid () != NO_ERROR);
4130  return er_errid ();
4131  }
4132  def->query_spec->next = found->next;
4133  }
4134  else
4135  {
4136  prev->next = classobj_make_query_spec (query);
4137  if (prev->next == NULL)
4138  {
4139  assert (er_errid () != NO_ERROR);
4140  return er_errid ();
4141  }
4142  prev->next->next = found->next;
4143  }
4144 
4145  classobj_free_query_spec (found);
4146  }
4147 
4148  return (error);
4149 }
4150 
4151 #if defined(ENABLE_UNUSED_FUNCTION)
4152 /*
4153  * smt_downcase_all_class_info()
4154  * return: none
4155  */
4156 
4157 void
4158 smt_downcase_all_class_info (void)
4159 {
4160  SM_CLASS *class_;
4161  SM_ATTRIBUTE *a;
4162  SM_METHOD *m;
4163  SM_RESOLUTION *r;
4164  LIST_MOPS *lmops;
4165  int c;
4166  char name_buf[SM_MAX_IDENTIFIER_LENGTH];
4167 
4169  if (lmops != NULL)
4170  {
4171 
4172  for (c = 0; c < lmops->num; c++)
4173  {
4174  class_ = (SM_CLASS *) locator_fetch_class (lmops->mops[c], DB_FETCH_WRITE);
4175 
4176  if (class_ == NULL)
4177  {
4178  return;
4179  }
4180 
4181  FOR_ATTRIBUTES (class_->attributes, a) DOWNCASE_NAME (a->header.name, name_buf);
4182 
4183  FOR_ATTRIBUTES (class_->shared, a) DOWNCASE_NAME (a->header.name, name_buf);
4184 
4185  FOR_ATTRIBUTES (class_->class_attributes, a) DOWNCASE_NAME (a->header.name, name_buf);
4186 
4187  FOR_METHODS (class_->methods, m) DOWNCASE_NAME (m->header.name, name_buf);
4188 
4189  FOR_METHODS (class_->class_methods, m) DOWNCASE_NAME (m->header.name, name_buf);
4190 
4191  for (r = class_->resolutions; r != NULL; r = r->next)
4192  {
4193  DOWNCASE_NAME (r->name, name_buf);
4194  DOWNCASE_NAME (r->alias, name_buf);
4195  }
4196  ws_dirty (lmops->mops[c]);
4197  }
4198  locator_free_list_mops (lmops);
4199  }
4200 }
4201 #endif
4202 
4203 /*
4204  * smt_change_attribute() - Changes an attribute of a template (name, domain
4205  * and ordering).
4206  * For class and shared atribute the value is changed according to new
4207  * domain. For normal attribute, the instance values are not changed, only
4208  * the schema modification is performed.
4209  * The new domain may be specified either with a string or a DB_DOMAIN *.
4210  * If new_domain is not NULL, it is used. Otherwise new_domain_string is
4211  * used.
4212  * The attribute ordering may be changed if either the "change_first"
4213  * argument is "true" or "change_after_attribute" is non-null and contains
4214  * the name of an existing attribute.
4215  * If all operations are successful, the changed attribute is returned in
4216  * "found_att".
4217  *
4218  * return: NO_ERROR on success, non-zero for ERROR
4219  * template(in/out): schema template
4220  * name(in): attribute current name
4221  * new_name(in): attribute new name (may be NULL if unchanged)
4222  * new_domain_string(in): new domain name string
4223  * new_domain(in): new domain
4224  * name_space(in): class, share or normal attribute
4225  * change_first(in): the attribute will become the first in the attributes
4226  * list
4227  * change_after_attribute(in): the attribute will be repositioned
4228  * after the attribute with the given name
4229  * found_att(out) : the new attribute if successfully changed
4230  */
4231 static int
4232 smt_change_attribute (SM_TEMPLATE * template_, const char *name, const char *new_name, const char *new_domain_string,
4233  DB_DOMAIN * new_domain, const SM_NAME_SPACE name_space, const bool change_first,
4234  const char *change_after_attribute, SM_ATTRIBUTE ** found_att)
4235 {
4236  int error_code = NO_ERROR;
4237  SM_ATTRIBUTE *att = NULL;
4238  SM_ATTRIBUTE **att_list = NULL;
4239  char real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
4240  char real_new_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
4241  char change_after_attribute_real_name[SM_MAX_IDENTIFIER_LENGTH] = { 0 };
4242 
4243  assert (template_ != NULL);
4244 
4245  if (name_space == ID_CLASS_ATTRIBUTE)
4246  {
4247  att_list = &template_->class_attributes;
4248  }
4249  else
4250  {
4251  att_list = &template_->attributes;
4252  }
4253 
4254  sm_downcase_name (name, real_name, SM_MAX_IDENTIFIER_LENGTH);
4255  name = real_name;
4256  if (!sm_check_name (name))
4257  {
4258  assert (er_errid () != NO_ERROR);
4259  error_code = er_errid ();
4260  goto error_exit;
4261  }
4262 
4263  if (new_name != NULL)
4264  {
4265  sm_downcase_name (new_name, real_new_name, SM_MAX_IDENTIFIER_LENGTH);
4266  new_name = real_new_name;
4267 
4268  if (!sm_check_name (new_name))
4269  {
4270  assert (er_errid () != NO_ERROR);
4271  error_code = er_errid ();
4272  goto error_exit;
4273  }
4274  }
4275 
4276  if (change_after_attribute != NULL)
4277  {
4278  sm_downcase_name (change_after_attribute, change_after_attribute_real_name, SM_MAX_IDENTIFIER_LENGTH);
4279  change_after_attribute = change_after_attribute_real_name;
4280  }
4281 
4282  if (new_name != NULL)
4283  {
4284  error_code = check_namespace (template_, new_name, (name_space == ID_CLASS_ATTRIBUTE) ? true : false);
4285  if (error_code != NO_ERROR)
4286  {
4287  goto error_exit;
4288  }
4289  }
4290 
4291  error_code = get_domain (template_, new_domain_string, &new_domain);
4292  if (error_code != NO_ERROR)
4293  {
4294  goto error_exit;
4295  }
4296 
4297  if (new_domain == NULL)
4298  {
4299  ERROR0 (error_code, ER_SM_INVALID_ARGUMENTS);
4300  goto error_exit;
4301  }
4302 
4303  if (TP_DOMAIN_TYPE (new_domain) == DB_TYPE_OBJECT)
4304  {
4305  error_code = check_domain_class_type (template_, new_domain->class_mop);
4306  if (error_code != NO_ERROR)
4307  {
4308  goto error_exit;
4309  }
4310  }
4311 
4312  error_code = smt_find_attribute (template_, name, (name_space == ID_CLASS_ATTRIBUTE) ? 1 : 0, &att);
4313  if (error_code != NO_ERROR)
4314  {
4315  goto error_exit;
4316  }
4317 
4318  assert (att != NULL);
4319  *found_att = att;
4320 
4321 
4322  if (name_space == ID_CLASS_ATTRIBUTE || name_space == ID_SHARED_ATTRIBUTE)
4323  {
4324  /* change the value according to new domain */
4325  error_code = smt_change_class_shared_attribute_domain (att, new_domain);
4326  if (error_code != NO_ERROR)
4327  {
4328  goto error_exit;
4329  }
4330  }
4331  else
4332  {
4333  assert (name_space == ID_ATTRIBUTE);
4334  }
4335 
4336  att->type = new_domain->type;
4337  att->domain = new_domain;
4338 
4339  /* change name */
4340  if (new_name != NULL)
4341  {
4342  error_code = check_namespace (template_, new_name, (name_space == ID_CLASS_ATTRIBUTE) ? true : false);
4343  if (error_code != NO_ERROR)
4344  {
4345  goto error_exit;
4346  }
4347 
4348  ws_free_string (att->header.name);
4349  att->header.name = ws_copy_string (new_name);
4350  if (att->header.name == NULL)
4351  {
4352  assert (er_errid () != NO_ERROR);
4353  error_code = er_errid ();
4354  goto error_exit;
4355  }
4356  }
4357  /* change order */
4358  if (change_first || change_after_attribute != NULL)
4359  {
4360  error_code = smt_change_attribute_pos_in_list (att_list, att, change_first, change_after_attribute);
4361  }
4362  return error_code;
4363 
4364 error_exit:
4365 
4366  return error_code;
4367 }
4368 
4369 /*
4370  * smt_change_attribute_w_dflt_w_order()
4371  * return: NO_ERROR on success, non-zero for ERROR
4372  * def(in/out):
4373  * name(in): attribute name
4374  * new_name(in): attribute's new name, otherwise NULL
4375  * domain_string(in): domain name string
4376  * domain(in): domain
4377  * name_space(in): class, shared or normal attribute
4378  * new_default_value(in): default value
4379  * new_default_expr(in): default expression
4380  * new_on_update_expr(in): on_update default expression
4381  * change_first(in): the attribute should be added at the beginning of the attributes list
4382  * change_after_attribute(in): the attribute should be added in the attributes list
4383  * after the attribute with the given name
4384  * found_att(out) : the new attribute if successfully changed
4385  */
4386 int
4387 smt_change_attribute_w_dflt_w_order (DB_CTMPL * def, const char *name, const char *new_name,
4388  const char *new_domain_string, DB_DOMAIN * new_domain,
4389  const SM_NAME_SPACE name_space, DB_VALUE * new_default_value,
4390  DB_DEFAULT_EXPR * new_default_expr, DB_DEFAULT_EXPR_TYPE on_update_expr,
4391  const bool change_first, const char *change_after_attribute,
4392  SM_ATTRIBUTE ** found_att)
4393 {
4394  int error = NO_ERROR;
4395  int is_class_attr;
4396  DB_VALUE *orig_value = NULL;
4397  DB_VALUE *new_orig_value = NULL;
4398  TP_DOMAIN_STATUS status;
4399 
4400  *found_att = NULL;
4401  error = smt_change_attribute (def, name, new_name, new_domain_string, new_domain, name_space, change_first,
4402  change_after_attribute, found_att);
4403  if (error != NO_ERROR)
4404  {
4405  return error;
4406  }
4407  if (*found_att == NULL)
4408  {
4409  assert (false);
4410  ERROR1 (error, ER_UNEXPECTED, "Attribute not found.");
4411  return error;
4412  }
4413 
4414  is_class_attr = (name_space == ID_CLASS_ATTRIBUTE);
4415  if (new_default_value != NULL || (new_default_expr != NULL && new_default_expr->default_expr_type != DB_DEFAULT_NONE))
4416  {
4417  assert (((*found_att)->flags & SM_ATTFLAG_NEW) == 0);
4418  error = smt_set_attribute_default (def, ((new_name != NULL) ? new_name : name), is_class_attr, new_default_value,
4419  new_default_expr);
4420  if (error != NO_ERROR)
4421  {
4422  return error;
4423  }
4424  }
4425 
4426  error = smt_set_attribute_on_update (def, ((new_name != NULL) ? new_name : name), is_class_attr, on_update_expr);
4427  if (error != NO_ERROR)
4428  {
4429  return error;
4430  }
4431 
4432  /* change original default : continue only for normal attributes */
4433  if (name_space == ID_CLASS_ATTRIBUTE || name_space == ID_SHARED_ATTRIBUTE)
4434  {
4435  assert (error == NO_ERROR);
4436  return error;
4437  }
4438 
4439  assert (name_space == ID_ATTRIBUTE);
4440 
4441  orig_value = &((*found_att)->default_value.original_value);
4442  if (DB_IS_NULL (orig_value))
4443  {
4444  /* the attribute has not set a default original value, so need to continue */
4445  assert (error == NO_ERROR);
4446  return error;
4447  }
4448 
4449  /* adjust original_value domain to new attribute domain */
4450  status = tp_domain_check ((*found_att)->domain, orig_value, TP_EXACT_MATCH);
4451 
4452  if (status == DOMAIN_COMPATIBLE)
4453  {
4454  /* the attribute's current default original value has the same domain, no need to change it */
4455  assert (error == NO_ERROR);
4456  return error;
4457  }
4458 
4459  /* cast the value to new one : explicit cast */
4460  new_orig_value = pr_make_ext_value ();
4461  error = db_value_coerce (orig_value, new_orig_value, (*found_att)->domain);
4462  if (error == NO_ERROR)
4463  {
4464  smt_set_attribute_orig_default_value (*found_att, new_orig_value, new_default_expr);
4465  }
4466  else
4467  {
4468  ERROR1 (error, ER_OBJ_DOMAIN_CONFLICT, (*found_att)->header.name);
4469  }
4470 
4471  pr_free_ext_value (new_orig_value);
4472 
4473  return error;
4474 }
4475 
4476 /*
4477  * smt_change_attribute_pos_in_list()
4478  * return: NO_ERROR on success, non-zero for ERROR
4479  * att_list(in/out): the list to add to
4480  * att(in): the attribute to add
4481  * add_first(in): the attribute should be added at the beginning of the
4482  * attributes list
4483  * add_after_attribute(in): the attribute should be added in the attributes
4484  * list after the attribute with the given name
4485  */
4486 
4487 static int
4488 smt_change_attribute_pos_in_list (SM_ATTRIBUTE ** att_list, SM_ATTRIBUTE * att, const bool change_first,
4489  const char *change_after_attribute)
4490 {
4491  int error_code = NO_ERROR;
4492 
4493  /* we must change the position : either to first or after another element */
4494  assert ((change_first && change_after_attribute == NULL) || (!change_first && change_after_attribute != NULL));
4495 
4496  assert (att != NULL);
4497  assert (att_list != NULL);
4498 
4499  /* first remove the attribute from list */
4500  if (WS_LIST_REMOVE (att_list, att) != 1)
4501  {
4502  error_code = ER_SM_ATTRIBUTE_NOT_FOUND;
4503  return error_code;
4504  }
4505 
4506  att->header.next = NULL;
4507  error_code = smt_add_attribute_to_list (att_list, att, change_first, change_after_attribute);
4508  /* error code already set */
4509  return error_code;
4510 }
4511 
4512 /*
4513  * smt_change_class_shared_attribute_domain() - changes the value domain of a
4514  * shared or class attribute
4515  *
4516  * return: NO_ERROR on success, non-zero for ERROR
4517  * att(in/out): attribute to change
4518  * new_domain(in): new domain of attribute
4519  */
4520 
4521 static int
4523 {
4524  int error = NO_ERROR;
4525  TP_DOMAIN_STATUS status;
4526  int cast_status = NO_ERROR;
4527  DB_VALUE *new_value = NULL;
4528  DB_VALUE *current_value = &(att->default_value.value);
4529 
4530  if (DB_IS_NULL (current_value))
4531  {
4532  /* the attribute has not been set with a value, set only new domain */
4533  assert (error == NO_ERROR);
4534  return error;
4535  }
4536 
4537  /* adjust original_value domain to new attribute domain */
4538  status = tp_domain_check (new_domain, current_value, TP_EXACT_MATCH);
4539 
4540  if (status == DOMAIN_COMPATIBLE)
4541  {
4542  /* the attribute's current value has the same domain, no need to change it */
4543  assert (error == NO_ERROR);
4544  return error;
4545  }
4546 
4547  /* cast the value to new domain : explicit cast */
4548  new_value = pr_make_ext_value ();
4549  cast_status = tp_value_cast (current_value, new_value, new_domain, false);
4550  if (cast_status == DOMAIN_COMPATIBLE)
4551  {
4553  pr_clone_value (new_value, &att->default_value.value);
4554 
4555  att->type = new_domain->type;
4556  att->domain = new_domain;
4557  }
4558  else
4559  {
4560  ERROR1 (error, ER_OBJ_DOMAIN_CONFLICT, att->header.name);
4561  }
4562 
4563  pr_free_ext_value (new_value);
4564 
4565  return error;
4566 }
4567 
4568 /*
4569  * smt_find_owner_of_constraint() - Find the owner mop of the given constraint.
4570  *
4571  * return: MOP on success, NULL for ERROR
4572  * ctemplate(in): class template
4573  * constrant_name(in):
4574  *
4575  * Note: This function requires that the given constraint must exist in the
4576  * class of ctemplate.
4577  */
4578 static MOP
4579 smt_find_owner_of_constraint (SM_TEMPLATE * ctemplate, const char *constraint_name)
4580 {
4581  int error = NO_ERROR;
4582  SM_CLASS_CONSTRAINT *super_cons = NULL;
4583  SM_CLASS_CONSTRAINT *cons = NULL;
4584  DB_OBJLIST *super;
4585  SM_CLASS *class_;
4586 
4587  if (ctemplate->inheritance == NULL)
4588  {
4589  return ctemplate->op;
4590  }
4591 
4592  for (super = ctemplate->inheritance; super != NULL; super = super->next)
4593  {
4594  error = au_fetch_class_force (super->op, &class_, AU_FETCH_READ);
4595  if (error != NO_ERROR)
4596  {
4597  return NULL;
4598  }
4599 
4600  error = classobj_make_class_constraints (class_->properties, class_->attributes, &super_cons);
4601  if (error != NO_ERROR)
4602  {
4603  return NULL;
4604  }
4605 
4606  for (cons = super_cons; cons != NULL; cons = cons->next)
4607  {
4608  if (constraint_name != NULL && cons->name != NULL && SM_COMPARE_NAMES (constraint_name, cons->name) == 0)
4609  {
4610  classobj_free_class_constraints (super_cons);
4611  super_cons = NULL;
4612 
4613  return super->op;
4614  }
4615  }
4616 
4617  if (super_cons != NULL)
4618  {
4619  classobj_free_class_constraints (super_cons);
4620  super_cons = NULL;
4621  }
4622  }
4623 
4624  return ctemplate->op;
4625 }
4626 
4627 static int
4628 change_constraints_status_partitioned_class (MOP obj, const char *index_name, SM_INDEX_STATUS index_status)
4629 {
4630  int error = NO_ERROR;
4631  int i, is_partition = 0;
4632  MOP *sub_partitions = NULL;
4633  SM_TEMPLATE *ctemplate = NULL;
4634  SM_CLASS_CONSTRAINT *cons;
4635 
4636  error = sm_partitioned_class_type (obj, &is_partition, NULL, &sub_partitions);
4637  if (error != NO_ERROR)
4638  {
4639  goto error_exit;
4640  }
4641 
4642  if (is_partition == DB_PARTITION_CLASS)
4643  {
4645  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4646  goto error_exit;
4647  }
4648  else if (is_partition == DB_NOT_PARTITIONED_CLASS)
4649  {
4650  goto end;
4651  }
4652 
4653  assert (is_partition == DB_PARTITIONED_CLASS);
4654 
4655  for (i = 0; sub_partitions[i]; i++)
4656  {
4657  ctemplate = smt_edit_class_mop (sub_partitions[i], AU_INDEX);
4658  if (ctemplate == NULL)
4659  {
4660  ASSERT_ERROR_AND_SET (error);
4661  goto error_exit;
4662  }
4663 
4664  cons = smt_find_constraint (ctemplate, index_name);
4665  if (cons == NULL)
4666  {
4667  ASSERT_ERROR_AND_SET (error);
4668  goto error_exit;
4669  }
4670 
4671  error = classobj_change_constraint_status (ctemplate->properties, cons, index_status);
4672  if (error != NO_ERROR)
4673  {
4674  goto error_exit;
4675  }
4676 
4677  /* classobj_free_template() is included in sm_update_class() */
4678  error = sm_update_class (ctemplate, NULL);
4679  if (error != NO_ERROR)
4680  {
4681  /* Even though sm_update() did not return NO_ERROR, ctemplate is already freed */
4682  ctemplate = NULL;
4683  goto error_exit;
4684  }
4685  }
4686 
4687 end:
4688  if (sub_partitions != NULL)
4689  {
4690  free_and_init (sub_partitions);
4691  }
4692  return error;
4693 
4694 error_exit:
4695  if (ctemplate != NULL)
4696  {
4697  /* smt_quit() always returns NO_ERROR */
4698  smt_quit (ctemplate);
4699  }
4700  goto end;
4701 }
4702 
4703 static SM_CLASS_CONSTRAINT *
4704 smt_find_constraint (SM_TEMPLATE * ctemplate, const char *constraint_name)
4705 {
4706  SM_CLASS_CONSTRAINT *cons_list = NULL, *cons = NULL;
4707  SM_CLASS *class_;
4708 
4709  assert (ctemplate != NULL && ctemplate->op != NULL);
4710 
4711  if (au_fetch_class (ctemplate->op, &class_, AU_FETCH_READ, AU_INDEX) != NO_ERROR)
4712  {
4713  ASSERT_ERROR ();
4714  return NULL;
4715  }
4716 
4717  cons_list = class_->constraints;
4718  if (cons_list == NULL)
4719  {
4721  return NULL;
4722  }
4723 
4724  cons = classobj_find_constraint_by_name (cons_list, constraint_name);
4725  if (cons == NULL)
4726  {
4728  return NULL;
4729  }
4730 
4731  return cons;
4732 }
4733 
4734 static int
4735 smt_is_change_status_allowed (SM_TEMPLATE * ctemplate, const char *index_name)
4736 {
4737  int error = NO_ERROR;
4738  SM_CLASS_CONSTRAINT *constraint;
4739  int partition_type;
4740 
4741  /* Check if this class is a partitioned class. We do not allow index status change on partitions indexes. */
4742  error = sm_partitioned_class_type (ctemplate->op, &partition_type, NULL, NULL);
4743  if (partition_type == DB_PARTITION_CLASS)
4744  {
4746  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 3, sm_ch_name ((MOBJ) ctemplate->current), index_name,
4747  "local index on a partition");
4748  return error;
4749  }
4750 
4751  constraint = smt_find_constraint (ctemplate, index_name);
4752  if (constraint == NULL)
4753  {
4754  ASSERT_ERROR_AND_SET (error);
4755  return error;
4756  }
4757 
4758  switch (constraint->type)
4759  {
4762  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 3, sm_ch_name ((MOBJ) ctemplate->current), constraint->name,
4763  "foreign key");
4764  return error;
4765 
4768  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 3, sm_ch_name ((MOBJ) ctemplate->current), constraint->name,
4769  "primary key");
4770  return error;
4771 
4774  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 3, sm_ch_name ((MOBJ) ctemplate->current), constraint->name,
4775  "NOT NULL constraint");
4776  return error;
4777 
4778  default:
4779  break;
4780  }
4781 
4782  return NO_ERROR;
4783 }
4784 
4785 int
4786 smt_change_constraint_status (SM_TEMPLATE * ctemplate, const char *index_name, SM_INDEX_STATUS index_status)
4787 {
4788  SM_CLASS_CONSTRAINT *cons = NULL;
4789  int error = NO_ERROR;
4790 
4791  assert (ctemplate != NULL && ctemplate->op != NULL);
4792 
4793  error = smt_is_change_status_allowed (ctemplate, index_name);
4794  if (error != NO_ERROR)
4795  {
4796  return error;
4797  }
4798 
4799  error = change_constraints_status_partitioned_class (ctemplate->op, index_name, index_status);
4800  if (error != NO_ERROR)
4801  {
4802  return error;
4803  }
4804 
4805  cons = smt_find_constraint (ctemplate, index_name);
4806  if (cons == NULL)
4807  {
4808  ASSERT_ERROR_AND_SET (error);
4809  return error;
4810  }
4811 
4812  error = classobj_change_constraint_status (ctemplate->properties, cons, index_status);
4813  if (error != NO_ERROR)
4814  {
4815  return error;
4816  }
4817 
4818  return NO_ERROR;
4819 }
static int check_namespace(SM_TEMPLATE *temp, const char *name, const bool class_namespace)
const char * name
Definition: class_object.h:631
SM_ATTRIBUTE * shared
Definition: class_object.h:722
#define ER_SM_INCOMPATIBLE_SUPER_CLASS
Definition: error_code.h:576
#define ER_SM_ATTRIBUTE_NOT_FOUND
Definition: error_code.h:311
int ml_append(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4548
static MOP smt_find_owner_of_constraint(SM_TEMPLATE *ctemplate, const char *constraint_name)
int db_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const DB_DOMAIN *desired_domain)
Definition: db_macro.c:1779
#define NO_ERROR
Definition: error_code.h:46
#define SM_MAP_CONSTRAINT_ATTFLAG_TO_PROPERTY(c)
Definition: class_object.h:86
#define ER_FK_HAS_DEFFERENT_TYPE_WITH_PK
Definition: error_code.h:1152
int smt_set_loader_commands(SM_TEMPLATE *template_, const char *commands)
int smt_add_super(SM_TEMPLATE *template_, MOP super_class)
DB_COLLECTION * db_get_set(const DB_VALUE *value)
#define SM_IS_CONSTRAINT_EXCEPT_INDEX_FAMILY(c)
Definition: class_object.h:134
#define ER_SM_RESOLUTION_COMPONENT_EXISTS
Definition: error_code.h:356
SM_CLASS * current
Definition: class_object.h:783
TP_DOMAIN_STATUS tp_domain_check(const TP_DOMAIN *domain, const DB_VALUE *value, TP_MATCH exact_match)
#define WS_LIST_FREE(lst, func)
Definition: work_space.h:575
void classobj_free_query_spec(SM_QUERY_SPEC *query_spec)
#define SM_MAP_CONSTRAINT_TO_ATTFLAG(c)
Definition: class_object.h:93
SM_FOREIGN_KEY_INFO * fk_info
Definition: class_object.h:537
#define ER_SM_QUERY_SPEC_NOT_FOUND
Definition: error_code.h:559
static int smt_add_attribute_to_list(SM_ATTRIBUTE **att_list, SM_ATTRIBUTE *att, const bool add_first, const char *add_after_attribute)
#define ER_SM_DEFAULT_NOT_ALLOWED
Definition: error_code.h:1266
void classobj_free_method(SM_METHOD *meth)
#define ASSERT_ERROR()
DB_OBJLIST * inheritance
Definition: class_object.h:718
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
#define ER_SM_ATTR_NOT_NULL
Definition: error_code.h:1327
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
int smt_delete_any(SM_TEMPLATE *template_, const char *name, SM_NAME_SPACE name_space)
int smt_quit(SM_TEMPLATE *template_)
unsigned self_ref
Definition: object_domain.h:96
SM_COMPONENT header
Definition: class_object.h:591
int smt_rename_method_file(SM_TEMPLATE *template_, const char *old_name, const char *new_name)
#define ER_SM_INVALID_ARGUMENTS
Definition: error_code.h:319
char * MOBJ
Definition: work_space.h:174
int classobj_put_index(DB_SEQ **properties, SM_CONSTRAINT_TYPE type, const char *constraint_name, SM_ATTRIBUTE **atts, const int *asc_desc, const int *attr_prefix_length, const BTID *id, SM_PREDICATE_INFO *filter_index_info, SM_FOREIGN_KEY_INFO *fk_info, char *shared_cons_name, SM_FUNCTION_INFO *func_index_info, const char *comment, SM_INDEX_STATUS index_status, bool attr_name_instead_of_id)
Definition: class_object.c:976
static int find_method(SM_TEMPLATE *template_, const char *name, int class_method, SM_METHOD **methodp)
const char * name
Definition: class_object.h:616
void ws_dirty(MOP op)
Definition: work_space.c:1622
int db_is_vclass(DB_OBJECT *op)
Definition: db_virt.c:681
DB_TYPE
Definition: dbtype_def.h:670
DB_OBJLIST * inheritance
Definition: class_object.h:788
SM_METHOD * class_methods
Definition: class_object.h:795
SM_CLASS_CONSTRAINT * classobj_find_class_primary_key(SM_CLASS *class_)
int smt_drop_method_file(SM_TEMPLATE *template_, const char *name)
SM_CLASS_CONSTRAINT * classobj_find_cons_primary_key(SM_CLASS_CONSTRAINT *cons_list)
int tp_domain_drop(TP_DOMAIN **dlist, TP_DOMAIN *domain)
#define DOWNCASE_NAME(a, b)
struct tp_domain * setdomain
Definition: object_domain.h:82
TP_DOMAIN * domain
Definition: class_object.h:444
#define SM_MAP_INDEX_ATTFLAG_TO_CONSTRAINT(c)
Definition: class_object.h:78
int classobj_get_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
static int smt_drop_constraint_from_property(SM_TEMPLATE *template_, const char *constraint_name, SM_ATTRIBUTE_FLAG constraint)
SM_CONSTRAINT_TYPE
Definition: class_object.h:274
static int change_constraints_comment_partitioned_class(MOP obj, const char *index_name, const char *comment)
int classobj_copy_default_expr(DB_DEFAULT_EXPR *dest, const DB_DEFAULT_EXPR *src)
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
SM_COMPONENT * classobj_find_component(SM_CLASS *class_, const char *name, int class_component)
#define ASSERT_ERROR_AND_SET(error_code)
DB_SEQ * properties
Definition: class_object.h:754
DB_SEQ * properties
Definition: class_object.h:807
SM_RESOLUTION * resolutions
Definition: class_object.h:735
int classobj_change_constraint_status(DB_SEQ *properties, SM_CLASS_CONSTRAINT *cons, SM_INDEX_STATUS index_status)
void classobj_free_template(SM_TEMPLATE *template_ptr)
#define SM_MAX_IDENTIFIER_LENGTH
SM_CLASS_TYPE
Definition: class_object.h:289
#define ER_SM_DOMAIN_NOT_A_CLASS
Definition: error_code.h:316
static int class_type(DB_OBJECT *class_obj)
Definition: cas_execute.c:8143
#define ER_SM_CONSTRAINT_HAS_DIFFERENT_TYPE
Definition: error_code.h:1256
static int find_any(SM_TEMPLATE *template_, const char *name, int class_stuff, SM_COMPONENT **thing)
SM_NAME_SPACE
static int smt_is_change_status_allowed(SM_TEMPLATE *ctemplate, const char *index_name)
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define ER_SM_SIGNATURE_NOT_FOUND
Definition: error_code.h:314
int smt_delete_set_attribute_domain(SM_TEMPLATE *template_, const char *name, int class_attribute, const char *domain_string, DB_DOMAIN *domain)
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
SM_CLASS_CONSTRAINT * classobj_find_constraint_by_name(SM_CLASS_CONSTRAINT *cons_list, const char *name)
struct sm_component * next
Definition: class_object.h:384
static int smt_change_attribute(SM_TEMPLATE *template_, const char *name, const char *new_name, const char *new_domain_string, DB_DOMAIN *new_domain, const SM_NAME_SPACE name_space, const bool change_first, const char *change_after_attribute, SM_ATTRIBUTE **found_att)
#define OID_SET_NULL(oidp)
Definition: oid.h:85
void sm_downcase_name(const char *name, char *buf, int maxlen)
unsigned is_cached
int smt_add_attribute_any(SM_TEMPLATE *template_, const char *name, const char *domain_string, DB_DOMAIN *domain, const SM_NAME_SPACE name_space, const bool add_first, const char *add_after_attribute, const char *comment)
#define ER_CANNOT_HAVE_PK_DEFAULT_NULL
Definition: error_code.h:1380
TP_DOMAIN * domain
Definition: class_object.h:559
#define ER_SM_SUPER_NOT_FOUND
Definition: error_code.h:330
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
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)
TP_DOMAIN * tp_domain_copy(const TP_DOMAIN *domain, bool check_cache)
SM_ATTRIBUTE * classobj_find_attribute(SM_CLASS *class_, const char *name, int class_attribute)
SM_METHOD_ARGUMENT * value
Definition: class_object.h:575
#define ER_SM_ATTMETH_NOT_FOUND
Definition: error_code.h:313
struct sm_class_constraint * next
Definition: class_object.h:530
SM_NAME_SPACE name_space
Definition: class_object.h:386
int er_errid(void)
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 smt_rename_any(SM_TEMPLATE *template_, const char *name, const bool class_namespace, const char *new_name)
#define ER_SM_INCOMPATIBLE_DOMAIN_CLASS_TYPE
Definition: error_code.h:699
#define ER_SM_CONSTRAINT_NOT_FOUND
Definition: error_code.h:870
static int get_domain_internal(SM_TEMPLATE *tmp, const char *domain_string, DB_DOMAIN **domainp, int check_internal)
#define ER_SM_SIGNATURE_EXISTS
Definition: error_code.h:323
const char * name
static int find_signature(SM_TEMPLATE *template_, const char *name, int class_method, const char *signame, SM_METHOD **methodp, SM_METHOD_SIGNATURE **sigp)
void locator_free_list_mops(LIST_MOPS *mops)
Definition: locator_cl.c:2978
enum tp_domain_status TP_DOMAIN_STATUS
LIST_MOPS * locator_get_all_mops(MOP class_mop, DB_FETCH_MODE purpose, LC_FETCH_VERSION_TYPE *force_fetch_version_type)
Definition: locator_cl.c:2839
SM_METHOD_ARGUMENT * classobj_make_method_arg(int index)
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
int ml_find(DB_OBJLIST *list, MOP mop)
Definition: work_space.c:4465
#define ER_SM_NOT_NULL_ON_VCLASS
Definition: error_code.h:883
#define ER_SM_SUPER_CAUSES_CYCLES
Definition: error_code.h:329
void ws_free_string(const char *str)
Definition: work_space.c:3480
int smt_reset_query_spec(SM_TEMPLATE *template_)
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
#define ER_FK_REF_CLASS_HAS_NOT_PK
Definition: error_code.h:1150
#define ER_SM_MULTIPLE_SIGNATURES
Definition: error_code.h:331
#define ERROR0(error, code)
Definition: error_manager.h:48
SM_METHOD * methods
Definition: class_object.h:791
int smt_add_method_any(SM_TEMPLATE *template_, const char *name, const char *function, SM_NAME_SPACE name_space)
int smt_reset_method_files(SM_TEMPLATE *template_)
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)
#define ER_SM_DOMAIN_NOT_FOUND
Definition: error_code.h:326
int smt_delete_super_connect(SM_TEMPLATE *template_, MOP super_class)
SM_ATTRIBUTE_FLAG
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
int smt_change_constraint_comment(SM_TEMPLATE *ctemplate, const char *index_name, const char *comment)
SM_CONSTRAINT_FAMILY
Definition: class_object.h:321
static DB_OBJECT * is_class(OID *obj_oid, OID *class_oid)
Definition: compactdb.c:637
int pr_free_ext_value(DB_VALUE *value)
MOBJ locator_fetch_class(MOP class_mop, DB_FETCH_MODE purpose)
Definition: locator_cl.c:2293
#define ER_SM_NOT_NULL_WRONG_NUM_ATTS
Definition: error_code.h:892
#define ER_UNEXPECTED
Definition: error_code.h:1254
bool pr_is_set_type(DB_TYPE type)
const char TEXT_CONSTRAINT_PREFIX[]
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
#define ER_SM_NOT_NULL_NOT_ALLOWED
Definition: error_code.h:1267
#define ER_SM_CONSTRAINT_EXISTS
Definition: error_code.h:875
static int smt_change_class_shared_attribute_domain(SM_ATTRIBUTE *att, DB_DOMAIN *new_domain)
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,...)
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)
#define ER_SM_ATTRIBUTE_PRIMARY_KEY_MEMBER
Definition: error_code.h:1113
const char * sm_ch_name(const MOBJ clobj)
int smt_delete_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name)
SM_METHOD_SIGNATURE * classobj_make_method_signature(const char *name)
#define assert(x)
int smt_drop_query_spec(SM_TEMPLATE *def, const int index)
PR_TYPE * tp_Type_null
DB_CONSTRAINT_TYPE
Definition: dbtype_def.h:452
#define ER_SM_METHOD_NOT_FOUND
Definition: error_code.h:312
int classobj_change_constraint_comment(DB_SEQ *properties, SM_CLASS_CONSTRAINT *cons, const char *comment)
SM_PARTITION * partition
Definition: class_object.h:814
static int find_argument(SM_TEMPLATE *template_, const char *name, int class_method, const char *signame, int index, int create, SM_METHOD **methodp, SM_METHOD_SIGNATURE **sigp, SM_METHOD_ARGUMENT **argp)
int smt_change_constraint_status(SM_TEMPLATE *ctemplate, const char *index_name, SM_INDEX_STATUS index_status)
#define ER_SM_RESOLUTION_NOT_FOUND
Definition: error_code.h:333
#define ER_SM_METHOD_FILE_NOT_FOUND
Definition: error_code.h:306
int au_fetch_class(MOP op, SM_CLASS **class_ptr, AU_FETCHMODE fetchmode, DB_AUTH type)
#define ER_SM_INHERITED
Definition: error_code.h:349
#define ERROR1(error, code, arg1)
Definition: error_manager.h:56
int sm_clean_class(MOP classmop, SM_CLASS *class_)
#define ER_FK_CANT_ON_SHARED_ATTRIBUTE
Definition: error_code.h:1263
#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)
struct sm_query_spec * next
Definition: class_object.h:683
static int get_domain(SM_TEMPLATE *tmp, const char *domain_string, DB_DOMAIN **domain)
#define ER_SM_INHERITED_METHOD
Definition: error_code.h:348
SM_QUERY_SPEC * classobj_make_query_spec(const char *specification)
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)
DB_VALUE original_value
Definition: class_object.h:393
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:725
void classobj_free_method_file(SM_METHOD_FILE *file)
SM_TEMPLATE * smt_copy_class(const char *new_name, const char *existing_name, SM_CLASS **class_)
int intl_identifier_casecmp(const char *str1, const char *str2)
int classobj_make_class_constraints(DB_SET *class_props, SM_ATTRIBUTE *attributes, SM_CLASS_CONSTRAINT **con_ptr)
static int check_resolution_name(MOP classmop, const char *name, int class_name)
#define TP_DOMAIN_COLLATION(dom)
static int smt_add_constraint_to_property(SM_TEMPLATE *template_, SM_CONSTRAINT_TYPE type, const char *constraint_name, SM_ATTRIBUTE **atts, const int *asc_desc, const int *attr_prefix_length, SM_FOREIGN_KEY_INFO *fk_info, char *shared_cons_name, SM_PREDICATE_INFO *filter_index, SM_FUNCTION_INFO *function_index, const char *comment, SM_INDEX_STATUS index_status)
#define ER_SM_INVALID_UNIQUE_TYPE
Definition: error_code.h:320
SM_QUERY_SPEC * query_spec
Definition: class_object.h:800
SM_NAME_SPACE name_space
Definition: class_object.h:633
#define SM_COMPARE_NAMES
Definition: class_object.h:47
METHOD_FUNCTION function
Definition: class_object.h:594
#define ER_SM_INVALID_PREFIX_LENGTH
Definition: error_code.h:1278
const char * sm_get_ch_name(MOP op)
static SM_TEMPLATE * def_class_internal(const char *name, int class_type)
void classobj_free_attribute(SM_ATTRIBUTE *att)
int smt_change_query_spec(SM_TEMPLATE *def, const char *query, const int index)
const char * function_name
Definition: class_object.h:570
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
#define TP_DOMAIN_TYPE(dom)
static int smt_change_attribute_pos_in_list(SM_ATTRIBUTE **att_list, SM_ATTRIBUTE *att, const bool change_first, const char *change_after_attribute)
#define ER_SM_INDEX_ATTR_DUPLICATED
Definition: error_code.h:1201
#define NULL
Definition: freelistheap.h:34
int tp_valid_indextype(DB_TYPE type)
int db_is_class(MOP obj)
Definition: db_info.c:310
struct pr_type * type
Definition: object_domain.h:76
const char * alias
Definition: class_object.h:632
SM_METHOD_SIGNATURE * signatures
Definition: class_object.h:593
const char * pr_type_name(DB_TYPE id)
#define ER_REGU_NOT_IMPLEMENTED
Definition: error_code.h:194
int sm_check_name(const char *name)
struct pr_type * type
Definition: class_object.h:443
#define BTID_SET_NULL(btid)
DB_VALUE * pr_make_ext_value(void)
SM_TEMPLATE * smt_copy_class_mop(const char *name, MOP op, SM_CLASS **class_)
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
#define err(fd,...)
Definition: porting.h:431
int ml_remove(DB_OBJLIST **list, MOP mop)
Definition: work_space.c:4613
static int delete_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name, SM_NAME_SPACE name_space)
const char * loader_commands
Definition: class_object.h:799
SM_METHOD * classobj_make_method(const char *name, SM_NAME_SPACE name_space)
SM_ATTRIBUTE * classobj_make_attribute(const char *name, struct pr_type *type, SM_NAME_SPACE name_space)
struct pr_type * type
Definition: class_object.h:558
SM_TEMPLATE * smt_edit_class_mop(MOP op, DB_AUTH db_auth_type)
int smt_add_method(SM_TEMPLATE *template_, const char *name, const char *function)
int smt_add_set_attribute_domain(SM_TEMPLATE *template_, const char *name, int class_attribute, const char *domain_string, DB_DOMAIN *domain)
int smt_add_class_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name, const char *alias)
int tp_domain_add(TP_DOMAIN **dlist, TP_DOMAIN *domain)
METHOD_FUNCTION function
Definition: class_object.h:571
struct db_objlist * next
Definition: dbtype_def.h:442
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:794
int sm_exist_index(MOP classop, const char *idxname, BTID *btid)
const char * classobj_map_constraint_to_property(SM_CONSTRAINT_TYPE constraint)
Definition: class_object.c:502
DB_DOMAIN * pt_string_to_db_domain(const char *s, const char *class_name)
Definition: parse_dbi.c:1332
int pr_clear_value(DB_VALUE *value)
static int resolve_class_domain(SM_TEMPLATE *tmp, DB_DOMAIN *domain)
#define ER_FK_CANT_DROP_PK_REFERRED
Definition: error_code.h:1154
static int check_alias_delete(SM_TEMPLATE *template_, const char *name, SM_NAME_SPACE name_space, int error)
SM_METHOD * class_methods
Definition: class_object.h:733
TP_DOMAIN_STATUS tp_check_value_size(TP_DOMAIN *domain, DB_VALUE *value)
#define WS_LIST_APPEND(lst, element)
Definition: work_space.h:577
#define WS_LIST_NCONC(lst1, lst2)
Definition: work_space.h:583
struct db_object * op
Definition: dbtype_def.h:443
SM_CLASS_CONSTRAINT * constraints
Definition: class_object.h:757
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)
void classobj_free_class_constraints(SM_CLASS_CONSTRAINT *constraints)
#define TP_IS_CHAR_TYPE(typeid)
static void error(const char *msg)
Definition: gencat.c:331
DB_DEFAULT_EXPR_TYPE on_update_default_expr
Definition: class_object.h:452
unsigned int flags
Definition: class_object.h:459
void classobj_free_resolution(SM_RESOLUTION *res)
SM_TEMPLATE * classobj_make_template(const char *name, MOP op, SM_CLASS *class_)
int sm_is_global_only_constraint(MOP classmop, SM_CLASS_CONSTRAINT *constraint, int *is_global, SM_TEMPLATE *template_)
TP_DOMAIN * tp_domain_construct(DB_TYPE domain_type, DB_OBJECT *class_obj, int precision, int scale, TP_DOMAIN *setdomain)
struct sm_method_signature * next
Definition: class_object.h:568
int smt_delete_class_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name)
#define WS_LIST_REMOVE(lst, element)
Definition: work_space.h:581
SM_TEMPLATE * classobj_make_template_like(const char *name, SM_CLASS *class_)
#define ER_FK_NOT_MATCH_KEY_COUNT
Definition: error_code.h:1158
#define TP_TYPE_HAS_COLLATION(typeid)
PR_TYPE * pr_find_type(const char *name)
#define SM_IS_INDEX_FAMILY(c)
Definition: class_object.h:139
#define ER_FK_UNKNOWN_REF_CLASSNAME
Definition: error_code.h:1149
const char * ref_class
Definition: class_object.h:475
#define AU_SELECT
Definition: authenticate.h:69
DB_AUTH
Definition: dbtype_def.h:239
#define ARG_FILE_LINE
Definition: error_manager.h:44
int smt_check_index_exist(SM_TEMPLATE *template_, char **out_shared_cons_name, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, const int *asc_desc, const SM_PREDICATE_INFO *filter_index, const SM_FUNCTION_INFO *function_index)
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)
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
#define NLIST_FIND(lst, name)
Definition: work_space.h:610
const char * name
Definition: class_object.h:787
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)
SM_METHOD_FILE * classobj_make_method_file(const char *name)
static int check_local_definition(SM_TEMPLATE *template_, const char *name, const char *alias, SM_NAME_SPACE name_space)
#define ER_FK_NOT_HAVE_PK_MEMBER
Definition: error_code.h:1151
static SM_CLASS_CONSTRAINT * smt_find_constraint(SM_TEMPLATE *ctemplate, const char *constraint_name)
static int check_domain_class_type(SM_TEMPLATE *template_, DB_OBJECT *domain_classobj)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define ER_SM_CLASS_WITH_PRIM_NAME
Definition: error_code.h:305
int smt_change_method_implementation(SM_TEMPLATE *template_, const char *name, int class_method, const char *function)
#define ER_SM_NAME_RESERVED_BY_ATT
Definition: error_code.h:317
int classobj_check_index_exist(SM_CLASS_CONSTRAINT *constraints, char **out_shared_cons_name, const char *class_name, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names, const int *asc_desc, const SM_PREDICATE_INFO *filter_index, const SM_FUNCTION_INFO *func_index_info)
SM_COMPONENT header
Definition: class_object.h:441
DB_CONSTRAINT_TYPE db_constraint_type(const DB_CONSTRAINT *constraint)
Definition: db_info.c:1978
#define ER_SM_INVALID_INDEX_TYPE
Definition: error_code.h:341
#define ERROR2(error, code, arg1, arg2)
Definition: error_manager.h:64
int smt_drop_constraint(SM_TEMPLATE *template_, const char **att_names, const char *constraint_name, int class_attribute, SM_ATTRIBUTE_FLAG constraint)
#define ER_OBJ_INVALID_ARGUMENTS
Definition: error_code.h:275
#define ER_SM_DOMAIN_NOT_A_SET
Definition: error_code.h:324
MOP mops[1]
Definition: locator_cl.h:67
SM_RESOLUTION * classobj_make_resolution(MOP class_mop, const char *name, const char *alias, SM_NAME_SPACE name_space)
#define ER_SM_INHERITED_ATTRIBUTE
Definition: error_code.h:347
SM_TEMPLATE * smt_def_class(const char *name)
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
SM_CLASS_TYPE class_type
Definition: class_object.h:784
int smt_add_query_spec(SM_TEMPLATE *template_, const char *specification)
SM_CLASS_TYPE class_type
Definition: class_object.h:713
#define ER_SM_SUPER_CLASS_EXISTS
Definition: error_code.h:328
SM_METHOD_ARGUMENT * args
Definition: class_object.h:577
#define ER_OBJ_STRING_OVERFLOW
Definition: error_code.h:293
void er_clear(void)
#define ER_SM_INDEX_STATUS_CHANGE_NOT_ALLOWED
Definition: error_code.h:1590
#define ER_QPROC_INVALID_COLNAME
Definition: error_code.h:524
const char ** ref_attrs
Definition: class_object.h:476
#define is_global(M)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
static SM_COMPONENT * find_component(SM_TEMPLATE *template_, const char *name, int class_stuff)
struct db_object * MOP
Definition: dbtype_def.h:409
#define AU_INDEX
Definition: authenticate.h:74
DB_TYPE id
int smt_add_method_file(SM_TEMPLATE *template_, const char *filename)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
SM_TEMPLATE * smt_def_typed_class(const char *name, SM_CLASS_TYPE ct)
#define ER_OBJ_DOMAIN_CONFLICT
Definition: error_code.h:285
int smt_add_attribute(SM_TEMPLATE *template_, const char *name, const char *domain_string, DB_DOMAIN *domain)
struct tp_domain * next
Definition: object_domain.h:74
#define ER_NOT_ALLOWED_ACCESS_TO_PARTITION
Definition: error_code.h:1137
#define ER_SM_INVALID_CONSTRAINT
Definition: error_code.h:871
int smt_set_attribute_on_update(SM_TEMPLATE *template_, const char *name, int class_attribute, DB_DEFAULT_EXPR_TYPE on_update)
const char * name
Definition: class_object.h:385
#define DB_IS_CONSTRAINT_INDEX_FAMILY(c)
Definition: dbtype_def.h:173
#define ER_SM_METHOD_ARG_NOT_FOUND
Definition: error_code.h:315
#define SM_IS_ATTFLAG_INDEX_FAMILY(c)
Definition: class_object.h:61
#define SM_GET_CONSTRAINT_STRING(c)
Definition: class_object.h:156
#define SM_IS_ATTFLAG_UNIQUE_FAMILY(c)
Definition: class_object.h:55
#define ER_SM_INDEX_EXISTS
Definition: error_code.h:344
MOP sm_Root_class_mop
struct db_object * class_mop
Definition: object_domain.h:81
#define ER_SM_ALIAS_COMPONENT_EXISTS
Definition: error_code.h:357
MOP sm_find_class(const char *name)
int smt_find_attribute(SM_TEMPLATE *template_, const char *name, int class_attribute, SM_ATTRIBUTE **attp)
SM_CLASS_TYPE smt_get_class_type(SM_TEMPLATE *template_)
int locator_is_class(MOP mop, DB_FETCH_MODE hint_purpose)
Definition: locator_cl.c:239
int smt_set_attribute_default(SM_TEMPLATE *template_, const char *name, int class_attribute, DB_VALUE *proposed_value, DB_DEFAULT_EXPR *default_expr)
#define ER_SM_INVALID_INDEX_WITH_PREFIX_TYPE
Definition: error_code.h:1262
#define SM_IS_ATTFLAG_UNIQUE_FAMILY_OR_FOREIGN_KEY(c)
Definition: class_object.h:73
#define ER_SM_NAME_RESERVED_BY_METHOD
Definition: error_code.h:318
char * ws_copy_string(const char *str)
Definition: work_space.c:3457
struct sm_resolution * next
Definition: class_object.h:628
int do_check_rows_for_null(MOP class_mop, const char *att_name, bool *has_nulls)
#define SM_FIND_NAME_IN_COMPONENT_LIST(complist, name)
Definition: class_object.h:146
DB_VALUE * default_value
Definition: esql_cli.c:348
SM_CLASS_TYPE sm_get_class_type(SM_CLASS *class_)
int smt_add_class_method(SM_TEMPLATE *template_, const char *name, const char *function)
#define ER_SM_UNIQUE_ON_VCLASS
Definition: error_code.h:884
static int add_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name, const char *alias, SM_NAME_SPACE name_space)
#define TP_IS_BIT_TYPE(typeid)
SM_METHOD * methods
Definition: class_object.h:730
#define ER_SM_INVALID_CLASS
Definition: error_code.h:365
static SM_RESOLUTION * find_alias(SM_RESOLUTION *reslist, const char *name, SM_NAME_SPACE name_space)
static int smt_check_foreign_key(SM_TEMPLATE *template_, const char *constraint_name, SM_ATTRIBUTE **atts, int n_atts, SM_FOREIGN_KEY_INFO *fk_info)
SM_INDEX_STATUS
Definition: class_object.h:510
SM_ATTRIBUTE * attributes
Definition: class_object.h:790
#define ER_SM_ARG_DOMAIN_NOT_A_SET
Definition: error_code.h:332
#define ER_OBJ_NOT_A_CLASS
Definition: error_code.h:288
#define ER_SM_INDEX_ON_SHARED
Definition: error_code.h:322
const char * comment
Definition: class_object.h:467
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
struct sm_method_file * next
Definition: class_object.h:615
void tp_domain_free(TP_DOMAIN *dom)
SM_METHOD_ARGUMENT * classobj_find_method_arg(SM_METHOD_ARGUMENT **arglist, int index, int create)
DB_DEFAULT_EXPR_TYPE
Definition: dbtype_def.h:1181
static int smt_set_attribute_orig_default_value(SM_ATTRIBUTE *att, DB_VALUE *new_orig_value, DB_DEFAULT_EXPR *default_expr)
SM_RESOLUTION * classobj_find_resolution(SM_RESOLUTION *reslist, MOP class_mop, const char *name, SM_NAME_SPACE name_space)
static int change_constraints_status_partitioned_class(MOP obj, const char *index_name, SM_INDEX_STATUS index_status)
const char * rel_major_release_string(void)
int smt_delete_super(SM_TEMPLATE *template_, MOP super_class)
int classobj_drop_prop(DB_SEQ *properties, const char *name)
Definition: class_object.c:394
SM_NAME_SPACE sm_resolution_space(SM_NAME_SPACE name_space)
const char * name
Definition: class_object.h:532
int classobj_find_prop_constraint(DB_SEQ *properties, const char *prop_name, const char *cnstr_name, DB_VALUE *cnstr_val)
int classobj_put_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
Definition: class_object.c:314
#define ER_SM_NO_NESTED_SETS
Definition: error_code.h:325
SM_METHOD * classobj_find_method(SM_CLASS *class_, const char *name, int class_method)
int sm_update_class(SM_TEMPLATE *template_, MOP *classmop)
int smt_add_resolution(SM_TEMPLATE *template_, MOP super_class, const char *name, const char *alias)