CUBRID Engine  latest
class_object.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  * class_object.c - Class Constructors
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "language_support.h"
32 #include "area_alloc.h"
33 #include "work_space.h"
34 #include "object_representation.h"
35 #include "object_primitive.h"
36 #include "class_object.h"
37 #include "boot_cl.h"
38 #include "locator_cl.h"
39 #include "authenticate.h"
40 #include "set_object.h"
41 #include "object_accessor.h"
42 #include "object_print.h"
43 #include "parser.h"
44 #include "trigger_manager.h"
45 #include "schema_manager.h"
46 #include "dbi.h"
47 #if defined(WINDOWS)
48 #include "misc_string.h"
49 #endif
50 #include "dbtype.h"
51 #include "printer.hpp"
52 
53 #if defined (SUPPRESS_STRLEN_WARNING)
54 #define strlen(s1) ((int) strlen(s1))
55 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
56 
57 /* Macro to generate the UNIQUE property string from the components */
58 #define SM_SPRINTF_UNIQUE_PROPERTY_VALUE(buffer, volid, fileid, pageid) \
59  sprintf(buffer, "%d|%d|%d", (int)volid, (int)fileid, (int)pageid)
60 
61 typedef enum
62 {
68 
69 const int SM_MAX_STRING_LENGTH = 1073741823; /* 0x3fffffff */
70 
78 };
79 
80 static const char *Constraint_properties[] = {
87 };
88 
89 #define NUM_CONSTRAINT_TYPES \
90  ((int)(sizeof(Constraint_types)/sizeof(Constraint_types[0])))
91 #define NUM_CONSTRAINT_PROPERTIES \
92  ((int)(sizeof(Constraint_properties)/sizeof(Constraint_properties[0])))
93 
95 
96 static void classobj_print_props (DB_SEQ * properties);
99 static DB_SEQ *classobj_make_index_attr_prefix_seq (int num_attrs, const int *attrs_prefix_length);
100 static DB_SEQ *classobj_make_index_filter_pred_seq (SM_PREDICATE_INFO * filter_index_info);
101 static void classobj_put_value_and_iterate (DB_SEQ * destination, int &index, DB_VALUE & value);
102 static int classobj_put_seq_and_iterate (DB_SEQ * destination, int &index, DB_SEQ * element);
103 static int classobj_put_seq_with_name_and_iterate (DB_SEQ * destination, int &index, const char *name, DB_SEQ * seq);
104 static SM_CONSTRAINT *classobj_make_constraint (const char *name, SM_CONSTRAINT_TYPE type, BTID * id,
105  bool has_function_constraint);
106 static void classobj_free_constraint (SM_CONSTRAINT * constraint);
107 static int classobj_constraint_size (SM_CONSTRAINT * constraint);
108 static bool classobj_cache_constraint_entry (const char *name, DB_SEQ * constraint_seq, SM_CLASS * class_,
109  SM_CONSTRAINT_TYPE constraint_type);
110 static bool classobj_cache_constraint_list (DB_SEQ * seq, SM_CLASS * class_, SM_CONSTRAINT_TYPE constraint_type);
112 static SM_FOREIGN_KEY_INFO *classobj_make_foreign_key_info (DB_SEQ * fk_seq, const char *cons_name,
113  SM_ATTRIBUTE * attributes);
116 static int *classobj_make_index_prefix_info (DB_SEQ * prefix_seq, int num_attrs);
118 static int classobj_cache_not_null_constraints (const char *class_name, SM_ATTRIBUTE * attributes,
119  SM_CLASS_CONSTRAINT ** con_ptr);
121 static int classobj_domain_size (TP_DOMAIN * domain);
122 static void classobj_filter_attribute_props (DB_SEQ * props);
123 static int classobj_init_attribute (SM_ATTRIBUTE * src, SM_ATTRIBUTE * dest, int copy);
124 static void classobj_clear_attribute_value (DB_VALUE * value);
125 static void classobj_clear_attribute (SM_ATTRIBUTE * att);
126 static int classobj_attribute_size (SM_ATTRIBUTE * att);
127 static void classobj_free_method_arg (SM_METHOD_ARGUMENT * arg);
132 static void classobj_clear_method (SM_METHOD * meth);
133 static int classobj_init_method (SM_METHOD * src, SM_METHOD * dest, int copy);
134 static int classobj_copy_methlist (SM_METHOD * methlist, MOP filter_class, SM_METHOD ** copy_ptr);
135 static int classobj_method_size (SM_METHOD * meth);
136 static int classobj_resolution_size (SM_RESOLUTION * res);
138 static int classobj_method_file_size (SM_METHOD_FILE * file);
140 static int classobj_repattribute_size (void);
142 static int classobj_query_spec_size (SM_QUERY_SPEC * query_spec);
143 static void classobj_insert_ordered_attribute (SM_ATTRIBUTE ** attlist, SM_ATTRIBUTE * att);
145 static void classobj_sort_attlist (SM_ATTRIBUTE ** source);
146 static void classobj_sort_methlist (SM_METHOD ** source);
147 static int classobj_copy_attribute_like (DB_CTMPL * ctemplate, SM_ATTRIBUTE * attribute,
148  const char *const like_class_name);
149 static int classobj_copy_constraint_like (DB_CTMPL * ctemplate, SM_CLASS_CONSTRAINT * constraint,
150  const char *const like_class_name);
154  const DB_CONSTRAINT_TYPE constraint_type,
155  const SM_PREDICATE_INFO * filter_predicate,
156  const SM_FUNCTION_INFO * func_index_info,
157  const SM_CLASS_CONSTRAINT * existing_con,
158  SM_CLASS_CONSTRAINT ** primary_con);
159 static int classobj_check_function_constraint_info (DB_SEQ * constraint_seq, bool * has_function_constraint);
160 static int classobj_partition_info_size (SM_PARTITION * partition_info);
161 
162 /*
163  * classobj_area_init - Initialize the area for schema templates.
164  * return: NO_ERROR or error code.
165  */
166 int
168 {
169  Template_area = area_create ("Schema templates", sizeof (SM_TEMPLATE), 4);
170  if (Template_area == NULL)
171  {
172  assert (er_errid () != NO_ERROR);
173  return er_errid ();
174  }
175 
176  return NO_ERROR;
177 }
178 
179 /*
180  * classobj_area_final - Finalize the area for schema templates.
181  * return: none.
182  */
183 void
185 {
186  if (Template_area != NULL)
187  {
188  area_destroy (Template_area);
189  Template_area = NULL;
190  }
191 }
192 
193 /* THREADED ARRAYS */
194 /*
195  * These are used for the representation of the flattened attribute and
196  * method lists. The structures are maintained contiguously in an array for
197  * quick indexing but in addition have a link field at the top so they can be
198  * traversed as lists. This is particularly helpful during class definition
199  * and makes it simpler for the class transformer to walk over the structures.
200  */
201 
202 /*
203  * classobj_alloc_threaded_array() - Allocates a threaded array and initializes
204  * the thread pointers.
205  * return: threaded array
206  * size(in): element size
207  * count(in): number of elements
208  */
209 
210 DB_LIST *
212 {
213  DB_LIST *array, *l;
214  char *ptr;
215  int i;
216 
217  array = NULL;
218  if (count)
219  {
220  array = (DB_LIST *) db_ws_alloc (size * count);
221  if (array == NULL)
222  {
223  return NULL;
224  }
225 
226  ptr = (char *) array;
227  for (i = 0; i < (count - 1); i++)
228  {
229  l = (DB_LIST *) ptr;
230  l->next = (DB_LIST *) (ptr + size);
231  ptr += size;
232  }
233  l = (DB_LIST *) ptr;
234  l->next = NULL;
235  }
236  return (array);
237 }
238 
239 /*
240  * classobj_free_threaded_array() - Frees a threaded array and calls a function on
241  * each element to free any storage referenced by the elements.
242  * return: none
243  * array(in): threaded array
244  * clear(in): function to free storage contained in elements
245  */
246 
247 void
249 {
250  DB_LIST *l;
251 
252  if (clear != NULL)
253  {
254  for (l = array; l != NULL; l = l->next)
255  {
256  if (clear != NULL)
257  {
258  (*clear) (l);
259  }
260  }
261  }
262  db_ws_free (array);
263 }
264 
265 /* PROPERTY LISTS */
266 /*
267  * These are used to maintain random values on class, method, and attribute
268  * definitions. The values are used infrequently so there is a motiviation
269  * for not reserving space for them unconditionally in the main
270  * structure body. They are implemented as sequences of name/value pairs.
271  */
272 
273 /*
274  * classobj_make_prop() - Creates an empty property list for a class, attribute,
275  * or method.
276  * return: an initialized property list
277  */
278 
279 DB_SEQ *
281 {
282  return (set_create_sequence (0));
283 }
284 
285 /*
286  * classobj_free_prop() - Frees a property list for a class, attribute, or method.
287  * return: none
288  * properties(in): a property list
289  */
290 
291 void
293 {
294  if (properties != NULL)
295  {
296  set_free (properties);
297  }
298 }
299 
300 /*
301  * classobj_put_prop() - This is used to add a new property to a property list.
302  * First the list is searched for a property with the given name. If the
303  * property already exists, the property value will be replaced with the
304  * new value and a non-zero is returned from the function.
305  * If the property does not exist, it will be added to the end of the
306  * list.
307  * return: index of the replaced property, 0 if not found
308  * properties(in): property list
309  * name(in): property name
310  * pvalue(in): new property value
311  */
312 
313 int
314 classobj_put_prop (DB_SEQ * properties, const char *name, DB_VALUE * pvalue)
315 {
316  int error;
317  int found, max, i;
318  DB_VALUE value;
319  const char *val_str;
320 
321  error = NO_ERROR;
322  found = 0;
323 
324  if (properties == NULL || name == NULL || pvalue == NULL)
325  {
326  return found;
327  }
328 
329  max = set_size (properties);
330  for (i = 0; i < max && !found && error == NO_ERROR; i += 2)
331  {
332  error = set_get_element (properties, i, &value);
333  if (error != NO_ERROR)
334  {
335  continue;
336  }
337 
338  if (DB_VALUE_TYPE (&value) != DB_TYPE_STRING || (val_str = db_get_string (&value)) == NULL)
339  {
340  error = ER_SM_INVALID_PROPERTY;
341  }
342  else
343  {
344  if (strcmp (name, val_str) == 0)
345  {
346  if ((i + 1) >= max)
347  {
348  error = ER_SM_INVALID_PROPERTY;
349  }
350  else
351  {
352  found = i + 1;
353  }
354  }
355  }
356  pr_clear_value (&value);
357  }
358 
359  if (error == NO_ERROR)
360  {
361  if (found)
362  {
363  set_put_element (properties, found, pvalue);
364  }
365  else
366  {
367  /* start with the property value to avoid growing the array twice */
368  set_put_element (properties, max + 1, pvalue);
369  db_make_string (&value, name);
370  set_put_element (properties, max, &value);
371  pr_clear_value (&value);
372  }
373  }
374 
375  if (error != NO_ERROR)
376  {
378  }
379 
380  return (found);
381 }
382 
383 /*
384  * classobj_drop_prop() - This removes a property from a property list.
385  * If the property was found, the name and value entries in the sequence
386  * are removed and a non-zero value is returned. If the property
387  * was not found, the sequence is unchanged and a zero is returned.
388  * return: non-zero if the property was dropped
389  * properties(in): property list
390  * name(in): property name
391  */
392 
393 int
394 classobj_drop_prop (DB_SEQ * properties, const char *name)
395 {
396  int error;
397  int dropped, max, i;
398  DB_VALUE value;
399  const char *val_str;
400 
401  error = NO_ERROR;
402  dropped = 0;
403 
404  if (properties == NULL || name == NULL)
405  {
406  goto error;
407  }
408 
409  max = set_size (properties);
410  for (i = 0; i < max && !dropped && error == NO_ERROR; i += 2)
411  {
412  error = set_get_element (properties, i, &value);
413  if (error != NO_ERROR)
414  {
415  continue;
416  }
417 
418  if (DB_VALUE_TYPE (&value) != DB_TYPE_STRING || (val_str = db_get_string (&value)) == NULL)
419  {
420  error = ER_SM_INVALID_PROPERTY;
421  }
422  else
423  {
424  if (strcmp (name, val_str) == 0)
425  {
426  if ((i + 1) >= max)
427  {
428  error = ER_SM_INVALID_PROPERTY;
429  }
430  else
431  {
432  dropped = 1;
433  /* drop the two elements at the found position */
434  set_drop_seq_element (properties, i);
435  set_drop_seq_element (properties, i);
436  }
437  }
438  }
439  pr_clear_value (&value);
440 
441  }
442 
443 error:
444  if (error)
445  {
447  }
448 
449  return (dropped);
450 }
451 
452 /*
453  * classobj_print_props() - Debug function to dump a property list to standard out.
454  * return: none
455  * properties(in): property list
456  */
457 
458 static void
460 {
461  set_print (properties);
462  fprintf (stdout, "\n");
463 #if 0
464  DB_VALUE value;
465  int max, i;
466 
467  if (properties == NULL)
468  {
469  return;
470  }
471  max = set_size (properties);
472  if (max)
473  {
474  for (i = 0; i < max; i++)
475  {
476  if (set_get_element (properties, i, &value) != NO_ERROR)
477  fprintf (stdout, "*** error *** ");
478  else
479  {
480  help_fprint_value (stdout, &value);
481  pr_clear_value (&value);
482  fprintf (stdout, " ");
483  }
484  }
485  fprintf (stdout, "\n");
486  }
487 
488 #endif /* 0 */
489 }
490 
491 
492 /*
493  * classobj_map_constraint_to_property() - Return the SM_PROPERTY type corresponding to
494  * the SM_CONSTRAINT_TYPE. This is necessary since we don't store
495  * SM_CONSTRAINT_TYPE's in the property lists.
496  * A NULL is returned if there is not a corresponding SM_PROPERTY type
497  * return: SM_PROPERTY type
498  * constraint(in): constraint type
499  */
500 
501 const char *
503 {
504  const char *property_type = NULL;
505 
506  switch (constraint)
507  {
508  case SM_CONSTRAINT_INDEX:
509  property_type = SM_PROPERTY_INDEX;
510  break;
512  property_type = SM_PROPERTY_UNIQUE;
513  break;
515  property_type = SM_PROPERTY_NOT_NULL;
516  break;
518  property_type = SM_PROPERTY_REVERSE_INDEX;
519  break;
521  property_type = SM_PROPERTY_REVERSE_UNIQUE;
522  break;
524  property_type = SM_PROPERTY_PRIMARY_KEY;
525  break;
527  property_type = SM_PROPERTY_FOREIGN_KEY;
528  break;
529  default:
531  break;
532  }
533 
534  return property_type;
535 }
536 
537 /*
538  * classobj_copy_props() - Copies a property list. The filter class is optional and
539  * will cause those properties whose origin is the given class to be copied
540  * and others to be filtered out. This is useful when we want to filter out
541  * inherited properties.
542  * return: NO_ERROR on success, non-zero for ERROR
543  * properties(in): property list to copy
544  * filter_class(in): optional filter class
545  * new_properties(out): output property list where the properties are copied to
546  */
547 
548 int
549 classobj_copy_props (DB_SEQ * properties, MOP filter_class, DB_SEQ ** new_properties)
550 {
551  int error = NO_ERROR;
552  SM_CLASS_CONSTRAINT *constraints = NULL;
553 
554  if (properties == NULL)
555  {
556  return error;
557  }
558 
559  *new_properties = set_copy (properties);
560 
561  if (*new_properties == NULL)
562  {
563  assert (er_errid () != NO_ERROR);
564  return er_errid ();
565  }
566 
567  /* Filter out INDEXs and UNIQUE constraints which are inherited */
568  if (filter_class != NULL)
569  {
571  SM_CLASS *class_;
572  int is_global = 0;
573  error = au_fetch_class_force (filter_class, &class_, AU_FETCH_READ);
574  if (error != NO_ERROR)
575  {
576  goto error_condition;
577  }
578 
579  /* Remove all constraints from the property list. We'll add the locally defined ones bellow. We can't just
580  * start with an empty property list since there might be other properties on it (such as proxy information).
581  *
582  * We don't know (or care) if the properties already exist so just ignore the return value. */
583  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_UNIQUE);
584  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_INDEX);
585  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_NOT_NULL);
586  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_REVERSE_UNIQUE);
587  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_REVERSE_INDEX);
588  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_PRIMARY_KEY);
589  (void) classobj_drop_prop (*new_properties, SM_PROPERTY_FOREIGN_KEY);
590 
591  error = classobj_make_class_constraints (properties, class_->attributes, &constraints);
592  if (error != NO_ERROR)
593  {
594  goto error_condition;
595  }
596 
597  for (c = constraints; c != NULL; c = c->next)
598  {
599  if (c->attributes == NULL)
600  {
601  error = ER_FAILED;
602  goto error_condition;
603  }
604 
606  || c->type == SM_CONSTRAINT_FOREIGN_KEY || c->attributes[0]->class_mop == filter_class)
607  {
608  is_global = 0;
609  }
610  else if (SM_IS_CONSTRAINT_UNIQUE_FAMILY (c->type))
611  {
612  SM_CLASS *super_class = NULL;
613  error = au_fetch_class_force (c->attributes[0]->class_mop, &super_class, AU_FETCH_READ);
614  if (error != NO_ERROR)
615  {
616  goto error_condition;
617  }
618 
619  error = sm_is_global_only_constraint (c->attributes[0]->class_mop, c, &is_global, NULL);
620  if (error != NO_ERROR)
621  {
622  goto error_condition;
623  }
624  }
625  if (is_global == 0)
626  {
627  if (classobj_put_index (new_properties, c->type, c->name, c->attributes, c->asc_desc,
630  != NO_ERROR)
631  {
632  error = ER_SM_INVALID_PROPERTY;
634  goto error_condition;
635  }
636  }
637  }
638 
639  classobj_free_class_constraints (constraints);
640  }
641 
642  return (error);
643 
644 
645  /* Error Handlers */
646 error_condition:
647  if (*new_properties != NULL)
648  {
649  classobj_free_prop (*new_properties);
650  }
651 
652  if (constraints != NULL)
653  {
654  classobj_free_class_constraints (constraints);
655  }
656 
657  return error;
658 }
659 
660 /*
661  * classobj_make_foreign_key_info_seq()
662  * return:
663  * fk_info(in):
664  */
665 
666 static DB_SEQ *
668 {
669  DB_VALUE value;
670  DB_SEQ *fk_seq;
671  char pbuf[128];
672 
673  fk_seq = set_create_sequence (4);
674 
675  if (fk_seq == NULL)
676  {
677  return NULL;
678  }
679 
680  sprintf (pbuf, "%d|%d|%d", (int) fk_info->ref_class_oid.pageid, (int) fk_info->ref_class_oid.slotid,
681  (int) fk_info->ref_class_oid.volid);
682  db_make_string (&value, pbuf);
683  set_put_element (fk_seq, 0, &value);
684 
685  sprintf (pbuf, "%d|%d|%d", (int) fk_info->ref_class_pk_btid.vfid.volid, (int) fk_info->ref_class_pk_btid.vfid.fileid,
686  (int) fk_info->ref_class_pk_btid.root_pageid);
687  db_make_string (&value, pbuf);
688  set_put_element (fk_seq, 1, &value);
689 
690  db_make_int (&value, fk_info->delete_action);
691  set_put_element (fk_seq, 2, &value);
692 
693  db_make_int (&value, fk_info->update_action);
694  set_put_element (fk_seq, 3, &value);
695 
696  return fk_seq;
697 }
698 
699 /*
700  * classobj_make_foreign_key_ref_seq()
701  * return:
702  * fk_info(in):
703  */
704 
705 static DB_SEQ *
707 {
708  DB_VALUE value;
709  DB_SEQ *fk_seq;
710  char pbuf[128];
711 
712  fk_seq = set_create_sequence (5);
713 
714  if (fk_seq == NULL)
715  {
716  return NULL;
717  }
718 
719  sprintf (pbuf, "%d|%d|%d", (int) fk_info->self_oid.pageid, (int) fk_info->self_oid.slotid,
720  (int) fk_info->self_oid.volid);
721  db_make_string (&value, pbuf);
722  set_put_element (fk_seq, 0, &value);
723 
724  sprintf (pbuf, "%d|%d|%d", (int) fk_info->self_btid.vfid.volid, (int) fk_info->self_btid.vfid.fileid,
725  (int) fk_info->self_btid.root_pageid);
726  db_make_string (&value, pbuf);
727  set_put_element (fk_seq, 1, &value);
728 
729  db_make_int (&value, fk_info->delete_action);
730  set_put_element (fk_seq, 2, &value);
731 
732  db_make_int (&value, fk_info->update_action);
733  set_put_element (fk_seq, 3, &value);
734 
735  db_make_string (&value, fk_info->name);
736  set_put_element (fk_seq, 4, &value);
737 
738  return fk_seq;
739 }
740 
741 /*
742  * classobj_describe_foreign_key_action()
743  * return:
744  * action(in):
745  */
746 
747 char *
749 {
750  switch (action)
751  {
753  return (char *) "CASCADE";
755  return (char *) "RESTRICT";
757  return (char *) "NO ACTION";
759  return (char *) "SET NULL";
760  }
761 
762  return (char *) "";
763 }
764 
765 /*
766  * classobj_make_index_attr_prefix_seq() - Make sequence which contains prefix length
767  * return: sequence
768  * num_attrs(in): key attribute count
769  * attrs_prefix_length(in): array which contains prefix length
770  */
771 static DB_SEQ *
772 classobj_make_index_attr_prefix_seq (int num_attrs, const int *attrs_prefix_length)
773 {
774  DB_SEQ *prefix_seq;
775  DB_VALUE v;
776  int i;
777 
778  prefix_seq = set_create_sequence (num_attrs);
779 
780  if (prefix_seq == NULL)
781  {
782  return NULL;
783  }
784 
785  for (i = 0; i < num_attrs; i++)
786  {
787  if (attrs_prefix_length != NULL)
788  {
789  db_make_int (&v, attrs_prefix_length[i]);
790  }
791  else
792  {
793  db_make_int (&v, -1);
794  }
795 
796  set_put_element (prefix_seq, i, &v);
797  }
798 
799  return prefix_seq;
800 
801 }
802 
803 /*
804  * classobj_make_index_attr_prefix_seq() - Make sequence which contains filter predicate
805  * return: sequence
806  * filter_index_info(in): filter predicate
807  */
808 static DB_SEQ *
810 {
811  DB_SEQ *pred_seq = NULL;
812  DB_VALUE value;
813  DB_SEQ *att_seq = NULL;
814  int i;
815 
816  if (filter_index_info == NULL)
817  {
818  return NULL;
819  }
820 
821  pred_seq = set_create_sequence (3);
822  if (pred_seq == NULL)
823  {
824  return NULL;
825  }
826 
827  att_seq = set_create_sequence (0);
828  if (att_seq == NULL)
829  {
830  set_free (pred_seq);
831  return NULL;
832  }
833 
834  if (filter_index_info->pred_string)
835  {
836  db_make_string (&value, filter_index_info->pred_string);
837  }
838  else
839  {
840  db_make_null (&value);
841  }
842  set_put_element (pred_seq, 0, &value);
843 
844  if (filter_index_info->pred_stream)
845  {
846  db_make_char (&value, filter_index_info->pred_stream_size, filter_index_info->pred_stream,
848  }
849  else
850  {
851  db_make_null (&value);
852  }
853  set_put_element (pred_seq, 1, &value);
854 
855  /* attribute ids */
856  for (i = 0; i < filter_index_info->num_attrs; i++)
857  {
858  db_make_int (&value, filter_index_info->att_ids[i]);
859  set_put_element (att_seq, i, &value);
860  }
861 
862  db_make_sequence (&value, att_seq);
863  set_put_element (pred_seq, 2, &value);
864  pr_clear_value (&value);
865 
866  return pred_seq;
867 }
868 
869 static void
870 classobj_put_value_and_iterate (DB_SEQ * destination, int &index, DB_VALUE & value)
871 {
872  set_put_element (destination, index, &value);
873  pr_clear_value (&value);
874 
875  // increment index
876  ++index;
877 }
878 
879 static int
880 classobj_put_seq_and_iterate (DB_SEQ * destination, int &index, DB_SEQ * element)
881 {
882  if (element == NULL)
883  {
884  // assert (false); // is this acceptable?
885  return ER_FAILED;
886  }
887 
888  DB_VALUE elem_dbval;
889  if (db_make_sequence (&elem_dbval, element) != NO_ERROR)
890  {
891  assert (false); // should not happen
892  return ER_FAILED;
893  }
894 
895  classobj_put_value_and_iterate (destination, index, elem_dbval);
896  return NO_ERROR;
897 }
898 
899 static int
900 classobj_put_seq_with_name_and_iterate (DB_SEQ * destination, int &index, const char *name, DB_SEQ * seq)
901 {
902  // we make a sequence with name and seq and add that to destination
903  DB_SEQ *subseq = set_create_sequence (0);
904  if (subseq == NULL)
905  {
906  return ER_FAILED;
907  }
908 
909  DB_VALUE value;
910  int subseq_index = 0;
911  int error_code = NO_ERROR;
912 
913  db_make_string (&value, name);
914  classobj_put_value_and_iterate (subseq, subseq_index, value);
915 
916  error_code = classobj_put_seq_and_iterate (subseq, subseq_index, seq);
917  if (error_code != NO_ERROR)
918  {
919  set_free (subseq);
920  return error_code;
921  }
922 
923  // now put built sequence into destination
924  error_code = classobj_put_seq_and_iterate (destination, index, subseq);
925  if (error_code != NO_ERROR)
926  {
927  set_free (subseq);
928  return error_code;
929  }
930 
931  return NO_ERROR;
932 }
933 
934 /*
935  * classobj_put_index() - This is used to put and update indexes on the property list.
936  * The property list is composed of name/value pairs. For unique
937  * indexes, this will be SM_PROPERTY_UNIQUE/{uniques} where {uniques}
938  * are another property list of unique instances. The general form
939  * is;
940  * {"*U",
941  * {
942  * "name",
943  * {
944  * "volid|pageid|fileid",
945  * ["attr", asc_desc]+ {fk_info},
946  * "pred_expression",
947  * "comment"
948  * },
949  * "name",
950  * {
951  * "volid|pageid|fileid",
952  * ["attr", asc_desc]+ {fk_info},
953  * "pred_expression",
954  * "comment"
955  * }
956  * }
957  * }
958  * Until we fully support named constraints, use the attribute name as
959  * the constraint name. Each constraint instance must be uniquely named.
960  * An old value will be overwritten with a new value with the same name.
961  * return: non-zero if property was replaced
962  * properties(out):
963  * type(in):
964  * constraint_name(in):
965  * atts(in): attribute list
966  * asc_desc: asc/desc info list
967  * attr_prefix_length:
968  * id(in): new index value
969  * filter_index_info(in):
970  * fk_info(in):
971  * shared_cons_name(in):
972  * func_index_info(in):
973  * comment(in):
974  */
975 int
976 classobj_put_index (DB_SEQ ** properties, SM_CONSTRAINT_TYPE type, const char *constraint_name, SM_ATTRIBUTE ** atts,
977  const int *asc_desc, const int *attr_prefix_length, const BTID * id,
978  SM_PREDICATE_INFO * filter_index_info, SM_FOREIGN_KEY_INFO * fk_info, char *shared_cons_name,
979  SM_FUNCTION_INFO * func_index_info, const char *comment, SM_INDEX_STATUS index_status,
980  bool attr_name_instead_of_id)
981 {
982  int i;
983  const char *prop_name = classobj_map_constraint_to_property (type);
984  DB_VALUE pvalue, value;
985  DB_SEQ *unique_property = NULL, *constraint = NULL;
986  int found = 0;
987  bool is_new_created = false; /* Is *properties new created or not */
988  char buf[128], *pbuf;
989  int constraint_seq_index;
990  int num_attrs = 0;
991 
992  db_make_null (&pvalue);
993  db_make_null (&value);
994 
995  /*
996  * If the property pointer is NULL, create an empty property sequence
997  */
998  if (*properties == NULL)
999  {
1000  *properties = classobj_make_prop ();
1001  if (*properties == NULL)
1002  {
1003  goto error;
1004  }
1005 
1006  is_new_created = true;
1007  }
1008 
1009  /*
1010  * Get a copy of the existing UNIQUE property value. If one
1011  * doesn't exist, create a new one.
1012  */
1013  found = classobj_get_prop (*properties, prop_name, &pvalue);
1014 
1015  if (found)
1016  {
1017  unique_property = db_get_set (&pvalue);
1018  }
1019  else
1020  {
1021  unique_property = set_create_sequence (0);
1022  if (unique_property == NULL)
1023  {
1024  goto error;
1025  }
1026  }
1027 
1028  /* Create a sequence that will hold a constraint instance
1029  * i.e. constraint_name {unique BTID, attribute_name(s)} */
1030  constraint = set_create_sequence (2);
1031  if (constraint == NULL)
1032  {
1033  goto error;
1034  }
1035 
1036  constraint_seq_index = 0; /* init */
1037 
1038  /* Fill the BTID into the sequence */
1039  if ((id == NULL || BTID_IS_NULL (id)) && shared_cons_name != NULL)
1040  {
1041  size_t len = strlen (shared_cons_name) + 10;
1042 
1043  pbuf = (char *) malloc (len);
1044  if (pbuf)
1045  {
1046  sprintf (pbuf, "SHARED:%s", shared_cons_name);
1047  }
1048  else
1049  {
1051  goto error;
1052  }
1053  }
1054  else
1055  {
1056  pbuf = &(buf[0]);
1057  if (id != NULL)
1058  {
1059  sprintf (pbuf, "%d|%d|%d", (int) id->vfid.volid, (int) id->vfid.fileid, (int) id->root_pageid);
1060  }
1061  else
1062  {
1063  sprintf (pbuf, "%d|%d|%d", (int) NULL_VOLID, (int) NULL_FILEID, (int) NULL_PAGEID);
1064  }
1065  }
1066 
1067  db_make_string (&value, pbuf);
1068  classobj_put_value_and_iterate (constraint, constraint_seq_index, value);
1069 
1070  if (pbuf && pbuf != &(buf[0]))
1071  {
1072  free_and_init (pbuf);
1073  }
1074 
1075  /* Fill the indexed attributes into the sequence */
1076  for (i = 0, num_attrs = 0; atts[i] != NULL; i++, num_attrs++)
1077  {
1078  if (attr_name_instead_of_id)
1079  {
1080  /* name */
1081  db_make_string (&value, atts[i]->header.name);
1082  }
1083  else
1084  {
1085  /* id */
1086  db_make_int (&value, atts[i]->id);
1087  }
1088  classobj_put_value_and_iterate (constraint, constraint_seq_index, value);
1089 
1090  /* asc_desc */
1091  db_make_int (&value, asc_desc ? asc_desc[i] : 0);
1092  classobj_put_value_and_iterate (constraint, constraint_seq_index, value);
1093  }
1094 
1095  if (type == SM_CONSTRAINT_FOREIGN_KEY)
1096  {
1097  if (classobj_put_seq_and_iterate (constraint, constraint_seq_index, classobj_make_foreign_key_info_seq (fk_info))
1098  != NO_ERROR)
1099  {
1100  goto error;
1101  }
1102  }
1103  else if (type == SM_CONSTRAINT_PRIMARY_KEY)
1104  {
1105  SM_FOREIGN_KEY_INFO *fk;
1106  int num_live_fk = 0;
1107 
1108  for (fk = fk_info; fk != NULL; fk = fk->next)
1109  {
1110  if (!fk->is_dropped)
1111  {
1112  num_live_fk++;
1113  }
1114  }
1115 
1116  if (0 < num_live_fk)
1117  {
1118  // create subset sequence for all foreign key references
1119  DB_SEQ *fk_container = set_create_sequence (1);
1120 
1121  if (fk_container == NULL)
1122  {
1123  goto error;
1124  }
1125 
1126  int fk_index = 0;
1127  for (fk = fk_info; fk; fk = fk->next)
1128  {
1129  if (fk->is_dropped)
1130  {
1131  continue;
1132  }
1133 
1134  if (classobj_put_seq_and_iterate (fk_container, fk_index,
1136  {
1137  set_free (fk_container);
1138  goto error;
1139  }
1140  }
1141  assert (num_live_fk == fk_index);
1142 
1143  // put fk sequence into constraint sequence
1144  if (classobj_put_seq_and_iterate (constraint, constraint_seq_index, fk_container) != NO_ERROR)
1145  {
1146  set_free (fk_container);
1147  goto error;
1148  }
1149  fk_container = NULL;
1150  }
1151  }
1152  else
1153  {
1154  if (filter_index_info == NULL && func_index_info == NULL)
1155  {
1156  /* prefix length */
1157  if (classobj_put_seq_and_iterate (constraint, constraint_seq_index,
1158  classobj_make_index_attr_prefix_seq (num_attrs, attr_prefix_length))
1159  != NO_ERROR)
1160  {
1161  goto error;
1162  }
1163  }
1164  else
1165  {
1166  int seq_index = 0;
1167  DB_SEQ *seq = set_create_sequence (0);
1168 
1169  if (seq == NULL)
1170  {
1171  goto error;
1172  }
1173 
1174  if (filter_index_info != NULL)
1175  {
1177  classobj_make_index_filter_pred_seq (filter_index_info))
1178  != NO_ERROR)
1179  {
1180  set_free (seq);
1181  goto error;
1182  }
1183 
1186  attr_prefix_length))
1187  != NO_ERROR)
1188  {
1189  set_free (seq);
1190  goto error;
1191  }
1192  }
1193 
1194  if (func_index_info != NULL)
1195  {
1197  classobj_make_function_index_info_seq (func_index_info))
1198  != NO_ERROR)
1199  {
1200  set_free (seq);
1201  goto error;
1202  }
1203  }
1204 
1205  // now put seq into constraint
1206  if (classobj_put_seq_and_iterate (constraint, constraint_seq_index, seq) != NO_ERROR)
1207  {
1208  set_free (seq);
1209  goto error;
1210  }
1211 
1212  // ok
1213  }
1214  }
1215 
1216  /* add index status. */
1217  db_make_int (&value, index_status);
1218  classobj_put_value_and_iterate (constraint, constraint_seq_index, value);
1219 
1220  /* comment */
1221  db_make_string (&value, comment);
1222  classobj_put_value_and_iterate (constraint, constraint_seq_index, value);
1223 
1224  /* Append the constraint to the unique property sequence */
1225  db_make_sequence (&value, constraint);
1226  constraint = NULL;
1227  classobj_put_prop (unique_property, constraint_name, &value);
1228  pr_clear_value (&value);
1229 
1230  /* Put/Replace the unique property */
1231  db_make_sequence (&value, unique_property);
1232  unique_property = NULL;
1233  classobj_put_prop (*properties, prop_name, &value);
1234  pr_clear_value (&value);
1235 
1236  if (found)
1237  {
1238  pr_clear_value (&pvalue);
1239  }
1240 
1241  /* Just to be sure. */
1242  pr_clear_value (&value);
1243 
1244  return NO_ERROR;
1245 
1246 error:
1247 
1248  if (is_new_created && *properties != NULL)
1249  {
1250  set_free (*properties);
1251  }
1252 
1253  if (found)
1254  {
1255  pr_clear_value (&pvalue);
1256  }
1257  else
1258  {
1259  if (unique_property != NULL)
1260  {
1261  set_free (unique_property);
1262  }
1263  }
1264 
1265  if (constraint != NULL)
1266  {
1267  set_free (constraint);
1268  }
1269 
1270  return ER_FAILED;
1271 }
1272 
1273 /*
1274  * classobj_is_exist_foreign_key_ref()
1275  * return:
1276  * refop(in):
1277  * fk_info(in):
1278  */
1279 
1280 bool
1282 {
1283  SM_CLASS *ref_cls;
1284  SM_CLASS_CONSTRAINT *pk;
1285  SM_FOREIGN_KEY_INFO *fk_ref;
1286  int error = NO_ERROR;
1287 
1288  error = au_fetch_class_force (refop, &ref_cls, AU_FETCH_READ);
1289  if (error != NO_ERROR)
1290  {
1291  return false;
1292  }
1293 
1294  pk = classobj_find_class_primary_key (ref_cls);
1295  if (pk == NULL)
1296  {
1297  return false;
1298  }
1299 
1300  for (fk_ref = pk->fk_info; fk_ref; fk_ref = fk_ref->next)
1301  {
1302  if (OID_EQ (&fk_ref->self_oid, &fk_info->self_oid))
1303  {
1304  if (BTID_IS_EQUAL (&(fk_ref->self_btid), &(fk_info->self_btid))
1305  /* although enough to BTID_IS_EQUAL, check for full match BTID structure */
1306  && (fk_ref->self_btid.root_pageid == fk_info->self_btid.root_pageid))
1307  {
1308  return true;
1309  }
1310  }
1311  }
1312 
1313  return false;
1314 }
1315 
1316 
1317 /*
1318  * classobj_is_pk_refer_other()
1319  * return:
1320  * clsop(in):
1321  * fk_info(in):
1322  * include_self_ref(in): include the class where PK is defined
1323  */
1324 
1325 bool
1326 classobj_is_pk_referred (MOP clsop, SM_FOREIGN_KEY_INFO * fk_info, bool include_self_ref, char **fk_name)
1327 {
1328  if (fk_name != NULL)
1329  {
1330  *fk_name = NULL;
1331  }
1332 
1333  if (include_self_ref)
1334  {
1335  if (fk_info != NULL)
1336  {
1337  if (fk_name != NULL)
1338  {
1339  *fk_name = fk_info->name;
1340  }
1341 
1342  return true;
1343  }
1344  else
1345  {
1346  return false;
1347  }
1348  }
1349  else
1350  {
1351  SM_FOREIGN_KEY_INFO *fk_ref;
1352  OID *cls_oid;
1353 
1354  cls_oid = ws_oid (clsop);
1355 
1356  for (fk_ref = fk_info; fk_ref; fk_ref = fk_ref->next)
1357  {
1358  if (!OID_EQ (&fk_ref->self_oid, cls_oid))
1359  {
1360  if (fk_name != NULL)
1361  {
1362  *fk_name = fk_ref->name;
1363  }
1364 
1365  return true;
1366  }
1367  }
1368 
1369  return false;
1370  }
1371 }
1372 
1373 /*
1374  * classobj_put_foreign_key_ref()
1375  * return: NO_ERROR on success, non-zero for ERROR
1376  * properties(in/out):
1377  * fk_info(in):
1378  */
1379 
1380 int
1382 {
1383  DB_VALUE prop_val, pk_val, fk_container_val, fk_val;
1384  DB_SEQ *pk_property, *pk_seq, *fk_container, *fk_seq;
1385  int size;
1386  int fk_container_pos, pk_seq_pos;
1387  int err = NO_ERROR;
1388 
1389  PRIM_SET_NULL (&prop_val);
1390  PRIM_SET_NULL (&pk_val);
1391  PRIM_SET_NULL (&fk_container_val);
1392  PRIM_SET_NULL (&fk_val);
1393 
1394  if (classobj_get_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) <= 0)
1395  {
1396  assert (er_errid () != NO_ERROR);
1397  return er_errid ();
1398  }
1399 
1400  pk_property = db_get_set (&prop_val);
1401  err = set_get_element (pk_property, 1, &pk_val);
1402  if (err != NO_ERROR)
1403  {
1404  goto end;
1405  }
1406 
1407  pk_seq = db_get_set (&pk_val);
1408  size = set_size (pk_seq);
1409 
1410  err = set_get_element (pk_seq, size - 3, &fk_container_val);
1411  if (err != NO_ERROR)
1412  {
1413  goto end;
1414  }
1415 
1416  if (DB_VALUE_TYPE (&fk_container_val) == DB_TYPE_SEQUENCE)
1417  {
1418  fk_container = db_get_set (&fk_container_val);
1419  fk_container_pos = set_size (fk_container);
1420  pk_seq_pos = size - 3;
1421  }
1422  else
1423  {
1424  fk_container = set_create_sequence (1);
1425  if (fk_container == NULL)
1426  {
1427  goto end;
1428  }
1429  db_make_sequence (&fk_container_val, fk_container);
1430  fk_container_pos = 0;
1431  pk_seq_pos = size - 2;
1432  }
1433 
1434  fk_seq = classobj_make_foreign_key_ref_seq (fk_info);
1435  if (fk_seq == NULL)
1436  {
1437  goto end;
1438  }
1439 
1440  db_make_sequence (&fk_val, fk_seq);
1441  err = set_put_element (fk_container, fk_container_pos, &fk_val);
1442  if (err != NO_ERROR)
1443  {
1444  goto end;
1445  }
1446 
1447  if (pk_seq_pos == size - 3)
1448  {
1449  err = set_put_element (pk_seq, pk_seq_pos, &fk_container_val);
1450  if (err != NO_ERROR)
1451  {
1452  goto end;
1453  }
1454  }
1455  else
1456  {
1457  /* retrieve the last element */
1458  DB_VALUE save_last;
1459  PRIM_SET_NULL (&save_last);
1460  err = set_get_element (pk_seq, size - 1, &save_last);
1461  if (err != NO_ERROR)
1462  {
1463  pr_clear_value (&save_last);
1464  goto end;
1465  }
1466 
1467  /* Retrieve status. */
1468  DB_VALUE save_status;
1469  PRIM_SET_NULL (&save_status);
1470  err = set_get_element (pk_seq, size - 2, &save_status);
1471  if (err != NO_ERROR)
1472  {
1473  pr_clear_value (&save_status);
1474  goto end;
1475  }
1476  /* put fk_container */
1477  err = set_put_element (pk_seq, pk_seq_pos, &fk_container_val);
1478  if (err != NO_ERROR)
1479  {
1480  pr_clear_value (&save_last);
1481  goto end;
1482  }
1483 
1484  /* Put the status now. */
1485  err = set_put_element (pk_seq, pk_seq_pos + 1, &save_status);
1486  if (err != NO_ERROR)
1487  {
1488  pr_clear_value (&save_last);
1489  goto end;
1490  }
1491 
1492  /* put the last element to the tail */
1493  err = set_put_element (pk_seq, pk_seq_pos + 2, &save_last);
1494  if (err != NO_ERROR)
1495  {
1496  pr_clear_value (&save_last);
1497  goto end;
1498  }
1499  }
1500 
1501  err = set_put_element (pk_property, 1, &pk_val);
1502  if (err != NO_ERROR)
1503  {
1504  goto end;
1505  }
1506 
1507  if (classobj_put_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) == 0)
1508  {
1509  assert (er_errid () != NO_ERROR);
1510  err = er_errid ();
1511  goto end;
1512  }
1513 
1514 end:
1515  pr_clear_value (&prop_val);
1516  pr_clear_value (&pk_val);
1517  pr_clear_value (&fk_container_val);
1518  pr_clear_value (&fk_val);
1519 
1520  return err;
1521 }
1522 
1523 #if defined (ENABLE_RENAME_CONSTRAINT)
1524 /*
1525  * classobj_rename_foreign_key_ref()
1526  *
1527  * return: NO_ERROR on success, non-zero for ERROR
1528  * properties(in/out):
1529  * btid(in): The BTID of the constraint which needs rename.
1530  * old_name(in): The old constraint name.
1531  * new_name(in): The new constraint name.
1532  */
1533 int
1534 classobj_rename_foreign_key_ref (DB_SEQ ** properties, const BTID * btid, const char *old_name, const char *new_name)
1535 {
1536  DB_VALUE prop_val, pk_val, fk_container_val;
1537  DB_VALUE fk_val, new_fk_val;
1538  DB_VALUE name_val, new_name_val;
1539  DB_VALUE btid_val;
1540  DB_SEQ *pk_property, *pk_seq, *fk_container, *fk_seq = NULL;
1541  int size;
1542  int fk_container_pos, pk_seq_pos;
1543  int err = NO_ERROR;
1544  int fk_container_len;
1545  int i;
1546  int volid, pageid, fileid;
1547  char *name = NULL;
1548  int found = 0;
1549 
1550  PRIM_SET_NULL (&prop_val);
1551  PRIM_SET_NULL (&pk_val);
1552  PRIM_SET_NULL (&fk_container_val);
1553  PRIM_SET_NULL (&fk_val);
1554  PRIM_SET_NULL (&new_fk_val);
1555  PRIM_SET_NULL (&new_name_val);
1556 
1557  if (classobj_get_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) <= 0)
1558  {
1559  err = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
1560  return err;
1561  }
1562 
1563  pk_property = db_get_set (&prop_val);
1564  err = set_get_element (pk_property, 1, &pk_val);
1565  if (err != NO_ERROR)
1566  {
1567  goto end;
1568  }
1569 
1570  pk_seq = db_get_set (&pk_val);
1571  size = set_size (pk_seq);
1572 
1573  err = set_get_element (pk_seq, size - 2, &fk_container_val);
1574  if (err != NO_ERROR)
1575  {
1576  goto end;
1577  }
1578 
1579  if (DB_VALUE_TYPE (&fk_container_val) == DB_TYPE_SEQUENCE)
1580  {
1581  fk_container = db_get_set (&fk_container_val);
1582  fk_container_len = set_size (fk_container);
1583  pk_seq_pos = size - 2;
1584 
1585  /* find the position of the existing FK ref */
1586  for (i = 0; i < fk_container_len; i++)
1587  {
1588  PRIM_SET_NULL (&fk_val);
1589  PRIM_SET_NULL (&name_val);
1590 
1591  err = set_get_element (fk_container, i, &fk_val);
1592  if (err != NO_ERROR)
1593  {
1594  goto end;
1595  }
1596 
1597  fk_seq = db_get_set (&fk_val);
1598 
1599  /* A shallow copy for btid_val is enough. So, no need pr_clear_val(&btid_val). */
1600  err = set_get_element_nocopy (fk_seq, 1, &btid_val);
1601  if (err != NO_ERROR)
1602  {
1603  goto end;
1604  }
1605 
1606  if (classobj_decompose_property_oid (db_get_string (&btid_val), &volid, &fileid, &pageid) != 3)
1607  {
1608  err = ER_SM_INVALID_PROPERTY;
1610  goto end;
1611  }
1612 
1613  /* A shallow copy for name_val is enough. So, no need pr_clear_val(&name_val). */
1614  err = set_get_element_nocopy (fk_seq, 4, &name_val);
1615  if (err != NO_ERROR)
1616  {
1617  goto end;
1618  }
1619 
1620  if (DB_VALUE_TYPE (&name_val) != DB_TYPE_STRING)
1621  {
1622  err = ER_SM_INVALID_PROPERTY;
1624  goto end;
1625  }
1626 
1627  name = db_get_string (&name_val);
1628 
1629  if (btid->vfid.volid == volid && btid->vfid.fileid == fileid && btid->root_pageid == pageid
1630  && old_name != NULL && name != NULL && SM_COMPARE_NAMES (old_name, name) == 0)
1631  {
1632  fk_container_pos = i;
1633 
1634  db_make_string (&new_name_val, new_name);
1635 
1636  err = set_put_element (fk_seq, 4, &new_name_val);
1637  if (err != NO_ERROR)
1638  {
1639  goto end;
1640  }
1641 
1642  found = 1;
1643  break;
1644  }
1645  else
1646  {
1647  /* This fk_val is not the one we need. */
1648  pr_clear_value (&fk_val);
1649  }
1650  }
1651  }
1652 
1653  if (!found)
1654  {
1655  assert (false);
1656 
1657  err = ER_SM_INVALID_PROPERTY;
1659  goto end;
1660  }
1661 
1662  db_make_sequence (&new_fk_val, fk_seq);
1663 
1664  err = set_put_element (fk_container, fk_container_pos, &new_fk_val);
1665  if (err != NO_ERROR)
1666  {
1667  goto end;
1668  }
1669 
1670  err = set_put_element (pk_seq, pk_seq_pos, &fk_container_val);
1671  if (err != NO_ERROR)
1672  {
1673  goto end;
1674  }
1675 
1676  err = set_put_element (pk_property, 1, &pk_val);
1677  if (err != NO_ERROR)
1678  {
1679  goto end;
1680  }
1681 
1682  if (classobj_put_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) == 0)
1683  {
1684  err = (er_errid () != NO_ERROR) ? er_errid () : ER_FAILED;
1685  goto end;
1686  }
1687 
1688 end:
1689  pr_clear_value (&prop_val);
1690  pr_clear_value (&pk_val);
1691  pr_clear_value (&fk_container_val);
1692  pr_clear_value (&fk_val);
1693  pr_clear_value (&new_fk_val);
1694  pr_clear_value (&new_name_val);
1695 
1696  return err;
1697 }
1698 #endif
1699 
1700 /*
1701  * classobj_drop_foreign_key_ref()
1702  * return: NO_ERROR on success, non-zero for ERROR
1703  * properties(in/out):
1704  * btid(in): The BTID of the constraint which needs drop.
1705  * name(in): The constraint name
1706  */
1707 
1708 int
1709 classobj_drop_foreign_key_ref (DB_SEQ ** properties, const BTID * btid, const char *name)
1710 {
1711  int i, fk_container_pos, fk_count;
1712  DB_VALUE prop_val, pk_val, fk_container_val, fk_val, btid_val;
1713  DB_SEQ *pk_property, *pk_seq, *fk_container, *fk_seq;
1714  DB_VALUE cons_name_val;
1715  const char *cons_name = NULL;
1716  int volid, pageid, fileid;
1717  int err = NO_ERROR;
1718 
1719  db_make_null (&prop_val);
1720  db_make_null (&pk_val);
1721  db_make_null (&fk_container_val);
1722  db_make_null (&fk_val);
1723  db_make_null (&btid_val);
1724 
1725  if (classobj_get_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) <= 0)
1726  {
1727  assert (er_errid () != NO_ERROR);
1728  return er_errid ();
1729  }
1730 
1731  pk_property = db_get_set (&prop_val);
1732  err = set_get_element (pk_property, 1, &pk_val);
1733  if (err != NO_ERROR)
1734  {
1735  goto end;
1736  }
1737 
1738  pk_seq = db_get_set (&pk_val);
1739  fk_container_pos = set_size (pk_seq) - 3;
1740 
1741  err = set_get_element (pk_seq, fk_container_pos, &fk_container_val);
1742  if (err != NO_ERROR)
1743  {
1744  goto end;
1745  }
1746 
1747  if (DB_VALUE_TYPE (&fk_container_val) != DB_TYPE_SEQUENCE)
1748  {
1749  err = ER_SM_INVALID_PROPERTY;
1751  goto end;
1752  }
1753 
1754  fk_container = db_get_set (&fk_container_val);
1755  fk_count = set_size (fk_container);
1756 
1757  for (i = 0; i < fk_count; i++)
1758  {
1759  err = set_get_element (fk_container, i, &fk_val);
1760  if (err != NO_ERROR)
1761  {
1762  goto end;
1763  }
1764 
1765  fk_seq = db_get_set (&fk_val);
1766 
1767  err = set_get_element (fk_seq, 1, &btid_val);
1768  if (err != NO_ERROR)
1769  {
1770  goto end;
1771  }
1772 
1773  if (classobj_decompose_property_oid (db_get_string (&btid_val), &volid, &fileid, &pageid) != 3)
1774  {
1775  err = ER_SM_INVALID_PROPERTY;
1777  goto end;
1778  }
1779 
1780  /* A shallow copy for cons_name_val is enough. So, no need pr_clear_val(&cons_name_val). */
1781  err = set_get_element_nocopy (fk_seq, 4, &cons_name_val);
1782  if (err != NO_ERROR)
1783  {
1784  goto end;
1785  }
1786 
1787  if (DB_VALUE_TYPE (&cons_name_val) != DB_TYPE_STRING)
1788  {
1789  err = ER_SM_INVALID_PROPERTY;
1791  goto end;
1792  }
1793 
1794  cons_name = db_get_string (&cons_name_val);
1795 
1796  if (btid->vfid.volid == volid && btid->vfid.fileid == fileid && btid->root_pageid == pageid && name != NULL
1797  && cons_name != NULL && SM_COMPARE_NAMES (name, cons_name) == 0)
1798  {
1799  err = set_drop_seq_element (fk_container, i);
1800  if (err != NO_ERROR)
1801  {
1802  goto end;
1803  }
1804  break;
1805  }
1806 
1807  pr_clear_value (&btid_val);
1808  /* fk_val should clear after cons_name not be used anymore. */
1809  pr_clear_value (&fk_val);
1810  }
1811 
1812  if (set_size (fk_container) < 1)
1813  {
1814  err = set_drop_seq_element (pk_seq, fk_container_pos);
1815  if (err != NO_ERROR)
1816  {
1817  goto end;
1818  }
1819  }
1820  else
1821  {
1822  err = set_put_element (pk_seq, fk_container_pos, &fk_container_val);
1823  if (err != NO_ERROR)
1824  {
1825  goto end;
1826  }
1827  }
1828 
1829  err = set_put_element (pk_property, 1, &pk_val);
1830  if (err != NO_ERROR)
1831  {
1832  goto end;
1833  }
1834 
1835  if (classobj_put_prop (*properties, SM_PROPERTY_PRIMARY_KEY, &prop_val) == 0)
1836  {
1837  assert (er_errid () != NO_ERROR);
1838  err = er_errid ();
1839  goto end;
1840  }
1841 
1842 end:
1843 
1844  pr_clear_value (&prop_val);
1845  pr_clear_value (&pk_val);
1846  pr_clear_value (&fk_container_val);
1847  pr_clear_value (&fk_val);
1848  pr_clear_value (&btid_val);
1849 
1850  return err;
1851 }
1852 
1853 /*
1854  * classobj_find_prop_constraint() - This function is used to find and return
1855  * a constraint from a class property list.
1856  * return: non-zero if property was found
1857  * properties(in): Class property list
1858  * prop_name(in): Class property name
1859  * cnstr_name(in): Class constraint name
1860  * cnstr_val(out): Returned class constraint value
1861  */
1862 
1863 int
1864 classobj_find_prop_constraint (DB_SEQ * properties, const char *prop_name, const char *cnstr_name, DB_VALUE * cnstr_val)
1865 {
1866  DB_VALUE prop_val;
1867  DB_SEQ *prop_seq;
1868  int found = 0;
1869 
1870  db_make_null (&prop_val);
1871  if (classobj_get_prop (properties, prop_name, &prop_val) > 0)
1872  {
1873  prop_seq = db_get_set (&prop_val);
1874  found = classobj_get_prop (prop_seq, cnstr_name, cnstr_val);
1875  }
1876 
1877  pr_clear_value (&prop_val);
1878  return found;
1879 }
1880 
1881 #if defined (ENABLE_RENAME_CONSTRAINT)
1882 /*
1883  * classobj_rename_constraint() - This function is used to rename
1884  * a constraint name.
1885  * return: NO_ERROR on success, non-zero for ERROR
1886  * properties(in): Class property list
1887  * prop_name(in): Class property name
1888  * old_name(in): old constraint name
1889  * new_name(in): new constraint name
1890  */
1891 
1892 int
1893 classobj_rename_constraint (DB_SEQ * properties, const char *prop_name, const char *old_name, const char *new_name)
1894 {
1895  DB_VALUE prop_val, cnstr_val, new_val;
1896  DB_SEQ *prop_seq;
1897  int found = 0;
1898  int error = NO_ERROR;
1899 
1900  db_make_null (&prop_val);
1901  db_make_null (&cnstr_val);
1902  db_make_null (&new_val);
1903 
1904  found = classobj_get_prop (properties, prop_name, &prop_val);
1905  if (found == 0)
1906  {
1908  error = ER_SM_INVALID_PROPERTY;
1909  goto end;
1910  }
1911 
1912  prop_seq = db_get_set (&prop_val);
1913  found = classobj_get_prop (prop_seq, old_name, &cnstr_val);
1914  if (found == 0)
1915  {
1917  error = ER_SM_INVALID_PROPERTY;
1918  goto end;
1919  }
1920 
1921  db_make_string (&new_val, new_name);
1922 
1923  /* found - 1 (should be modified.. It seems to be ambiguous.) */
1924  error = set_put_element (prop_seq, found - 1, &new_val);
1925  if (error != NO_ERROR)
1926  {
1927  goto end;
1928  }
1929 
1930  found = classobj_put_prop (properties, prop_name, &prop_val);
1931  if (found == 0)
1932  {
1934  error = ER_SM_INVALID_PROPERTY;
1935  goto end;
1936  }
1937 
1938 end:
1939  pr_clear_value (&prop_val);
1940  pr_clear_value (&cnstr_val);
1941  pr_clear_value (&new_val);
1942  return error;
1943 }
1944 #endif
1945 
1946 /*
1947  * classobj_change_constraint_comment() - This function is used to change a constraint comment.
1948  * return: NO_ERROR on success, non-zero for ERROR
1949  * properties(in): Class property list
1950  * cons(in): constraint
1951  * comment(in): new comment of property
1952  */
1953 int
1954 classobj_change_constraint_comment (DB_SEQ * properties, SM_CLASS_CONSTRAINT * cons, const char *comment)
1955 {
1956  DB_VALUE prop_val, cnstr_val, curr_comment, new_comment;
1957  DB_SEQ *prop_seq, *idx_seq;
1958  const char *property_type;
1959  int found = 0;
1960  int error = NO_ERROR;
1961  int len = 0;
1962 
1963  assert (properties != NULL && cons != NULL);
1964 
1965  db_make_null (&prop_val);
1966  db_make_null (&cnstr_val);
1967  db_make_null (&curr_comment);
1968  db_make_null (&new_comment);
1969 
1970  property_type = classobj_map_constraint_to_property (cons->type);
1971 
1972  found = classobj_get_prop (properties, property_type, &prop_val);
1973  if (found == 0)
1974  {
1976  error = ER_SM_INVALID_PROPERTY;
1977  goto end;
1978  }
1979 
1980  prop_seq = db_get_set (&prop_val);
1981  found = classobj_get_prop (prop_seq, cons->name, &cnstr_val);
1982  if (found == 0)
1983  {
1985  error = ER_SM_INVALID_PROPERTY;
1986  goto end;
1987  }
1988 
1989  idx_seq = db_get_set (&cnstr_val);
1990  len = set_size (idx_seq);
1991 
1992  /* comment stands at the end of the seq */
1993  set_get_element (idx_seq, len - 1, &curr_comment);
1994  if (!DB_IS_NULL (&curr_comment) && DB_VALUE_TYPE (&curr_comment) != DB_TYPE_STRING)
1995  {
1997  error = ER_SM_INVALID_PROPERTY;
1998  goto end;
1999  }
2000 
2001  db_make_string (&new_comment, comment);
2002  error = set_put_element (idx_seq, len - 1, &new_comment);
2003  if (error != NO_ERROR)
2004  {
2005  goto end;
2006  }
2007 
2008  db_make_sequence (&cnstr_val, idx_seq);
2009  found = classobj_put_prop (prop_seq, cons->name, &cnstr_val);
2010  if (found == 0)
2011  {
2013  error = ER_SM_INVALID_PROPERTY;
2014  goto end;
2015  }
2016 
2017  db_make_sequence (&prop_val, prop_seq);
2018  found = classobj_put_prop (properties, property_type, &prop_val);
2019  if (found == 0)
2020  {
2022  error = ER_SM_INVALID_PROPERTY;
2023  goto end;
2024  }
2025 
2026 end:
2027  pr_clear_value (&prop_val);
2028  pr_clear_value (&cnstr_val);
2029  pr_clear_value (&curr_comment);
2030  pr_clear_value (&new_comment);
2031  return error;
2032 }
2033 
2034 /*
2035  * classobj_btid_from_property_value() - Little helper function to get a btid out of
2036  * a DB_VALUE that was obtained from a property list.
2037  * Note that it is still up to the caller to clear this value when they're
2038  * done with it.
2039  * return: NO_ERROR on success, non-zero for ERROR
2040  * value(in): value containing btid property
2041  * btid(out): btid we extracted
2042  * shared_cons_name(out):
2043  */
2044 
2045 int
2046 classobj_btid_from_property_value (DB_VALUE * value, BTID * btid, char **shared_cons_name)
2047 {
2048  const char *btid_string = NULL;
2049  int volid, pageid, fileid;
2050  int args;
2051 
2052  if (DB_VALUE_TYPE (value) != DB_TYPE_STRING)
2053  {
2054  goto structure_error;
2055  }
2056 
2057  btid_string = db_get_string (value);
2058  if (btid_string == NULL)
2059  {
2060  goto structure_error;
2061  }
2062 
2063  if (strncasecmp ("SHARED:", btid_string, 7) == 0)
2064  {
2065  if (shared_cons_name)
2066  {
2067  *shared_cons_name = strdup (btid_string + 7);
2068  }
2069  }
2070  else
2071  {
2072 
2073  args = classobj_decompose_property_oid (btid_string, &volid, &fileid, &pageid);
2074  if (args != 3)
2075  {
2076  goto structure_error;
2077  }
2078 
2079  btid->vfid.volid = (VOLID) volid;
2080  btid->root_pageid = (PAGEID) pageid;
2081  btid->vfid.fileid = (FILEID) fileid;
2082  }
2083 
2084  return NO_ERROR;
2085 
2086 structure_error:
2087  /* should have a more appropriate error for this */
2089  return er_errid ();
2090 }
2091 
2092 /*
2093  * classobj_oid_from_property_value()
2094  * return: NO_ERROR on success, non-zero for ERROR
2095  * value(in):
2096  * oid(out):
2097  */
2098 
2099 int
2101 {
2102  const char *oid_string;
2103  int volid, pageid, slotid;
2104  int args;
2105 
2106  if (DB_VALUE_TYPE (value) != DB_TYPE_STRING)
2107  {
2108  goto structure_error;
2109  }
2110 
2111  oid_string = db_get_string (value);
2112  if (oid_string == NULL)
2113  {
2114  goto structure_error;
2115  }
2116  args = classobj_decompose_property_oid (oid_string, &pageid, &slotid, &volid);
2117 
2118  if (args != 3)
2119  {
2120  goto structure_error;
2121  }
2122 
2123  oid->pageid = (PAGEID) pageid;
2124  oid->slotid = (PGSLOTID) slotid;
2125  oid->volid = (VOLID) volid;
2126 
2127  return NO_ERROR;
2128 
2129 structure_error:
2130  /* should have a more appropriate error for this */
2132  return er_errid ();
2133 }
2134 
2135 /*
2136  * classobj_get_cached_constraint() - This is used to find a constraint of the given
2137  * type, and return the ID. If the constraint list does not contain
2138  * a constraint of the requested type, a 0 is returned. Non-zero is returned
2139  * if the constraint is found. The value pointed to by id is only
2140  * valid if the function returns non-zero.
2141  * return: non-zero if id was found
2142  * constraints(in): constraint list
2143  * type(in): constraint type
2144  * id(out): pointer to ID
2145  */
2146 int
2148 {
2149  SM_CONSTRAINT *cnstr;
2150  int ok = 0;
2151 
2152  for (cnstr = constraints; cnstr != NULL; cnstr = cnstr->next)
2153  {
2154  if (cnstr->type != type)
2155  {
2156  continue;
2157  }
2158 
2159  if (id != NULL)
2160  {
2161  *id = cnstr->index;
2162  }
2163  ok = 1;
2164  break;
2165 
2166  }
2167 
2168  return ok;
2169 }
2170 
2171 /*
2172  * classobj_has_unique_constraint ()
2173  * return: true if an unique constraint is contained in the constraint list,
2174  * otherwise false.
2175  * constraints(in): constraint list
2176  */
2177 bool
2179 {
2181 
2182  for (c = constraints; c != NULL; c = c->next)
2183  {
2185  {
2186  return true;
2187  }
2188  }
2189 
2190  return false;
2191 }
2192 
2193 /*
2194  * classobj_has_unique_constraint ()
2195  * return: true if an unique constraint is contained in the constraint list,
2196  * otherwise false.
2197  * constraints(in): constraint list
2198  */
2199 bool
2201 {
2202  SM_CONSTRAINT *c;
2203 
2204  for (c = constraints; c != NULL; c = c->next)
2205  {
2207  {
2208  return true;
2209  }
2210  }
2211 
2212  return false;
2213 }
2214 
2215 /*
2216  * classobj_has_function_constraint () - check if has function constraint
2217  * return: true if an function constraint is contained in the
2218  * constraint list, otherwise false.
2219  * constraints(in): constraint list
2220  */
2221 bool
2223 {
2224  SM_CONSTRAINT *c;
2225 
2226  for (c = constraints; c != NULL; c = c->next)
2227  {
2228  if (c->has_function)
2229  {
2230  return true;
2231  }
2232  }
2233 
2234  return false;
2235 }
2236 
2237 /* SM_CONSTRAINT */
2238 /*
2239  * classobj_make_constraint() - Creates a new constraint node.
2240  * return: new constraint structure
2241  * name(in): Constraint name
2242  * type(in): Constraint type
2243  * id(in): Unique BTID
2244  * has_function_constraint(in): true if is function constraint
2245  */
2246 
2247 static SM_CONSTRAINT *
2248 classobj_make_constraint (const char *name, SM_CONSTRAINT_TYPE type, BTID * id, bool has_function_constraint)
2249 {
2250  SM_CONSTRAINT *constraint;
2251 
2252  constraint = (SM_CONSTRAINT *) db_ws_alloc (sizeof (SM_CONSTRAINT));
2253 
2254  if (constraint == NULL)
2255  {
2256  return NULL;
2257  }
2258 
2259  constraint->next = NULL;
2260  constraint->name = ws_copy_string (name);
2261  constraint->type = type;
2262  constraint->index = *id;
2263  constraint->has_function = has_function_constraint;
2264 
2265  if (name && !constraint->name)
2266  {
2267  classobj_free_constraint (constraint);
2268  return NULL;
2269  }
2270 
2271  return constraint;
2272 }
2273 
2274 /*
2275  * classobj_free_constraint() - Frees an constraint structure and all memory
2276  * associated with a constraint node.
2277  * return: none
2278  * constraint(in): Pointer to constraint node
2279  */
2280 
2281 static void
2283 {
2284  if (constraint == NULL)
2285  {
2286  return;
2287  }
2288 
2289  if (constraint->next)
2290  {
2291  classobj_free_constraint (constraint->next);
2292  }
2293 
2294  if (constraint->name)
2295  {
2296  db_ws_free (constraint->name);
2297  }
2298 
2299  db_ws_free (constraint);
2300 }
2301 
2302 /*
2303  * classobj_constraint_size() - Calculates the total number of bytes occupied by
2304  * the constraint list.
2305  * return: size of constraint list
2306  * constraint(in): Pointer to constraint list
2307  */
2308 
2309 static int
2311 {
2312  return sizeof (SM_CONSTRAINT);
2313 }
2314 
2315 /*
2316  * classobj_cache_constraint_entry() - Cache the constraint entry on the caches of
2317  * the associated attributes.
2318  * return: true if constraint entry was cached
2319  * name(in): Constraint name
2320  * constraint_seq(in): Constraint entry. This is a sequence of the form:
2321  * {
2322  * "B-tree ID",
2323  * [ "att_name", "asc_dsc", ]
2324  * [ "att_name", "asc_dsc", ]
2325  * {fk_info | pk_info | prefix_length}
2326  * "filter_predicate",
2327  * "comment"
2328  * }
2329  * class(in): Class pointer.
2330  * constraint_type(in):
2331  */
2332 
2333 static bool
2334 classobj_cache_constraint_entry (const char *name, DB_SEQ * constraint_seq, SM_CLASS * class_,
2335  SM_CONSTRAINT_TYPE constraint_type)
2336 {
2337  int error;
2338  int i, e, info_len, att_cnt;
2339  BTID id;
2340  DB_VALUE id_val, att_val;
2341  SM_ATTRIBUTE *att;
2342  SM_CONSTRAINT *ptr;
2343  bool ok = true;
2344  bool has_function_constraint = false;
2345 
2346  /*
2347  * Extract the first element of the sequence which is the
2348  * encoded B-tree ID
2349  */
2350  info_len = set_size (constraint_seq);
2351  att_cnt = (info_len - 3) / 2; /* excludes BTID, status and comment */
2352  e = 0;
2353 
2354  /* get the btid */
2355  error = set_get_element (constraint_seq, e++, &id_val);
2356  if (error != NO_ERROR)
2357  {
2358  goto finish;
2359  }
2360 
2361  if (classobj_btid_from_property_value (&id_val, &id, NULL))
2362  {
2363  pr_clear_value (&id_val);
2364  goto finish;
2365  }
2366 
2367  /*
2368  * Assign the B-tree ID.
2369  * Loop over the attribute names in the constraint and cache
2370  * the constraint in those attributes.
2371  */
2372  for (i = 0; i < att_cnt && ok; i++)
2373  {
2374  /* name( or id) */
2375  error = set_get_element (constraint_seq, e++, &att_val);
2376  if (error == NO_ERROR)
2377  {
2378  att = NULL;
2379  if (DB_VALUE_TYPE (&att_val) == DB_TYPE_STRING && db_get_string (&att_val) != NULL)
2380  {
2381  att = classobj_find_attribute (class_, db_get_string (&att_val), 0);
2382  }
2383  else if (DB_VALUE_TYPE (&att_val) == DB_TYPE_INTEGER)
2384  {
2385  att = classobj_find_attribute_id (class_, db_get_int (&att_val), 0);
2386  }
2387  if (att != NULL)
2388  {
2389  if (constraint_type == SM_CONSTRAINT_INDEX || constraint_type == SM_CONSTRAINT_REVERSE_INDEX
2390  || constraint_type == SM_CONSTRAINT_UNIQUE || constraint_type == SM_CONSTRAINT_REVERSE_UNIQUE)
2391  {
2392  if (classobj_check_function_constraint_info (constraint_seq, &has_function_constraint) != NO_ERROR)
2393  {
2394  pr_clear_value (&att_val);
2395  pr_clear_value (&id_val);
2396  ok = false;
2397  goto finish;
2398  }
2399  }
2400 
2401  /*
2402  * Add a new constraint node to the cache list
2403  */
2404  ptr = classobj_make_constraint (name, constraint_type, &id, has_function_constraint);
2405  if (ptr == NULL)
2406  {
2407  ok = false;
2408  }
2409  else
2410  {
2411  if (att->constraints == NULL)
2412  {
2413  att->constraints = ptr;
2414  }
2415  else
2416  {
2417  ptr->next = att->constraints;
2418  att->constraints = ptr;
2419  }
2420  }
2421  }
2422  }
2423 
2424  pr_clear_value (&att_val);
2425 
2426  /* asc_desc */
2427  e++;
2428  }
2429 
2430  pr_clear_value (&id_val);
2431 
2432 finish:
2433  return ok;
2434 }
2435 
2436 
2437 /*
2438  * classobj_cache_constraint_list() - Cache the constraint list into the appropriate
2439  * attribute caches
2440  * return: non-zero if constraint list was cached
2441  * seq(in): Unique constraint list. This is a sequence of constraint
2442  * name/ID pairs of the form:
2443  * {
2444  * { "name", "filter_predicate", { btid, att_nam(s)..}, ... },
2445  * { "name", "filter_predicate", { btid, att_nam(s)..}, ... },
2446  * {fk_info | pk_info | prefix_length}
2447  * "filter_predicate"
2448  * }
2449  * class(in): Class pointer
2450  * constraint_type(in):
2451  */
2452 
2453 static bool
2455 {
2456  int i, max;
2457  DB_VALUE ids_val, name_val;
2458  DB_SEQ *ids_seq;
2459 
2460  int error = NO_ERROR;
2461  bool ok = true;
2462 
2463  /* Make sure that the DB_VALUES are initialized */
2464  db_make_null (&ids_val);
2465  db_make_null (&name_val);
2466 
2467  max = set_size (seq);
2468  for (i = 0; i < max && error == NO_ERROR && ok; i += 2)
2469  {
2470  /* Get the constraint name */
2471  error = set_get_element (seq, i, &name_val);
2472  if (error != NO_ERROR)
2473  {
2474  continue;
2475  }
2476  /* get the constraint value sequence */
2477  error = set_get_element (seq, i + 1, &ids_val);
2478  if (error == NO_ERROR)
2479  {
2480  if (DB_VALUE_TYPE (&ids_val) == DB_TYPE_SEQUENCE)
2481  {
2482  ids_seq = db_get_set (&ids_val);
2483  ok = classobj_cache_constraint_entry (db_get_string (&name_val), ids_seq, class_, constraint_type);
2484  }
2485  pr_clear_value (&ids_val);
2486  }
2487  pr_clear_value (&name_val);
2488  }
2489 
2490  if (error != NO_ERROR)
2491  {
2492  goto error;
2493  }
2494 
2495  return ok;
2496 
2497  /* Error Processing */
2498 error:
2499  pr_clear_value (&ids_val);
2500  pr_clear_value (&name_val);
2501  return 0;
2502 }
2503 
2504 
2505 /*
2506  * classobj_cache_constraints() - Cache the constraint properties from the property
2507  * list into the attribute's constraint structure for faster retrieval.
2508  * return: true if constraint properties were cached
2509  * class(in): Pointer to attribute structure
2510  */
2511 
2512 bool
2514 {
2515  SM_ATTRIBUTE *att;
2516  DB_VALUE un_value;
2517  DB_SEQ *un_seq;
2518  int i;
2519  bool ok = true;
2520  int num_constraint_types = NUM_CONSTRAINT_TYPES;
2521 
2522  /*
2523  * Clear the attribute caches
2524  */
2525  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
2526  {
2527  if (att->constraints)
2528  {
2530  att->constraints = NULL;
2531  }
2532  }
2533 
2534  /*
2535  * Extract the constraint property and process
2536  */
2537  if (class_->properties == NULL)
2538  {
2539  return ok;
2540  }
2541 
2542  for (i = 0; i < num_constraint_types && ok; i++)
2543  {
2544  if (classobj_get_prop (class_->properties, Constraint_properties[i], &un_value) > 0)
2545  {
2546  if (DB_VALUE_TYPE (&un_value) == DB_TYPE_SEQUENCE)
2547  {
2548  un_seq = db_get_set (&un_value);
2549  ok = classobj_cache_constraint_list (un_seq, class_, Constraint_types[i]);
2550  }
2551  pr_clear_value (&un_value);
2552  }
2553  }
2554 
2555  return ok;
2556 }
2557 
2558 /* SM_CLASS_CONSTRAINT */
2559 /*
2560  * classobj_find_attribute_list() - Alternative to classobj_find_attribute when we're
2561  * looking for an attribute on a particular list.
2562  * return: attribute structure
2563  * attlist(in): list of attributes
2564  * name(in): name to look for
2565  * id(in): attribute id
2566  */
2567 
2568 SM_ATTRIBUTE *
2569 classobj_find_attribute_list (SM_ATTRIBUTE * attlist, const char *name, int id)
2570 {
2571  SM_ATTRIBUTE *att;
2572 
2573  for (att = attlist; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
2574  {
2575  if (name != NULL)
2576  {
2577  if (intl_identifier_casecmp (att->header.name, name) == 0)
2578  {
2579  break;
2580  }
2581  }
2582  else if (att->id == id)
2583  {
2584  break;
2585  }
2586  }
2587  return att;
2588 }
2589 
2590 /*
2591  * classobj_make_class_constraint() - Allocate and initialize a new constraint
2592  * structure. The supplied name is ours to keep, don't make a copy.
2593  * return: new constraint structure
2594  * name(in): constraint name
2595  * type(in): constraint type
2596  */
2597 
2598 static SM_CLASS_CONSTRAINT *
2600 {
2601  SM_CLASS_CONSTRAINT *new_;
2602 
2603  /* make a new constraint list entry */
2604  new_ = (SM_CLASS_CONSTRAINT *) db_ws_alloc (sizeof (SM_CLASS_CONSTRAINT));
2605  if (new_ == NULL)
2606  {
2607  return NULL;
2608  }
2609 
2610  new_->next = NULL;
2611  new_->name = name;
2612  new_->type = type;
2613  new_->attributes = NULL;
2614  new_->asc_desc = NULL;
2615  new_->attrs_prefix_length = NULL;
2616  BTID_SET_NULL (&new_->index_btid);
2617  new_->fk_info = NULL;
2618  new_->shared_cons_name = NULL;
2619  new_->filter_predicate = NULL;
2620  new_->func_index_info = NULL;
2621  new_->comment = NULL;
2623  new_->index_status = SM_NO_INDEX;
2624 
2625  return new_;
2626 }
2627 
2628 /*
2629  * classobj_free_foreign_key_ref()
2630  * return: none
2631  * fk_info(in):
2632  */
2633 
2634 void
2636 {
2637  SM_FOREIGN_KEY_INFO *p, *next;
2638 
2639  for (p = fk_info; p; p = next)
2640  {
2641  next = p->next;
2642  free_and_init (p->name);
2643  db_ws_free (p);
2644  }
2645 }
2646 
2647 /*
2648  * classobj_free_class_constraints() - Frees a list of class constraint structures
2649  * allocated by classobj_make_class_constraints.
2650  * If we ever get into the situation where SM_CONSTRAINT structures
2651  * point back to these, we'll need to make sure that the
2652  * these are freed LAST.
2653  * return: none
2654  * constraints(in): constraint list
2655  */
2656 
2657 void
2659 {
2660  SM_CLASS_CONSTRAINT *c, *next;
2661 
2662  for (c = constraints, next = NULL; c != NULL; c = next)
2663  {
2664  next = c->next;
2665  ws_free_string (c->name);
2666  ws_free_string (c->comment);
2667  db_ws_free (c->attributes);
2668  db_ws_free (c->asc_desc);
2669  if (c->attrs_prefix_length)
2670  {
2672  }
2673  if (c->func_index_info)
2674  {
2676  }
2678  if (c->filter_predicate)
2679  {
2680  if (c->filter_predicate->pred_stream)
2681  {
2683  }
2684  if (c->filter_predicate->pred_string)
2685  {
2687  }
2688  if (c->filter_predicate->att_ids)
2689  {
2691  }
2693  }
2694 
2695  if (c->fk_info)
2696  {
2697  if (c->type == SM_CONSTRAINT_PRIMARY_KEY)
2698  {
2700  }
2701  else if (c->type == SM_CONSTRAINT_FOREIGN_KEY)
2702  {
2703  db_ws_free (c->fk_info);
2704  }
2705  }
2706 
2707  db_ws_free (c);
2708  }
2709 }
2710 
2711 /*
2712  * classobj_make_foreign_key_info()
2713  * return:
2714  * fk_seq(in):
2715  * cons_name(in):
2716  * attributes(in):
2717  */
2718 
2719 static SM_FOREIGN_KEY_INFO *
2720 classobj_make_foreign_key_info (DB_SEQ * fk_seq, const char *cons_name, SM_ATTRIBUTE * attributes)
2721 {
2722  DB_VALUE fvalue;
2723  SM_FOREIGN_KEY_INFO *fk_info;
2724 
2725  fk_info = (SM_FOREIGN_KEY_INFO *) db_ws_alloc (sizeof (SM_FOREIGN_KEY_INFO));
2726 
2727  if (fk_info == NULL)
2728  {
2729  return NULL;
2730  }
2731 
2732  if (set_get_element (fk_seq, 0, &fvalue))
2733  {
2734  goto error;
2735  }
2736  if (classobj_oid_from_property_value (&fvalue, &fk_info->ref_class_oid))
2737  {
2738  goto error;
2739  }
2740  pr_clear_value (&fvalue);
2741 
2742  if (set_get_element (fk_seq, 1, &fvalue))
2743  {
2744  goto error;
2745  }
2746  if (classobj_btid_from_property_value (&fvalue, &fk_info->ref_class_pk_btid, NULL))
2747  {
2748  goto error;
2749  }
2750  pr_clear_value (&fvalue);
2751 
2752  if (set_get_element (fk_seq, 2, &fvalue))
2753  {
2754  goto error;
2755  }
2756  fk_info->delete_action = (SM_FOREIGN_KEY_ACTION) db_get_int (&fvalue);
2757 
2758  if (set_get_element (fk_seq, 3, &fvalue))
2759  {
2760  goto error;
2761  }
2762  fk_info->update_action = (SM_FOREIGN_KEY_ACTION) db_get_int (&fvalue);
2763 
2764 
2765  fk_info->name = (char *) cons_name;
2766  fk_info->is_dropped = false;
2767  fk_info->next = NULL;
2768 
2769 
2770  return fk_info;
2771 
2772 error:
2773 
2774  if (fk_info)
2775  {
2776  db_ws_free (fk_info);
2777  }
2778 
2779  return NULL;
2780 }
2781 
2782 /*
2783  * classobj_make_foreign_key_ref()
2784  * return:
2785  * fk_seq(in):
2786  */
2787 
2788 static SM_FOREIGN_KEY_INFO *
2790 {
2791  DB_VALUE fvalue;
2792  SM_FOREIGN_KEY_INFO *fk_info;
2793  const char *val_str;
2794 
2795  fk_info = (SM_FOREIGN_KEY_INFO *) db_ws_alloc (sizeof (SM_FOREIGN_KEY_INFO));
2796  if (fk_info == NULL)
2797  {
2798  return NULL;
2799  }
2800 
2801  fk_info->next = NULL;
2802 
2803  if (set_get_element (fk_seq, 0, &fvalue))
2804  {
2805  goto error;
2806  }
2807  if (classobj_oid_from_property_value (&fvalue, &fk_info->self_oid))
2808  {
2809  goto error;
2810  }
2811  pr_clear_value (&fvalue);
2812 
2813  if (set_get_element (fk_seq, 1, &fvalue))
2814  {
2815  goto error;
2816  }
2817  if (classobj_btid_from_property_value (&fvalue, &fk_info->self_btid, NULL))
2818  {
2819  goto error;
2820  }
2821  pr_clear_value (&fvalue);
2822 
2823  if (set_get_element (fk_seq, 2, &fvalue))
2824  {
2825  goto error;
2826  }
2827  fk_info->delete_action = (SM_FOREIGN_KEY_ACTION) db_get_int (&fvalue);
2828 
2829  if (set_get_element (fk_seq, 3, &fvalue))
2830  {
2831  goto error;
2832  }
2833  fk_info->update_action = (SM_FOREIGN_KEY_ACTION) db_get_int (&fvalue);
2834 
2835  if (set_get_element (fk_seq, 4, &fvalue))
2836  {
2837  goto error;
2838  }
2839  val_str = db_get_string (&fvalue);
2840  if (val_str == NULL)
2841  {
2842  goto error;
2843  }
2844  fk_info->name = strdup (val_str);
2845  pr_clear_value (&fvalue);
2846 
2847  fk_info->is_dropped = false;
2848 
2849  return fk_info;
2850 error:
2851 
2852  if (fk_info)
2853  {
2854  db_ws_free (fk_info);
2855  }
2856 
2857  return NULL;
2858 }
2859 
2860 /*
2861  * classobj_make_foreign_key_ref_list()
2862  * return:
2863  * fk_container(in):
2864  */
2865 
2866 static SM_FOREIGN_KEY_INFO *
2868 {
2869  int size, i;
2870  DB_VALUE fkvalue;
2871  SM_FOREIGN_KEY_INFO *list = NULL, *fk_info, *cur = NULL;
2872  DB_SEQ *fk_seq;
2873 
2874  size = set_size (fk_container);
2875 
2876  for (i = 0; i < size; i++)
2877  {
2878  if (set_get_element (fk_container, i, &fkvalue))
2879  {
2880  goto error;
2881  }
2882 
2883  fk_seq = db_get_set (&fkvalue);
2884 
2885  fk_info = classobj_make_foreign_key_ref (fk_seq);
2886  if (fk_info == NULL)
2887  {
2888  goto error;
2889  }
2890 
2891  pr_clear_value (&fkvalue);
2892 
2893  if (i == 0)
2894  {
2895  list = fk_info;
2896  cur = list;
2897  }
2898  else
2899  {
2900  cur->next = fk_info;
2901  cur = cur->next;
2902  }
2903  }
2904 
2905  return list;
2906 
2907 error:
2908  if (list)
2909  {
2911  }
2912 
2913  return NULL;
2914 }
2915 
2916 /*
2917  * classobj_make_index_prefix_info() - Make array which contains
2918  * prefix length
2919  * return: array
2920  * prefix_seq(in): sequence which contains prefix length
2921  * num_attrs(in): key attribute count
2922  */
2923 static int *
2924 classobj_make_index_prefix_info (DB_SEQ * prefix_seq, int num_attrs)
2925 {
2926  DB_VALUE v;
2927  int *prefix_length;
2928  int i;
2929 
2930  assert (prefix_seq != NULL && set_size (prefix_seq) == num_attrs);
2931 
2932  prefix_length = (int *) db_ws_alloc (sizeof (int) * num_attrs);
2933  if (prefix_length == NULL)
2934  {
2935  return NULL;
2936  }
2937 
2938  for (i = 0; i < num_attrs; i++)
2939  {
2940  if (set_get_element_nocopy (prefix_seq, i, &v) != NO_ERROR)
2941  {
2942  db_ws_free (prefix_length);
2943  return NULL;
2944  }
2945 
2946  prefix_length[i] = db_get_int (&v);
2947  }
2948 
2949  return prefix_length;
2950 }
2951 
2952 /*
2953  * classobj_make_index_filter_pred_info() - Make index filter predicate
2954  * from sequence
2955  * return: SM_PREDICATE_INFO *
2956  * pred_seq(in): sequence which contains filter predicate
2957  */
2958 static SM_PREDICATE_INFO *
2960 {
2961  SM_PREDICATE_INFO *filter_predicate = NULL;
2962  DB_VALUE fvalue, avalue, v;
2963  const char *val_str = NULL;
2964  size_t val_str_len = 0;
2965  const char *buffer = NULL;
2966  int buffer_len = 0;
2967  DB_SEQ *att_seq = NULL;
2968  int att_seq_size = 0, i;
2969 
2970  assert (pred_seq != NULL && set_size (pred_seq) == 3);
2971  db_make_null (&avalue);
2972 
2973  if (set_get_element_nocopy (pred_seq, 0, &fvalue) != NO_ERROR)
2974  {
2976  goto error;
2977  }
2978 
2979  if (DB_VALUE_TYPE (&fvalue) == DB_TYPE_NULL)
2980  {
2981  return NULL;
2982  }
2983  assert (DB_VALUE_TYPE (&fvalue) == DB_TYPE_STRING);
2984  if (DB_VALUE_TYPE (&fvalue) != DB_TYPE_STRING)
2985  {
2986  assert (false);
2988  goto error;
2989  }
2990 
2991  val_str = db_get_string (&fvalue);
2992  val_str_len = db_get_string_size (&fvalue);
2993  assert (val_str != NULL);
2994 
2995  filter_predicate = (SM_PREDICATE_INFO *) db_ws_alloc (sizeof (SM_PREDICATE_INFO));
2996  if (filter_predicate == NULL)
2997  {
2998  goto error;
2999  }
3000  if (val_str_len > 0)
3001  {
3002  filter_predicate->pred_string = (char *) db_ws_alloc (val_str_len + 1);
3003  if (filter_predicate->pred_string == NULL)
3004  {
3005  goto error;
3006  }
3007  memset (filter_predicate->pred_string, 0, val_str_len + 1);
3008  memcpy (filter_predicate->pred_string, (val_str), val_str_len);
3009  }
3010 
3011  if (set_get_element_nocopy (pred_seq, 1, &fvalue) != NO_ERROR)
3012  {
3014  goto error;
3015  }
3016 
3017  /* since pred string is not null, pred stream should be not null, also */
3018  if (DB_VALUE_TYPE (&fvalue) != DB_TYPE_CHAR)
3019  {
3021  goto error;
3022  }
3023 
3024  buffer = db_get_string (&fvalue);
3025  buffer_len = db_get_string_size (&fvalue);
3026  filter_predicate->pred_stream = (char *) db_ws_alloc (buffer_len * sizeof (char));
3027  if (filter_predicate->pred_stream == NULL)
3028  {
3029  goto error;
3030  }
3031 
3032  memcpy (filter_predicate->pred_stream, buffer, buffer_len);
3033  filter_predicate->pred_stream_size = buffer_len;
3034 
3035  if (set_get_element (pred_seq, 2, &avalue) != NO_ERROR)
3036  {
3038  goto error;
3039  }
3040 
3041  if (DB_VALUE_TYPE (&avalue) != DB_TYPE_SEQUENCE)
3042  {
3044  goto error;
3045  }
3046 
3047  att_seq = db_get_set (&avalue);
3048  filter_predicate->num_attrs = att_seq_size = set_size (att_seq);
3049  if (att_seq_size == 0)
3050  {
3051  filter_predicate->att_ids = NULL;
3052  }
3053  else
3054  {
3055  filter_predicate->att_ids = (int *) db_ws_alloc (sizeof (int) * att_seq_size);
3056  if (filter_predicate->att_ids == NULL)
3057  {
3058  goto error;
3059  }
3060 
3061  for (i = 0; i < att_seq_size; i++)
3062  {
3063  if (set_get_element_nocopy (att_seq, i, &v) != NO_ERROR)
3064  {
3066  goto error;
3067  }
3068 
3069  filter_predicate->att_ids[i] = db_get_int (&v);
3070  }
3071  }
3072 
3073  pr_clear_value (&avalue);
3074 
3075  return filter_predicate;
3076 error:
3077 
3078  if (filter_predicate)
3079  {
3080  if (filter_predicate->pred_string)
3081  {
3082  db_ws_free (filter_predicate->pred_string);
3083  }
3084 
3085  if (filter_predicate->pred_stream)
3086  {
3087  db_ws_free (filter_predicate->pred_stream);
3088  }
3089 
3090  if (filter_predicate->att_ids)
3091  {
3092  db_ws_free (filter_predicate->att_ids);
3093  }
3094 
3095  db_ws_free (filter_predicate);
3096  }
3097 
3098  pr_clear_value (&avalue);
3099  return NULL;
3100 }
3101 
3102 /*
3103  * classobj_make_class_constraints() - Walk over a class property list extracting
3104  * constraint information. Build up a list of SM_CLASS_CONSTRAINT structures
3105  * and return it.
3106  * The list must be freed with classobj_free_class_constraints().
3107  * return: NO_ERROR on success, non-zero for ERROR
3108  * class_props(in): class property list
3109  * attributes(in):
3110  * con_ptr(out):
3111  */
3112 
3113 int
3115 {
3116  SM_ATTRIBUTE *att;
3117  SM_CLASS_CONSTRAINT *constraints, *last, *new_;
3118  DB_SET *props, *info, *fk;
3119  DB_VALUE pvalue, uvalue, bvalue, avalue, fvalue, cvalue, statusval;
3120  int i, j, k, e, len, info_len, att_cnt;
3121  int *asc_desc;
3122  int num_constraint_types = NUM_CONSTRAINT_TYPES;
3123 
3124  if (con_ptr != NULL)
3125  {
3126  *con_ptr = NULL;
3127  }
3128 
3129  /* make sure these are initialized for the error cleanup code */
3130  db_make_null (&pvalue);
3131  db_make_null (&uvalue);
3132  db_make_null (&bvalue);
3133  db_make_null (&avalue);
3134  db_make_null (&fvalue);
3135  db_make_null (&cvalue);
3136  db_make_null (&statusval);
3137 
3138  constraints = last = NULL;
3139 
3140  /*
3141  * Process Index and Unique constraints
3142  */
3143  for (k = 0; k < num_constraint_types; k++)
3144  {
3145  if (classobj_get_prop (class_props, Constraint_properties[k], &pvalue) > 0)
3146  {
3147  /* get the sequence & its size */
3148  if (DB_VALUE_TYPE (&pvalue) != DB_TYPE_SEQUENCE)
3149  {
3150  goto structure_error;
3151  }
3152  props = db_get_set (&pvalue);
3153  len = set_size (props);
3154 
3155  /* this sequence is an alternating pair of constraint name & info sequence, as by: { name, { BTID,
3156  * [att_name, asc_dsc], {fk_info | pk_info | prefix_length}, filter_predicate, status, comment }, name, { BTID,
3157  * [att_name, asc_dsc], {fk_info | pk_info | prefix_length}, filter_predicate, status, comment }, ... } */
3158  for (i = 0; i < len; i += 2)
3159  {
3160 
3161  /* get the name */
3162  if (set_get_element (props, i, &uvalue))
3163  {
3164  goto other_error;
3165  }
3166  if (DB_VALUE_TYPE (&uvalue) != DB_TYPE_STRING)
3167  {
3168  goto structure_error;
3169  }
3170 
3171  /* make a new constraint list node, the string in uvalue will become owned by the constraint so we don't
3172  * have to free it. */
3174  if (new_ == NULL)
3175  {
3176  goto memory_error;
3177  }
3178  if (constraints == NULL)
3179  {
3180  constraints = new_;
3181  }
3182  else
3183  {
3184  last->next = new_;
3185  }
3186  last = new_;
3187 
3188  /* Get the information sequence, this sequence contains a BTID followed by the names/ids of each
3189  * attribute. */
3190  if (set_get_element (props, i + 1, &uvalue))
3191  {
3192  goto structure_error;
3193  }
3194  if (DB_VALUE_TYPE (&uvalue) != DB_TYPE_SEQUENCE)
3195  {
3196  goto structure_error;
3197  }
3198 
3199  info = db_get_set (&uvalue);
3200  info_len = set_size (info);
3201 
3202  att_cnt = (info_len - 3) / 2; /* excludes BTID and comment */
3203  assert (att_cnt > 0);
3204 
3205  e = 0;
3206 
3207  /* get the btid */
3208  if (set_get_element (info, e++, &bvalue))
3209  {
3210  goto structure_error;
3211  }
3212  if (classobj_btid_from_property_value (&bvalue, &new_->index_btid, (char **) &new_->shared_cons_name))
3213  {
3214  goto structure_error;
3215  }
3216  pr_clear_value (&bvalue);
3217 
3218  /* Allocate an array to contain pointers to the attributes involved in this constraint. The array will be
3219  * NULL terminated. */
3220  new_->attributes = (SM_ATTRIBUTE **) db_ws_alloc (sizeof (SM_ATTRIBUTE *) * (att_cnt + 1));
3221  if (new_->attributes == NULL)
3222  {
3223  goto memory_error;
3224  }
3225 
3226  new_->asc_desc = (int *) db_ws_alloc (sizeof (int) * att_cnt);
3227  if (new_->asc_desc == NULL)
3228  {
3229  goto memory_error;
3230  }
3231  asc_desc = (int *) new_->asc_desc;
3232 
3233  att = NULL;
3234  /* Find each attribute referenced by the constraint. */
3235  for (j = 0; j < att_cnt; j++)
3236  {
3237  /* name( or id) */
3238  if (set_get_element (info, e++, &avalue))
3239  {
3240  goto structure_error;
3241  }
3242 
3243  if (DB_VALUE_TYPE (&avalue) == DB_TYPE_SEQUENCE)
3244  {
3245  new_->attributes[j] = NULL;
3246  pr_clear_value (&avalue);
3247  break;
3248  }
3249 
3250  if (DB_VALUE_TYPE (&avalue) == DB_TYPE_STRING)
3251  {
3252  att = classobj_find_attribute_list (attributes, db_get_string (&avalue), -1);
3253  }
3254  else if (DB_VALUE_TYPE (&avalue) == DB_TYPE_INTEGER)
3255  {
3256  att = classobj_find_attribute_list (attributes, NULL, db_get_int (&avalue));
3257  }
3258  else
3259  {
3260  goto structure_error;
3261  }
3262 
3263  new_->attributes[j] = att;
3264 
3265  /* clear each attribute name/id value */
3266  pr_clear_value (&avalue);
3267 
3268  if (att == NULL)
3269  {
3270  /* go to the next element index in "info" */
3271  e = 1 + att_cnt * 2;
3272  break;
3273  }
3274 
3275  /* asc_desc */
3276  if (set_get_element (info, e++, &avalue))
3277  {
3278  goto structure_error;
3279  }
3280 
3281  if (DB_VALUE_TYPE (&avalue) == DB_TYPE_INTEGER)
3282  {
3283  asc_desc[j] = db_get_int (&avalue);
3286  {
3287  asc_desc[j] = 1; /* Desc */
3288  }
3289  }
3290  else
3291  {
3292  goto structure_error;
3293  }
3294 
3295  /* clear each attribute asc_desc value */
3296  pr_clear_value (&avalue);
3297  }
3298 
3299  /* If an attribute couldn't be found, then NULL out the entire array. Otherwise (if all attributes were
3300  * found), NULL terminate the array . */
3301  if (att == NULL)
3302  {
3303  j = 0;
3304  }
3305 
3306  for (; j < att_cnt + 1; j++)
3307  {
3308  new_->attributes[j] = NULL;
3309  }
3310 
3312  {
3313  if (set_get_element (info, e++, &bvalue))
3314  {
3315  goto structure_error;
3316  }
3317  fk = db_get_set (&bvalue);
3318 
3319  new_->fk_info = classobj_make_foreign_key_info (fk, new_->name, attributes);
3320  if (new_->fk_info == NULL)
3321  {
3322  goto structure_error;
3323  }
3324 
3325  pr_clear_value (&bvalue);
3326  }
3328  {
3329  if (set_get_element (info, e++, &bvalue))
3330  {
3331  goto structure_error;
3332  }
3333 
3334  if (DB_VALUE_TYPE (&bvalue) == DB_TYPE_SEQUENCE)
3335  {
3337  if (new_->fk_info == NULL)
3338  {
3339  goto structure_error;
3340  }
3341 
3342  pr_clear_value (&bvalue);
3343  }
3344  }
3345  else
3346  {
3347  if (set_get_element (info, e++, &bvalue))
3348  {
3349  goto structure_error;
3350  }
3351 
3352  if (DB_VALUE_TYPE (&bvalue) == DB_TYPE_SEQUENCE)
3353  {
3354  DB_SEQ *seq = db_get_set (&bvalue);
3355  if (set_get_element (seq, 0, &fvalue))
3356  {
3357  pr_clear_value (&bvalue);
3358  goto structure_error;
3359  }
3360  if (DB_VALUE_TYPE (&fvalue) == DB_TYPE_INTEGER)
3361  {
3363  if (new_->attrs_prefix_length == NULL)
3364  {
3365  goto structure_error;
3366  }
3367  }
3368  else if (DB_VALUE_TYPE (&fvalue) == DB_TYPE_SEQUENCE)
3369  {
3370  DB_SET *seq = db_get_set (&bvalue);
3371  DB_SET *child_seq = db_get_set (&fvalue);
3372  int seq_size = set_size (seq);
3373  int flag;
3374 
3375  j = 0;
3376  while (true)
3377  {
3378  flag = 0;
3379  if (set_get_element (child_seq, 0, &avalue) != NO_ERROR)
3380  {
3381  goto structure_error;
3382  }
3383 
3384  if (DB_IS_NULL (&avalue) || DB_VALUE_TYPE (&avalue) != DB_TYPE_STRING)
3385  {
3386  goto structure_error;
3387  }
3388 
3389  if (strcmp (db_get_string (&avalue), SM_FILTER_INDEX_ID) == 0)
3390  {
3391  flag = 0x01;
3392  }
3393  else if (strcmp (db_get_string (&avalue), SM_FUNCTION_INDEX_ID) == 0)
3394  {
3395  flag = 0x02;
3396  }
3397  else if (strcmp (db_get_string (&avalue), SM_PREFIX_INDEX_ID) == 0)
3398  {
3399  flag = 0x03;
3400  }
3401 
3402  pr_clear_value (&avalue);
3403 
3404  if (set_get_element (child_seq, 1, &avalue) != NO_ERROR)
3405  {
3406  goto structure_error;
3407  }
3408 
3409  if (DB_VALUE_TYPE (&avalue) != DB_TYPE_SEQUENCE)
3410  {
3411  goto structure_error;
3412  }
3413 
3414  switch (flag)
3415  {
3416  case 0x01:
3418  break;
3419 
3420  case 0x02:
3422  break;
3423 
3424  case 0x03:
3425  new_->attrs_prefix_length =
3426  classobj_make_index_prefix_info (db_get_set (&avalue), att_cnt);
3427  break;
3428 
3429  default:
3430  break;
3431  }
3432 
3433  pr_clear_value (&avalue);
3434 
3435  j++;
3436  if (j >= seq_size)
3437  {
3438  break;
3439  }
3440 
3441  pr_clear_value (&fvalue);
3442  if (set_get_element (seq, j, &fvalue) != NO_ERROR)
3443  {
3444  goto structure_error;
3445  }
3446 
3447  if (DB_VALUE_TYPE (&fvalue) != DB_TYPE_SEQUENCE)
3448  {
3449  goto structure_error;
3450  }
3451 
3452  child_seq = db_get_set (&fvalue);
3453  }
3454 
3455  if (new_->func_index_info)
3456  {
3457  /* function index and prefix length not allowed, yet */
3458  new_->attrs_prefix_length = (int *) db_ws_alloc (sizeof (int) * att_cnt);
3459  if (new_->attrs_prefix_length == NULL)
3460  {
3461  goto structure_error;
3462  }
3463  for (j = 0; j < att_cnt; j++)
3464  {
3465  new_->attrs_prefix_length[j] = -1;
3466  }
3467  }
3468  }
3469  else
3470  {
3471  goto structure_error;
3472  }
3473 
3474  pr_clear_value (&bvalue);
3475  pr_clear_value (&fvalue);
3476  }
3477  else
3478  {
3479  goto structure_error;
3480  }
3481  }
3482 
3483  /* Get the status. */
3484  set_get_element (info, info_len - 2, &statusval);
3485  new_->index_status = (SM_INDEX_STATUS) db_get_int (&statusval);
3486 
3487  if (set_get_element (info, info_len - 1, &cvalue))
3488  {
3489  /* if not exists, set comment to null */
3490  new_->comment = NULL;
3491  }
3492  else if (DB_IS_NULL (&cvalue) || DB_VALUE_TYPE (&cvalue) == DB_TYPE_STRING)
3493  {
3494  /* take "cvalue == null" case into account */
3495  new_->comment = db_get_string (&cvalue);
3496  }
3497  else
3498  {
3499  goto structure_error;
3500  }
3501 
3502  /* clear each unique info sequence value */
3503  pr_clear_value (&uvalue);
3504  }
3505  /* clear the property value */
3506  pr_clear_value (&pvalue);
3507  }
3508  }
3509 
3510  if (con_ptr == NULL)
3511  {
3512  classobj_free_class_constraints (constraints);
3513  }
3514  else
3515  {
3516  *con_ptr = constraints;
3517  }
3518 
3519  return NO_ERROR;
3520 
3521  /* ERROR PROCESSING */
3522 structure_error:
3523 
3524  /* should have a more appropriate error for this */
3526 
3527 memory_error:
3528 other_error:
3529  /* clean up our values and return the error that has been set */
3530  pr_clear_value (&cvalue);
3531  pr_clear_value (&fvalue);
3532  pr_clear_value (&avalue);
3533  pr_clear_value (&bvalue);
3534  pr_clear_value (&uvalue);
3535  pr_clear_value (&pvalue);
3536  pr_clear_value (&statusval);
3537 
3538  classobj_free_class_constraints (constraints);
3539 
3540  assert (er_errid () != NO_ERROR);
3541  return er_errid ();
3542 }
3543 
3544 /*
3545  * classobj_decache_class_constraints() - Removes any cached constraint information
3546  * from the class.
3547  * return: none
3548  * class(in): class to ponder
3549  */
3550 
3551 void
3553 {
3555  if (class_->constraints != NULL)
3556  {
3558  class_->constraints = NULL;
3559  }
3560 }
3561 
3562 
3563 /*
3564  * classobj_cache_not_null_constraints() - Cache the NOT NULL constraints from
3565  * the attribute list into the CLASS constraint cache.
3566  * return: NO_ERROR on success, non-zero for ERROR
3567  * class_name(in): Class Name
3568  * attributes(in): Pointer to an attribute list. NOT NULL constraints can
3569  * be applied to normal, shared and class attributes.
3570  * con_ptr(in/out): Pointer to the class constraint cache.
3571  */
3572 
3573 static int
3574 classobj_cache_not_null_constraints (const char *class_name, SM_ATTRIBUTE * attributes, SM_CLASS_CONSTRAINT ** con_ptr)
3575 {
3576  SM_ATTRIBUTE *att = NULL;
3577  SM_CLASS_CONSTRAINT *new_ = NULL;
3578  SM_CLASS_CONSTRAINT *constraints = NULL;
3579  SM_CLASS_CONSTRAINT *last = NULL;
3580  const char *att_names[2];
3581  char *ws_name = NULL;
3582  char *constraint_name = NULL;
3583 
3584  /* Set constraints to point to the first node of the constraint cache and last to point to the last node. */
3585 
3586  assert (con_ptr != NULL);
3587 
3588  constraints = last = *con_ptr;
3589 
3590  if (last != NULL)
3591  {
3592  while (last->next != NULL)
3593  {
3594  last = last->next;
3595  }
3596  }
3597 
3598  for (att = attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
3599  {
3600  if (att->flags & SM_ATTFLAG_NON_NULL)
3601  {
3602 
3603  /* Construct a default name for the constraint node. The constraint name is normally allocated from the heap
3604  * but we want it stored in the workspace so we'll construct it as usual and then copy it into the workspace
3605  * before calling classobj_make_class_constraint(). After the name is copied into the workspace it can be
3606  * deallocated from the heap. The name will be deallocated from the workspace when the constraint node is
3607  * destroyed. */
3608  att_names[0] = att->header.name;
3609  att_names[1] = NULL;
3610  constraint_name = sm_produce_constraint_name (class_name, DB_CONSTRAINT_NOT_NULL, att_names, NULL, NULL);
3611  if (constraint_name == NULL)
3612  {
3613  goto memory_error;
3614  }
3615 
3616  ws_name = ws_copy_string (constraint_name);
3617  if (ws_name == NULL)
3618  {
3619  goto memory_error;
3620  }
3621 
3622 
3623 
3624  /* Allocate a new class constraint node */
3626  if (new_ == NULL)
3627  {
3628  goto memory_error;
3629  }
3630 
3631  /* The constraint node now has a pointer to the workspace name so we'll disassociate our local pointer with
3632  * the string. */
3633  ws_name = NULL;
3634 
3635  /* Add the new constraint node to the list */
3636  if (constraints == NULL)
3637  {
3638  constraints = new_;
3639  }
3640  else
3641  {
3642  last->next = new_;
3643  }
3644 
3645  last = new_;
3646 
3647  /* Allocate an array for the attribute involved in the constraint. The array will always contain one
3648  * attribute pointer and a terminating NULL pointer. */
3649  new_->attributes = (SM_ATTRIBUTE **) db_ws_alloc (sizeof (SM_ATTRIBUTE *) * 2);
3650  if (new_->attributes == NULL)
3651  {
3652  goto memory_error;
3653  }
3654 
3655  new_->attributes[0] = att;
3656  new_->attributes[1] = NULL;
3657 
3658  free_and_init (constraint_name);
3659  }
3660  }
3661 
3662  *con_ptr = constraints;
3663 
3664  return NO_ERROR;
3665 
3666 
3667  /* ERROR PROCESSING */
3668 
3669 memory_error:
3670  classobj_free_class_constraints (constraints);
3671  if (constraint_name)
3672  {
3673  free_and_init (constraint_name);
3674  }
3675  if (ws_name)
3676  {
3677  db_ws_free (ws_name);
3678  }
3679 
3680  assert (er_errid () != NO_ERROR);
3681  return er_errid ();
3682 }
3683 
3684 /*
3685  * classobj_cache_class_constraints() - Converts the constraint information stored on
3686  * the class's property list into the cache SM_CLASS_CONSTRAINT list in
3687  * the class structure. This is way more convenient to deal with than
3688  * walking through the property list. Note that modifications to the class
3689  * do NOT become persistent.
3690  * Need to merge this with the earlier code for SM_CONSTRAINT maintenance
3691  * above.
3692  * return: NO_ERROR on success, non-zero for ERROR
3693  * class(in): class to ponder
3694  */
3695 
3696 int
3698 {
3699  int error = NO_ERROR;
3700 
3702 
3703  /* Cache the Indexes and Unique constraints found in the property list */
3704  error = classobj_make_class_constraints (class_->properties, class_->attributes, &(class_->constraints));
3705 
3706  /* The NOT NULL constraints are not in the property lists but are instead contained in the SM_ATTRIBUTE structures as
3707  * flags. Search through the attributes and cache the NOT NULL constraints found. */
3708  if (error == NO_ERROR)
3709  {
3710  error =
3711  classobj_cache_not_null_constraints (sm_ch_name ((MOBJ) class_), class_->attributes, &(class_->constraints));
3712  }
3713  if (error == NO_ERROR)
3714  {
3715  error = classobj_cache_not_null_constraints (sm_ch_name ((MOBJ) class_), class_->shared, &(class_->constraints));
3716  }
3717  if (error == NO_ERROR)
3718  {
3719  error =
3720  classobj_cache_not_null_constraints (sm_ch_name ((MOBJ) class_), class_->class_attributes,
3721  &(class_->constraints));
3722  }
3723 
3724  return error;
3725 }
3726 
3727 
3728 /*
3729  * classobj_find_class_constraint() - Searches a list of class constraint structures
3730  * for one with a certain name. Couldn't we be using nlist for this?
3731  * return: constraint
3732  * constraints(in): constraint list
3733  * type(in):
3734  * name(in): name to look for
3735  */
3736 
3739 {
3740  SM_CLASS_CONSTRAINT *con;
3741 
3742  for (con = constraints; con != NULL; con = con->next)
3743  {
3744  if ((con->type == type) && (intl_identifier_casecmp (con->name, name) == 0))
3745  {
3746  break;
3747  }
3748  }
3749  return con;
3750 }
3751 
3752 /*
3753  * classobj_find_class_constraint_by_btid() - Searches a list of class
3754  * constraint structures for one with a certain btid. Couldn't we be
3755  * using nlist for this?
3756  * return: constraint
3757  * constraints(in): constraint list
3758  * type(in):
3759  * btid(in): btid to look for
3760  */
3761 
3764 {
3765  SM_CLASS_CONSTRAINT *con;
3766 
3767  for (con = constraints; con != NULL; con = con->next)
3768  {
3769  if ((con->type == type) && BTID_IS_EQUAL (&btid, &con->index_btid))
3770  {
3771  break;
3772  }
3773  }
3774  return con;
3775 }
3776 
3777 /*
3778  * classobj_find_cons_index()
3779  * return: constraint
3780  * cons_list(in): constraint list
3781  * name(in): name to look for
3782  */
3783 
3786 {
3787  SM_CLASS_CONSTRAINT *cons;
3788 
3789  for (cons = cons_list; cons; cons = cons->next)
3790  {
3791  if ((SM_IS_CONSTRAINT_INDEX_FAMILY (cons->type)) && !SM_COMPARE_NAMES (cons->name, name))
3792  {
3793  break;
3794  }
3795  }
3796 
3797  return cons;
3798 }
3799 
3800 /*
3801  * classobj_find_class_index()
3802  * return: constraint
3803  * class(in):
3804  * name(in): name to look for
3805  */
3806 
3808 classobj_find_class_index (SM_CLASS * class_, const char *name)
3809 {
3810  return classobj_find_constraint_by_name (class_->constraints, name);
3811 }
3812 
3813 /*
3814  * classobj_find_cons_primary_key()
3815  * return: constraint
3816  * cons_list(in):
3817  */
3818 
3821 {
3822  SM_CLASS_CONSTRAINT *cons = NULL;
3823 
3824  for (cons = cons_list; cons; cons = cons->next)
3825  {
3826  if (cons->type == SM_CONSTRAINT_PRIMARY_KEY)
3827  {
3828  break;
3829  }
3830  }
3831 
3832  return cons;
3833 }
3834 
3835 /*
3836  * classobj_find_class_primary_key()
3837  * return: constraint
3838  * class(in):
3839  */
3840 
3843 {
3845 }
3846 
3847 #if defined(ENABLE_UNUSED_FUNCTION)
3848 /*
3849  * classobj_count_class_foreign_key()
3850  * return:
3851  * class(in):
3852  */
3853 
3854 int
3855 classobj_count_class_foreign_key (SM_CLASS * class_)
3856 {
3857  SM_CLASS_CONSTRAINT *cons = NULL;
3858  int count = 0;
3859 
3860  for (cons = class_->constraints; cons; cons = cons->next)
3861  {
3862  if (cons->type == SM_CONSTRAINT_FOREIGN_KEY)
3863  count++;
3864  }
3865 
3866  return count;
3867 }
3868 
3869 /*
3870  * classobj_count_cons_attributes()
3871  * return:
3872  * cons(in):
3873  */
3874 
3875 int
3876 classobj_count_cons_attributes (SM_CLASS_CONSTRAINT * cons)
3877 {
3878  int i = 0;
3879 
3880  for (i = 0; cons->attributes[i]; i++);
3881  return i;
3882 }
3883 #endif /* ENABLE_UNUSED_FUNCTION */
3884 
3885 /*
3886  * classobj_is_possible_constraint()
3887  * return:
3888  * existed(in):
3889  * new(in):
3890  */
3891 
3892 static bool
3894 {
3895  switch (existed)
3896  {
3897  case SM_CONSTRAINT_UNIQUE:
3899  switch (new_)
3900  {
3901  case DB_CONSTRAINT_UNIQUE:
3903  return false;
3904  case DB_CONSTRAINT_INDEX:
3905  return false;
3907  return false;
3909  return true;
3911  return false;
3912  default:
3913  return true;
3914  }
3915  case SM_CONSTRAINT_INDEX:
3916  switch (new_)
3917  {
3918  case DB_CONSTRAINT_UNIQUE:
3920  return false;
3921  case DB_CONSTRAINT_INDEX:
3922  return false;
3924  return true;
3926  return true;
3928  return false;
3929  default:
3930  return true;
3931  }
3933  switch (new_)
3934  {
3935  case DB_CONSTRAINT_UNIQUE:
3937  return false;
3938  case DB_CONSTRAINT_INDEX:
3939  return true;
3941  return false;
3943  return false;
3945  return false;
3946  default:
3947  return true;
3948  }
3950  switch (new_)
3951  {
3952  case DB_CONSTRAINT_UNIQUE:
3954  return true;
3955  case DB_CONSTRAINT_INDEX:
3956  return true;
3958  return false;
3960  return false;
3962  return true;
3963  default:
3964  return true;
3965  }
3967  switch (new_)
3968  {
3969  case DB_CONSTRAINT_UNIQUE:
3971  return false;
3972  case DB_CONSTRAINT_INDEX:
3973  return false;
3975  return false;
3977  return true;
3979  return false;
3980  default:
3981  return true;
3982  }
3983  default:
3984  return true;
3985  }
3986 }
3987 
3988 /*
3989  * classobj_find_cons_index2_col_type_list()
3990  * return:
3991  * cons(in):
3992  * stats(in):
3993  */
3994 
3995 TP_DOMAIN *
3997 {
3998  TP_DOMAIN *key_type = NULL;
3999  int i, j;
4000  ATTR_STATS *attr_statsp;
4001  BTREE_STATS *bt_statsp;
4002  CLASS_STATS *local_stats = NULL;
4003 
4004  if (!cons)
4005  {
4006  return NULL; /* invalid args */
4007  }
4008 
4009  if (!SM_IS_CONSTRAINT_INDEX_FAMILY (cons->type))
4010  {
4011  return NULL; /* give up */
4012  }
4013 
4014  if (OID_ISNULL (root_oid))
4015  {
4016  return NULL;
4017  }
4018 
4019  /* Get local stats including invisible indexes. */
4020  int err = stats_get_statistics (root_oid, 0, &local_stats);
4021  if (err != NO_ERROR || local_stats == NULL)
4022  {
4023  return NULL;
4024  }
4025 
4026  attr_statsp = local_stats->attr_stats;
4027  for (i = 0; i < local_stats->n_attrs && !key_type; i++, attr_statsp++)
4028  {
4029  bt_statsp = attr_statsp->bt_stats;
4030  for (j = 0; j < attr_statsp->n_btstats && !key_type; j++, bt_statsp++)
4031  {
4032  if (BTID_IS_EQUAL (&bt_statsp->btid, &cons->index_btid))
4033  {
4034  key_type = bt_statsp->key_type;
4035  }
4036  } /* for ( j = 0; ...) */
4037  } /* for ( i = 0; ...) */
4038 
4039  if (TP_DOMAIN_TYPE (key_type) == DB_TYPE_MIDXKEY)
4040  {
4041  /* get the column key-type of multi-column index */
4042  key_type = key_type->setdomain;
4043  }
4044 
4045  if (local_stats != NULL)
4046  {
4047  stats_free_statistics (local_stats);
4048  }
4049 
4050  return key_type;
4051 }
4052 
4053 
4054 /*
4055  * classobj_find_cons_index2()
4056  * return:
4057  * cons_list(in):
4058  * stats(in):
4059  * new_cons(in):
4060  * att_names(in):
4061  * asc_desc(in):
4062  */
4064 classobj_find_constraint_by_attrs (SM_CLASS_CONSTRAINT * cons_list, DB_CONSTRAINT_TYPE new_cons, const char **att_names,
4065  const int *asc_desc)
4066 {
4067  SM_CLASS_CONSTRAINT *cons;
4068  SM_ATTRIBUTE **attp;
4069  const char **namep;
4070  int i, len, order;
4071 
4072  for (cons = cons_list; cons; cons = cons->next)
4073  {
4074  if (SM_IS_CONSTRAINT_INDEX_FAMILY (cons->type))
4075  {
4076  attp = cons->attributes;
4077  namep = att_names;
4078  if (!attp || !namep)
4079  {
4080  continue;
4081  }
4082 
4083  len = 0; /* init */
4084  while (*attp && *namep && !intl_identifier_casecmp ((*attp)->header.name, *namep))
4085  {
4086  attp++;
4087  namep++;
4088  len++; /* increase name number */
4089  }
4090 
4091  if (!*attp && !*namep && !classobj_is_possible_constraint (cons->type, new_cons))
4092  {
4093  for (i = 0; i < len; i++)
4094  {
4095  /* if not specified, ascending order */
4096  order = (asc_desc ? asc_desc[i] : 0);
4097  assert (order == 0 || order == 1);
4098  if (order != cons->asc_desc[i])
4099  {
4100  break; /* not match */
4101  }
4102  }
4103 
4104  if (i == len)
4105  {
4106  return cons; /* match */
4107  }
4108  }
4109  }
4110  }
4111 
4112  return cons;
4113 }
4114 
4115 /*
4116  * cl_remove_class_constraint() - Drop the constraint node from the class
4117  * constraint cache.
4118  * return: none
4119  * constraints(in): Pointer to class constraint list
4120  * node(in): Pointer to a node in the constraint list
4121  */
4122 
4123 void
4125 {
4126  SM_CLASS_CONSTRAINT *con = NULL, *next = NULL, *prev = NULL;
4127 
4128  for (con = *constraints; con != NULL; con = next)
4129  {
4130  next = con->next;
4131  if (con != node)
4132  {
4133  prev = con;
4134  }
4135  else
4136  {
4137  if (prev == NULL)
4138  {
4139  *constraints = con->next;
4140  }
4141  else
4142  {
4143  prev->next = con->next;
4144  }
4145 
4146  con->next = NULL;
4147  }
4148  }
4149 }
4150 
4151 /*
4152  * classobj_populate_class_properties() - Populate the property list from the class
4153  * constraint cache. Only the specified constraint type is populated.
4154  * return: NO_ERROR on success, non-zero for ERROR
4155  * properties(out): Pointer to class properties
4156  * constraints(in): Pointer to class constraint list
4157  * type(in): Type of constraint
4158  */
4159 
4160 int
4162 {
4163  int error = NO_ERROR;
4164  SM_CLASS_CONSTRAINT *con;
4165  const char *property_type;
4166 
4167 
4168  /* Map the SM_CONSTRAINT_TYPE to a SM_PROPERTY_TYPE */
4169  property_type = classobj_map_constraint_to_property (type);
4170  if (property_type == NULL)
4171  {
4172  assert (er_errid () != NO_ERROR);
4173  error = er_errid ();
4174  }
4175 
4176  if (error != NO_ERROR)
4177  {
4178  return error;
4179  }
4180  /* Drop the selected property from the property list */
4181  classobj_drop_prop (*properties, property_type);
4182 
4183  /* Rebuild the property list entry from the constraint cache */
4184  for (con = constraints; con != NULL && !error; con = con->next)
4185  {
4186  if (con->type != type)
4187  {
4188  continue;
4189  }
4190  if (classobj_put_index (properties, type, con->name, con->attributes, con->asc_desc, con->attrs_prefix_length,
4191  &(con->index_btid), con->filter_predicate, con->fk_info, con->shared_cons_name,
4192  con->func_index_info, con->comment, con->index_status, false) != NO_ERROR)
4193  {
4194  error = ER_SM_INVALID_PROPERTY;
4195  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
4196  }
4197 
4198  }
4199 
4200 
4201  return error;
4202 }
4203 
4204 
4205 /*
4206  * classobj_class_has_indexes() - Searches the class constraints
4207  * return: true if the class contains indexes(INDEX or UNIQUE constraints)
4208  * class(in): Class
4209  */
4210 
4211 bool
4213 {
4214  SM_CLASS_CONSTRAINT *con;
4215  bool has_index = false;
4216 
4217  has_index = false;
4218  for (con = class_->constraints; (con != NULL && !has_index); con = con->next)
4219  {
4221  {
4222  has_index = true;
4223  }
4224  }
4225 
4226  return has_index;
4227 }
4228 
4229 
4230 /* SM_DOMAIN */
4231 
4232 /*
4233  * classobj_domain_size() - Caclassobj_domain_sizee number of bytes of memory required for
4234  * a domain list.
4235  * return: byte size of domain list
4236  * domain(in): domain list
4237  */
4238 
4239 static int
4241 {
4242  int size;
4243 
4244  size = sizeof (TP_DOMAIN);
4245  size += ws_list_total ((DB_LIST *) domain->setdomain, (LTOTALER) classobj_domain_size);
4246 
4247  return (size);
4248 }
4249 
4250 /* SM_ATTRIBUTE */
4251 /*
4252  * classobj_make_attribute() - Construct a new attribute structure.
4253  * return: attribute structure
4254  * name(in): attribute name
4255  * type(in): primitive type
4256  * namespace(in): type of attribute (instance or class )
4257  */
4258 
4259 SM_ATTRIBUTE *
4260 classobj_make_attribute (const char *name, struct pr_type * type, SM_NAME_SPACE name_space)
4261 {
4262  SM_ATTRIBUTE *att;
4263 
4264  att = (SM_ATTRIBUTE *) db_ws_alloc (sizeof (SM_ATTRIBUTE));
4265  if (att == NULL)
4266  {
4267  return NULL;
4268  }
4269  att->header.next = NULL;
4270  att->header.name = NULL;
4271  att->header.name_space = name_space;
4272  att->id = -1;
4273  /* try to start phasing out att->type and instead use att->domain everywhere - jsl */
4274  att->type = type;
4275  att->domain = NULL;
4276  att->class_mop = NULL;
4277  att->offset = 0;
4278  att->flags = 0;
4279  att->order = 0;
4280  att->storage_order = 0;
4281  /* initial values are unbound */
4286 
4287  att->constraints = NULL;
4288  att->order_link = NULL;
4289  att->properties = NULL;
4290  att->triggers = NULL;
4291 
4292  if (name != NULL)
4293  {
4294  att->header.name = ws_copy_string (name);
4295  if (att->header.name == NULL)
4296  {
4297  db_ws_free (att);
4298  return NULL;
4299  }
4300  }
4301 
4302  att->comment = NULL;
4303 
4304  return (att);
4305 }
4306 
4307 /*
4308  * classobj_filter_attribute_props() - This examines the property list for copied
4309  * attribute and removes properties that aren't supposed to be copied as
4310  * attributes definitions are flattened. We could possibly make this
4311  * part of classobj_copy_props above.
4312  * UNIQUE properties are inheritable but INDEX properties are not.
4313  * return: none
4314  * properties(in): property list to filter
4315  */
4316 
4317 static void
4319 {
4320  /* these properties aren't inherited, they must be defined locally */
4321 
4324 }
4325 
4326 /*
4327  * classobj_initialize_attributes() - Initializes attribute
4328  *
4329  * return: nothing
4330  * attributes(in): attributes
4331  */
4332 void
4334 {
4335  SM_ATTRIBUTE *attr;
4336 
4337  for (attr = attributes; attr != NULL; attr = (SM_ATTRIBUTE *) (attr->header.next))
4338  {
4339  attr->constraints = NULL;
4340  attr->order_link = NULL;
4341  attr->properties = NULL;
4342  attr->triggers = NULL;
4343  attr->header.name = NULL;
4344  attr->domain = NULL;
4345  attr->comment = NULL;
4350  }
4351 }
4352 
4353 /*
4354  * classobj_initialize_methods() - Initializes methods
4355  *
4356  * return: nothing
4357  * attributes(in): attributes
4358  */
4359 void
4361 {
4362  SM_METHOD *method;
4363 
4364  for (method = methods; method != NULL; method = (SM_METHOD *) (method->header.next))
4365  {
4366  method->properties = NULL;
4367  method->function = NULL;
4368  method->signatures = NULL;
4369  method->header.name = NULL;
4370  }
4371 }
4372 
4373 /*
4374  * classobj_init_attribute() - Initializes an attribute using the contents of
4375  * another attribute. This is used when an attribute list is flattened
4376  * during class definition and the attribute lists are converted into
4377  * a threaded array of attributes.
4378  * NOTE: External allocations like name & domain may be either copied
4379  * or simply have their pointers transfered depending on the value
4380  * of the copy flag.
4381  * NOTE: Be careful not to touch the "next" field here since it may
4382  * have been already initialized as part of a threaded array.
4383  * return: NO_ERROR on success, non-zero for ERROR
4384  * src(in): source attribute
4385  * dest(out): destination attribute
4386  * copy(in): copy flag (non-zero to copy)
4387  */
4388 
4389 static int
4391 {
4392  int error = NO_ERROR;
4393 
4394  assert (src != NULL);
4395  dest->header.name = NULL;
4396  dest->header.name_space = src->header.name_space;
4397  dest->id = src->id; /* correct ? */
4398  dest->type = src->type;
4399  dest->class_mop = src->class_mop;
4400  dest->offset = src->offset;
4401  dest->flags = src->flags;
4402  dest->order = src->order;
4403  dest->storage_order = src->storage_order;
4404  dest->order_link = NULL; /* can never be copied */
4405  dest->constraints = NULL;
4406  dest->triggers = NULL;
4407  dest->domain = NULL;
4408  dest->properties = NULL;
4409  dest->auto_increment = src->auto_increment;
4412  dest->comment = NULL;
4413 
4414  if (copy)
4415  {
4416  if (src->header.name != NULL)
4417  {
4418  dest->header.name = ws_copy_string (src->header.name);
4419  if (dest->header.name == NULL)
4420  {
4421  goto memory_error;
4422  }
4423  }
4424  if (src->comment != NULL)
4425  {
4426  dest->comment = ws_copy_string (src->comment);
4427  if (dest->comment == NULL)
4428  {
4429  goto memory_error;
4430  }
4431  }
4432  if (src->domain != NULL)
4433  {
4434  dest->domain = tp_domain_copy (src->domain, true);
4435  if (dest->domain == NULL)
4436  {
4437  goto memory_error;
4438  }
4439  }
4440  if (src->properties != NULL)
4441  {
4442  error = classobj_copy_props (src->properties, NULL, &dest->properties);
4443  if (error != NO_ERROR)
4444  {
4445  goto memory_error;
4446  }
4447  }
4448  if (src->triggers != NULL)
4449  {
4450  dest->triggers = tr_copy_schema_cache (src->triggers, NULL);
4451  if (dest->triggers == NULL)
4452  {
4453  goto memory_error;
4454  }
4455  }
4456  /* remove the properties that can't be inherited */
4458 
4459  if (src->constraints != NULL)
4460  {
4461  /*
4462  * We used to just copy the unique BTID from the source to the
4463  * destination. We might want to copy the src cache to dest, or
4464  * maybe regenerate the cache for dest since the information is
4465  * already in its property list. - JB
4466  */
4467  }
4468 
4469  /* make a copy of the default value */
4471  {
4472  goto memory_error;
4473  }
4474 
4476  {
4477  goto memory_error;
4478  }
4479  }
4480  else
4481  {
4482  dest->header.name = src->header.name;
4483  dest->constraints = src->constraints;
4484  dest->properties = src->properties;
4485  dest->triggers = src->triggers;
4486  dest->comment = src->comment;
4487  src->header.name = NULL;
4488  src->constraints = NULL;
4489  src->properties = NULL;
4490  src->triggers = NULL;
4491  src->comment = NULL;
4492 
4493  /* Note that we don't clear the source domain here since it must be cached at this point. We keep the
4494  * src->domain around until the attribute is freed in case it is needed for something related to the default
4495  * values, etc. */
4496  dest->domain = src->domain;
4497 
4498  /*
4499  * do structure copies on the values and make sure the sources
4500  * get cleared
4501  */
4502  dest->default_value.value = src->default_value.value;
4504 
4507  }
4508 
4509  return NO_ERROR;
4510 
4511 memory_error:
4512  /* Could try to free the partially allocated things. If we get here then we're out of virtual memory, a few leaks
4513  * aren't going to matter much. */
4514  assert (er_errid () != NO_ERROR);
4515  return er_errid ();
4516 }
4517 
4518 
4519 /*
4520  * classobj_copy_attribute() - Copies an attribute.
4521  * The alias if provided will override the attribute name.
4522  * return: new attribute
4523  * src(in): source attribute
4524  * alias(in): alias name (can be NULL)
4525  */
4526 SM_ATTRIBUTE *
4527 classobj_copy_attribute (SM_ATTRIBUTE * src, const char *alias)
4528 {
4529  SM_ATTRIBUTE *att;
4530 
4531  att = (SM_ATTRIBUTE *) db_ws_alloc (sizeof (SM_ATTRIBUTE));
4532  if (att == NULL)
4533  {
4534  return NULL;
4535  }
4536  att->header.next = NULL;
4537 
4538  /* make a unique copy */
4539  if (classobj_init_attribute (src, att, 1))
4540  {
4541  db_ws_free (att);
4542  return NULL;
4543  }
4544 
4545  if (alias != NULL)
4546  {
4547  ws_free_string (att->header.name);
4548  att->header.name = ws_copy_string (alias);
4549  if (att->header.name == NULL)
4550  {
4551  db_ws_free (att);
4552  return NULL;
4553  }
4554  }
4555 
4556  return (att);
4557 }
4558 
4559 /*
4560  * classobj_copy_attlist() - Copies an attribute list. This does NOT return a
4561  * threaded array. The filter_class is optional and will cause only those
4562  * attributes whose origin is the given class to be copied to the result list
4563  * return: NO_ERROR on success, non-zero for ERROR
4564  * attlist(in): attribute list
4565  * filter_class(in): optional filter class
4566  * ordered(in):
4567  * copy_ptr(out): new attribute list
4568  */
4569 
4570 int
4571 classobj_copy_attlist (SM_ATTRIBUTE * attlist, MOP filter_class, int ordered, SM_ATTRIBUTE ** copy_ptr)
4572 {
4573  SM_ATTRIBUTE *att, *new_, *first, *last, *next;
4574 
4575  first = last = NULL;
4576 
4577  for (att = attlist, next = NULL; att != NULL; att = next)
4578  {
4579  if (ordered)
4580  {
4581  next = att->order_link;
4582  }
4583  else
4584  {
4585  next = (SM_ATTRIBUTE *) att->header.next;
4586  }
4587 
4588  if ((filter_class == NULL) || (filter_class == att->class_mop))
4589  {
4590  new_ = classobj_copy_attribute (att, NULL);
4591  if (new_ == NULL)
4592  {
4593  goto memory_error;
4594  }
4595  if (first == NULL)
4596  {
4597  first = new_;
4598  }
4599  else
4600  {
4601  last->header.next = (SM_COMPONENT *) new_;
4602  }
4603  last = new_;
4604  }
4605  }
4606  *copy_ptr = first;
4607  return NO_ERROR;
4608 
4609 memory_error:
4610  /* Could try to free the previously copied attribute list. We're out of virtual memory at this point. A few leaks
4611  * aren't going to matter. */
4612  assert (er_errid () != NO_ERROR);
4613  return er_errid ();
4614 }
4615 
4616 /*
4617  * classobj_clear_attribute_value() - This gets rid of storage for a DB_VALUE attached
4618  * to a class. This is a kludge primarily for the handling of set handles.
4619  * In normal db_value_clear() semantics, we would simply end up calling
4620  * set_free() on the set reference.
4621  * set_free() checks the ownership if the reference and will not free
4622  * the underlying set object if it is owned. Also, it won't free the
4623  * reference or set if the reference count is >1.
4624  * Here its a bit different since the class completely in charge of
4625  * how the storage for this set is managed.
4626  * We go around the usual db_value_clear() rules to make sure the
4627  * set gets freed.
4628  * As always, the handling of set memory needs to be cleaned up.
4629  * return: none
4630  * value(in/out): value to clear
4631  */
4632 
4633 static void
4635 {
4636  SETREF *ref;
4637  SETOBJ *set;
4638 
4639  if (!DB_IS_NULL (value) && TP_IS_SET_TYPE (DB_VALUE_TYPE (value)))
4640  {
4641  /* get directly to the set */
4642  ref = db_get_set (value);
4643  if (ref != NULL)
4644  {
4645  set = ref->set;
4646 
4647  /* always free the underlying set object */
4648  if (set != NULL)
4649  {
4650  setobj_free (set);
4651  }
4652 
4653  /* now free the reference, if the counter goes to zero its freed otherwise, it gets left dangling but at
4654  * least we've free the set storage at this point */
4655  set_free (ref);
4656  }
4657  }
4658  else
4659  {
4660  /* clear it the usual way */
4661  pr_clear_value (value);
4662  }
4663 }
4664 
4665 /*
4666  * classobj_clear_attribute() - Deallocate storage associated with an attribute.
4667  * Note that this doesn't deallocate the attribute structure itself since
4668  * this may be part of a threaded array.
4669  * return: none
4670  * att(in/out): attribute
4671  */
4672 
4673 static void
4675 {
4676  if (att == NULL)
4677  {
4678  return;
4679  }
4680  if (att->header.name != NULL)
4681  {
4682  ws_free_string (att->header.name);
4683  att->header.name = NULL;
4684  }
4685  if (att->comment != NULL)
4686  {
4687  ws_free_string (att->comment);
4688  att->comment = NULL;
4689  }
4690  if (att->constraints != NULL)
4691  {
4693  att->constraints = NULL;
4694  }
4695  if (att->properties != NULL)
4696  {
4698  att->properties = NULL;
4699  }
4700  if (att->triggers != NULL)
4701  {
4703  att->triggers = NULL;
4704  }
4707 
4709  {
4712  }
4713 
4714  att->header.name = NULL;
4715 
4716  /* Do this last in case we needed it for default value maintenance or something. This probably isn't necessary, the
4717  * domain should have been cached at this point ? */
4718  if (att->domain != NULL)
4719  {
4720  tp_domain_free (att->domain);
4721  att->domain = NULL;
4722  }
4723 
4724 }
4725 
4726 /*
4727  * classobj_free_attribute() - Frees an attribute structure and all memory
4728  * associated with the attribute.
4729  * return: none
4730  * att(in): attribute
4731  */
4732 
4733 void
4735 {
4736  if (att != NULL)
4737  {
4739  db_ws_free (att);
4740  }
4741 }
4742 
4743 /*
4744  * classobj_attribute_size() - Calculates the number of bytes required for the
4745  * memory representation of an attribute.
4746  * return: byte size of attribute
4747  * att(in): attribute
4748  */
4749 
4750 static int
4752 {
4753  int size;
4754 
4755  size = sizeof (SM_ATTRIBUTE);
4756  /* this can be NULL only for attributes used in an old representation */
4757  if (att->header.name != NULL)
4758  {
4759  size += strlen (att->header.name) + 1;
4760  }
4762  size += pr_value_mem_size (&att->default_value.value);
4764 
4765  if (att->constraints != NULL)
4766  {
4768  }
4769 
4770  if (att->comment != NULL)
4771  {
4772  size += strlen (att->comment) + 1;
4773  }
4774 
4775  /* need to add in property set */
4776 
4777  return (size);
4778 }
4779 
4780 /* SM_METHOD_ARGUMENT */
4781 /*
4782  * Initially these were threaded arrays. I changed them to be simple lists
4783  * because its easier to maintain and we won't be doing method overloading
4784  * for awhile (possibly never).
4785  *
4786  * When we start doing performance optimization for method dispatching, the
4787  * arglist should be compiled into an arrays.
4788 */
4789 
4790 /*
4791  * classobj_make_method_arg() - Creates and initializes a method argument strucutre.
4792  * return: new method argument
4793  * index(in): argument index
4794  */
4795 
4798 {
4799  SM_METHOD_ARGUMENT *arg;
4800 
4801  arg = (SM_METHOD_ARGUMENT *) db_ws_alloc (sizeof (SM_METHOD_ARGUMENT));
4802  if (arg != NULL)
4803  {
4804  arg->next = NULL;
4805  arg->index = index;
4806  arg->type = NULL;
4807  arg->domain = NULL;
4808  }
4809  return (arg);
4810 }
4811 
4812 /*
4813  * classobj_free_method_arg() - Frees memory associated with a method argument.
4814  * return: none
4815  * arg(in): method argument
4816  */
4817 
4818 static void
4820 {
4821  if (arg != NULL)
4822  {
4823  if (arg->domain != NULL)
4824  {
4825  tp_domain_free (arg->domain);
4826  }
4827  db_ws_free (arg);
4828  }
4829 }
4830 
4831 /*
4832  * classobj_copy_method_arg() - Copies a method argument structure
4833  * including the domain list.
4834  * return: new method argument
4835  * src(in): source method argument
4836  */
4837 
4838 static SM_METHOD_ARGUMENT *
4840 {
4841  SM_METHOD_ARGUMENT *new_ = NULL;
4842 
4843  if (src == NULL)
4844  {
4845  return NULL;
4846  }
4847 
4848  new_ = classobj_make_method_arg (src->index);
4849  if (new_ != NULL)
4850  {
4851  new_->type = src->type;
4852 
4853  if (src->domain != NULL)
4854  {
4855  new_->domain = tp_domain_copy (src->domain, true);
4856  if (new_->domain == NULL)
4857  {
4858  classobj_free_method_arg (new_);
4859  new_ = NULL;
4860  }
4861  }
4862  }
4863 
4864  return (new_);
4865 }
4866 
4867 /*
4868  * classobj_method_arg_size() - Calculates the number of bytes of storage
4869  * for a method argument.
4870  * return: byte size of method argument
4871  * arg(in): argument
4872  */
4873 
4874 static int
4876 {
4877  int size;
4878 
4879  size = sizeof (SM_METHOD_ARGUMENT);
4881 
4882  return (size);
4883 }
4884 
4885 /*
4886  * classobj_find_method_arg() - This searches an argument list for an argument with the
4887  * given index. If the argument was not found and the create flag is
4888  * non-zero, a new argument structure is allocated and added to the list.
4889  * return: method argument structure
4890  * arglist(in): argument list (possibly modified)
4891  * index(in): argument index
4892  * create(in): create flag (non-zero to create)
4893  */
4894 
4897 {
4898  SM_METHOD_ARGUMENT *arg, *found;
4899 
4900  found = NULL;
4901  for (arg = *arglist; arg != NULL && found == NULL; arg = arg->next)
4902  {
4903  if (arg->index == index)
4904  {
4905  found = arg;
4906  }
4907  }
4908  if ((found == NULL) && create)
4909  {
4910  found = classobj_make_method_arg (index);
4911  if (found != NULL)
4912  {
4913  found->next = *arglist;
4914  *arglist = found;
4915  }
4916  }
4917  return (found);
4918 }
4919 
4920 /* SM_METHOD_SIGNATURE */
4921 /* Multiple method signatures are not actually supported in the language but
4922  * the original implementation supported them so we'll leave them in in case
4923  * we wish to support them in the future.
4924  */
4925 
4926 /*
4927  * classobj_make_method_signature() - Makes a method signature.
4928  * The name must be the name of the C function that implements this
4929  * method. Two signatures cannot have the same name.
4930  * return: new method signature
4931  * name(in): implementation name
4932  */
4933 
4936 {
4937  SM_METHOD_SIGNATURE *sig;
4938 
4940 
4941  if (sig == NULL)
4942  {
4943  return NULL;
4944  }
4945 
4946  sig->next = NULL;
4947  sig->function_name = NULL;
4948  sig->sql_definition = NULL;
4949  sig->function = NULL;
4950  sig->num_args = 0;
4951  sig->value = NULL;
4952  sig->args = NULL;
4953 
4954  if (name != NULL)
4955  {
4956  sig->function_name = ws_copy_string (name);
4957  if (sig->function_name == NULL)
4958  {
4959  db_ws_free (sig);
4960  sig = NULL;
4961  }
4962  }
4963 
4964  return (sig);
4965 }
4966 
4967 /*
4968  * classobj_free_method_signature() - Free a method signature structure and
4969  * associated storage.
4970  * return: none
4971  * sig(in): signature
4972  */
4973 
4974 void
4976 {
4977  if (sig != NULL)
4978  {
4982  ws_list_free ((DB_LIST *) sig->args, (LFREEER) classobj_free_method_arg);
4983  db_ws_free (sig);
4984  }
4985 }
4986 
4987 /*
4988  * classobj_copy_method_signature() - Copy a method signature and all associated
4989  * arguments and domains.
4990  * return: new method signature
4991  * sig(in): source method signature
4992  */
4993 
4994 static SM_METHOD_SIGNATURE *
4996 {
4997  SM_METHOD_SIGNATURE *new_;
4998 
5000  if (new_ == NULL)
5001  {
5002  return NULL;
5003  }
5004  new_->value = NULL;
5005  new_->args = NULL;
5006  new_->sql_definition = NULL;
5007  new_->num_args = sig->num_args;
5008  new_->function = sig->function; /* should this be reset to NULL ? */
5009 
5010  if (sig->value != NULL)
5011  {
5012  new_->value =
5015  if (new_->value == NULL)
5016  {
5017  goto memory_error;
5018  }
5019  }
5020  if (sig->args != NULL)
5021  {
5022  new_->args =
5025  if (new_->args == NULL)
5026  {
5027  goto memory_error;
5028  }
5029  }
5030  if (sig->sql_definition != NULL)
5031  {
5033  if (new_->sql_definition == NULL)
5034  {
5035  goto memory_error;
5036  }
5037  }
5038 
5039  return (new_);
5040 
5041 memory_error:
5042  if (new_ != NULL)
5043  {
5045  }
5046  return NULL;
5047 }
5048 
5049 /*
5050  * classobj_method_signature_size() - Calculates the amound of memory used by
5051  * a method signature.
5052  * return: byte size of signature
5053  * sig(in): signature to examine
5054  */
5055 
5056 static int
5058 {
5059  int size;
5060 
5061  size = sizeof (SM_METHOD_SIGNATURE);
5062  if (sig->function_name != NULL)
5063  {
5064  size += strlen (sig->function_name) + 1;
5065  }
5066  if (sig->sql_definition != NULL)
5067  {
5068  size += strlen (sig->sql_definition) + 1;
5069  }
5071  size += ws_list_total ((DB_LIST *) sig->args, (LTOTALER) classobj_method_arg_size);
5072 
5073  return (size);
5074 }
5075 
5076 /* SM_METHOD */
5077 /*
5078  * classobj_make_method() - Creates a new method strucutre.
5079  * return: new method
5080  * name(in): method name
5081  * namespace (in): method type (class or instance)
5082  */
5083 
5084 SM_METHOD *
5085 classobj_make_method (const char *name, SM_NAME_SPACE name_space)
5086 {
5087  SM_METHOD *meth;
5088 
5089  meth = (SM_METHOD *) db_ws_alloc (sizeof (SM_METHOD));
5090 
5091  if (meth == NULL)
5092  {
5093  return NULL;
5094  }
5095 
5096  meth->header.next = NULL;
5097  meth->header.name = NULL;
5098  meth->header.name_space = name_space;
5099  meth->function = NULL;
5100  meth->class_mop = NULL;
5101  meth->id = -1;
5102  meth->signatures = NULL;
5103  meth->properties = NULL;
5104 
5105  if (name != NULL)
5106  {
5107  meth->header.name = ws_copy_string (name);
5108  if (meth->header.name == NULL)
5109  {
5110  db_ws_free (meth);
5111  meth = NULL;
5112  }
5113  }
5114  return (meth);
5115 }
5116 
5117 /*
5118  * classobj_clear_method() - Release storage contained in a method structure.
5119  * The method structure itself is not freed.
5120  * return: none
5121  * meth(in/out): method
5122  */
5123 
5124 static void
5126 {
5127  if (meth == NULL)
5128  {
5129  return;
5130  }
5131 
5132  if (meth->header.name != NULL)
5133  {
5134  ws_free_string (meth->header.name);
5135  meth->header.name = NULL;
5136  }
5137 
5138  if (meth->properties != NULL)
5139  {
5141  meth->properties = NULL;
5142  }
5143 
5144  if (meth->signatures != NULL)
5145  {
5147  meth->signatures = NULL;
5148  }
5149 
5150 }
5151 
5152 /*
5153  * classobj_init_method() - Initializes a method structure with a copy of another
5154  * method structure. If the copy flag is non-zero, external allocations
5155  * like method name and signatures are copied. If the copy
5156  * flag is zero, the pointers to the external allocations are
5157  * used directly.
5158  * return: NO_ERROR on success, non-zero for ERROR
5159  * src(in): source method
5160  * dest(out): destination method
5161  * copy(in): copy flag (non-zero to copy)
5162  */
5163 
5164 static int
5165 classobj_init_method (SM_METHOD * src, SM_METHOD * dest, int copy)
5166 {
5167  int error = NO_ERROR;
5168  dest->header.name = NULL;
5169  dest->header.name_space = src->header.name_space;
5170  dest->class_mop = src->class_mop;
5171  dest->id = src->id;
5172  dest->function = src->function; /* reset to NULL ? */
5173  dest->signatures = NULL;
5174  dest->properties = NULL;
5175 
5176  if (copy)
5177  {
5178  if (src->header.name != NULL)
5179  {
5180  dest->header.name = ws_copy_string (src->header.name);
5181  if (dest->header.name == NULL)
5182  {
5183  goto memory_error;
5184  }
5185  }
5186  if (src->signatures != NULL)
5187  {
5188  dest->signatures =
5191  if (dest->signatures == NULL)
5192  {
5193  goto memory_error;
5194  }
5195  }
5196  if (src->properties != NULL)
5197  {
5198  /* there are no method properties that need to be filtered */
5199  error = classobj_copy_props (src->properties, NULL, &dest->properties);
5200  if (error != NO_ERROR)
5201  {
5202  goto memory_error;
5203  }
5204  }
5205  }
5206  else
5207  {
5208  dest->header.name = src->header.name;
5209  dest->signatures = src->signatures;
5210  dest->properties = src->properties;
5211  src->header.name = NULL;
5212  src->signatures = NULL;
5213  src->properties = NULL;
5214  }
5215 
5216  return NO_ERROR;
5217 
5218 memory_error:
5219  classobj_clear_method (dest);
5220 
5221  assert (er_errid () != NO_ERROR);
5222  return er_errid ();
5223 }
5224 
5225 /*
5226  * classobj_copy_method() - Copies a method structure. The alias name is given
5227  * will override the method name.
5228  * return: new method
5229  * src(in): source method
5230  * alias(in): alias name (optional)
5231  */
5232 
5233 SM_METHOD *
5234 classobj_copy_method (SM_METHOD * src, const char *alias)
5235 {
5236  SM_METHOD *meth;
5237 
5238  meth = (SM_METHOD *) db_ws_alloc (sizeof (SM_METHOD));
5239  if (meth == NULL)
5240  {
5241  return NULL;
5242  }
5243 
5244  meth->header.next = NULL;
5245 
5246  if (classobj_init_method (src, meth, 1))
5247  {
5248  db_ws_free (meth);
5249  return NULL;
5250  }
5251 
5252  if (alias != NULL)
5253  {
5254  ws_free_string (meth->header.name);
5255  meth->header.name = ws_copy_string (alias);
5256  if (meth->header.name == NULL)
5257  {
5258  db_ws_free (meth);
5259  return NULL;
5260  }
5261  }
5262 
5263  return (meth);
5264 }
5265 
5266 /*
5267  * classobj_copy_methlist() - Copies a method list. This does NOT return a threaded
5268  * array. The filter class is optional and if set will copy only those
5269  * methods whose origin is the filter class.
5270  * return: NO_ERROR on success, non-zero for ERROR
5271  * methlist(in): method list
5272  * filter_class(in): optional filter class
5273  * copy_ptr(out): new method list
5274  */
5275 
5276 static int
5277 classobj_copy_methlist (SM_METHOD * methlist, MOP filter_class, SM_METHOD ** copy_ptr)
5278 {
5279  SM_METHOD *meth, *new_meth, *first, *last;
5280 
5281  first = last = NULL;
5282 
5283  for (meth = methlist; meth != NULL; meth = (SM_METHOD *) meth->header.next)
5284  {
5285  if ((filter_class == NULL) || (meth->class_mop == filter_class))
5286  {
5287  new_meth = classobj_copy_method (meth, NULL);
5288  if (new_meth == NULL)
5289  {
5290  goto memory_error;
5291  }
5292 
5293  if (first == NULL)
5294  {
5295  first = new_meth;
5296  }
5297  else
5298  {
5299  last->header.next = (SM_COMPONENT *) new_meth;
5300  }
5301  last = new_meth;
5302  }
5303  }
5304  *copy_ptr = first;
5305 
5306  return NO_ERROR;
5307 
5308 memory_error:
5309  /* could free the partially constructed method list */
5310  assert (er_errid () != NO_ERROR);
5311  return er_errid ();
5312 }
5313 
5314 /*
5315  * classobj_free_method() - Free a method and any associated storage.
5316  * return: none
5317  * meth(in): method
5318  */
5319 
5320 void
5322 {
5323  if (meth != NULL)
5324  {
5325  classobj_clear_method (meth);
5326  db_ws_free (meth);
5327  }
5328 }
5329 
5330 /*
5331  * classobj_method_size() - Calculates the amount of memory used for a method.
5332  * return: byte size of method
5333  * meth(in): method
5334  */
5335 
5336 static int
5338 {
5339  int size;
5340 
5341  size = sizeof (SM_METHOD);
5342  size += strlen (meth->header.name) + 1;
5344 
5345  return (size);
5346 }
5347 
5348 /* SM_RESOLUTION */
5349 /*
5350  * classobj_free_resolution() - Free a resolution structure and any associated memory.
5351  * return: none
5352  * res(in): resolution
5353  */
5354 
5355 void
5357 {
5358  if (res != NULL)
5359  {
5360  if (res->name != NULL)
5361  {
5362  ws_free_string (res->name);
5363  }
5364  if (res->alias != NULL)
5365  {
5366  ws_free_string (res->alias);
5367  }
5368  db_ws_free (res);
5369  }
5370 }
5371 
5372 /*
5373  * classobj_make_resolution() - Builds a new resolution structure.
5374  * return: new resolution
5375  * class_mop(in): source class
5376  * name(in): attribute/method name
5377  * alias(in): optional alias
5378  * name_space(in): resolution type (class or instance)
5379  */
5380 
5381 SM_RESOLUTION *
5382 classobj_make_resolution (MOP class_mop, const char *name, const char *alias, SM_NAME_SPACE name_space)
5383 {
5384  SM_RESOLUTION *res;
5385 
5386  res = (SM_RESOLUTION *) db_ws_alloc (sizeof (SM_RESOLUTION));
5387  if (res == NULL)
5388  {
5389  return NULL;
5390  }
5391  res->next = NULL;
5392  res->class_mop = class_mop;
5393  res->name_space = name_space;
5394  res->name = NULL;
5395  res->alias = NULL;
5396 
5397  if (name != NULL)
5398  {
5399  res->name = ws_copy_string (name);
5400  if (res->name == NULL)
5401  {
5402  goto memory_error;
5403  }
5404  }
5405  if (alias != NULL)
5406  {
5407  res->alias = ws_copy_string (alias);
5408  if (res->alias == NULL)
5409  {
5410  goto memory_error;
5411  }
5412  }
5413 
5414  return res;
5415 
5416 memory_error:
5417  if (res != NULL)
5418  {
5420  }
5421 
5422  return NULL;
5423 }
5424 
5425 /*
5426  * classobj_copy_reslist() - Copies a resolution list.
5427  * The copy can be filtered by using the resspace argument.
5428  * If resspace is ID_INSTANCE, only instance level resolutions
5429  * will be copied. If resspace is ID_CLASS, only class level resolutions
5430  * will be copied. If resspace is ID_NULL, all resolutions will be
5431  * copied.
5432  * return: NO_ERROR on success, non-zero for ERROR
5433  * src(in): source resolution list
5434  * resspace(in): resolution name_space (ID_NULL if no filtering)
5435  * copy_ptr(out): new resolution list
5436  */
5437 
5438 int
5440 {
5441  SM_RESOLUTION *r, *new_resolution, *first, *last;
5442 
5443  first = last = NULL;
5444 
5445  for (r = src; r != NULL; r = r->next)
5446  {
5447  if (resspace == ID_NULL || resspace == r->name_space)
5448  {
5449  new_resolution = classobj_make_resolution (r->class_mop, r->name, r->alias, r->name_space);
5450  if (new_resolution == NULL)
5451  {
5452  goto memory_error;
5453  }
5454 
5455  if (first == NULL)
5456  {
5457  first = new_resolution;
5458  }
5459  else
5460  {
5461  last->next = new_resolution;
5462  }
5463  last = new_resolution;
5464  }
5465  }
5466 
5467  *copy_ptr = first;
5468  return NO_ERROR;
5469 
5470 memory_error:
5471  /* could free the partially constructed resolution list */
5472  assert (er_errid () != NO_ERROR);
5473  return er_errid ();
5474 }
5475 
5476 /*
5477  * classobj_resolution_size() - Calculates the amount of memory used by a resolution.
5478  * return: byte size of resolution
5479  * res(in): resolution
5480  */
5481 
5482 static int
5484 {
5485  int size;
5486 
5487  size = sizeof (SM_RESOLUTION);
5488  size += strlen (res->name) + 1;
5489  if (res->alias != NULL)
5490  {
5491  size += strlen (res->alias) + 1;
5492  }
5493 
5494  return (size);
5495 }
5496 
5497 /*
5498  * classobj_find_resolution() - Searches a resolution list for a resolution
5499  * that matches the arguments.
5500  * return: resolution structure
5501  * reslist(in): list of resolution structures
5502  * class_mop(in): source class
5503  * name(in): attribute/method name
5504  * name_space(in): name_space identifier (class or instance)
5505  */
5506 
5507 SM_RESOLUTION *
5508 classobj_find_resolution (SM_RESOLUTION * reslist, MOP class_mop, const char *name, SM_NAME_SPACE name_space)
5509 {
5510  SM_RESOLUTION *res, *found = NULL;
5511 
5512  for (res = reslist, found; res != NULL && found == NULL; res = res->next)
5513  {
5514  if ((name_space == ID_NULL || name_space == res->name_space) && (class_mop == res->class_mop)
5515  && (strcmp (res->name, name) == 0))
5516  {
5517  found = res;
5518  }
5519  }
5520 
5521  return found;
5522 }
5523 
5524 /* SM_METHOD_FILE */
5525 /*
5526  * classobj_free_method_file() - Frees a method file and any associated storage.
5527  * return: none
5528  * file(in): method file structure
5529  */
5530 
5531 void
5533 {
5534  if (file != NULL)
5535  {
5536  if (file->name != NULL)
5537  {
5538  ws_free_string (file->name);
5539  }
5540  if (file->expanded_name != NULL)
5541  {
5542  ws_free_string (file->expanded_name);
5543  }
5544  if (file->source_name)
5545  {
5546  ws_free_string (file->source_name);
5547  }
5548  db_ws_free (file);
5549  }
5550 }
5551 
5552 /*
5553  * classobj_make_method_file() - This builds a method file structure.
5554  * return: method file structure
5555  * name(in): name of the file
5556  */
5557 
5559 classobj_make_method_file (const char *name)
5560 {
5561  SM_METHOD_FILE *file;
5562 
5563  file = (SM_METHOD_FILE *) db_ws_alloc (sizeof (SM_METHOD_FILE));
5564  if (file == NULL)
5565  {
5566  return NULL;
5567  }
5568 
5569  file->next = NULL;
5570  file->name = NULL;
5571  file->class_mop = NULL;
5572  file->expanded_name = NULL;
5573  file->source_name = NULL;
5574 
5575  if (name != NULL)
5576  {
5577  file->name = ws_copy_string (name);
5578  if (file->name == NULL)
5579  {
5580  db_ws_free (file);
5581  file = NULL;
5582  }
5583  }
5584 
5585  return (file);
5586 }
5587 
5588 /*
5589  * classobj_copy_methfile() - Copy a method file structure.
5590  * return: copied method file
5591  * src(in): method file to copy
5592  */
5593 
5594 static SM_METHOD_FILE *
5596 {
5597  SM_METHOD_FILE *new_method_file = NULL;
5598 
5599  if (src == NULL)
5600  {
5601  return NULL;
5602  }
5603 
5604  new_method_file = classobj_make_method_file (src->name);
5605  if (new_method_file == NULL)
5606  {
5607  return NULL;
5608  }
5609  new_method_file->class_mop = src->class_mop;
5610  if (src->expanded_name != NULL)
5611  {
5612  new_method_file->expanded_name = ws_copy_string (src->expanded_name);
5613  if (new_method_file->expanded_name == NULL)
5614  {
5615  goto memory_error;
5616  }
5617  }
5618  if (src->source_name != NULL)
5619  {
5620  new_method_file->source_name = ws_copy_string (src->source_name);
5621  if (new_method_file->source_name == NULL)
5622  {
5623  goto memory_error;
5624  }
5625  }
5626 
5627  return new_method_file;
5628 
5629 memory_error:
5630  if (new_method_file != NULL)
5631  {
5632  classobj_free_method_file (new_method_file);
5633  }
5634 
5635  return NULL;
5636 }
5637 
5638 /*
5639  * classobj_copy_methfiles() - Copy a list of method files.
5640  * return: NO_ERROR on success, non-zero for ERROR
5641  * files(in): method file list
5642  * filter_class(in): optional filter class
5643  * copy_ptr(out): new method file list
5644  */
5645 
5646 int
5647 classobj_copy_methfiles (SM_METHOD_FILE * files, MOP filter_class, SM_METHOD_FILE ** copy_ptr)
5648 {
5649  SM_METHOD_FILE *f, *new_method_file, *first, *last;
5650 
5651  first = last = NULL;
5652 
5653  for (f = files; f != NULL; f = f->next)
5654  {
5655  if (filter_class == NULL || f->class_mop == NULL || f->class_mop == filter_class)
5656  {
5657  new_method_file = classobj_copy_methfile (f);
5658  if (new_method_file == NULL)
5659  {
5660  goto memory_error;
5661  }
5662  if (first == NULL)
5663  {
5664  first = new_method_file;
5665  }
5666  else
5667  {
5668  last->next = new_method_file;
5669  }
5670  last = new_method_file;
5671  }
5672  }
5673  *copy_ptr = first;
5674  return NO_ERROR;
5675 
5676 memory_error:
5677  assert (er_errid () != NO_ERROR);
5678  return er_errid ();
5679 }
5680 
5681 /*
5682  * classobj_method_file_size() - Calculates the amount of storage used by a method file.
5683  * return: byte size of method file
5684  * file(in): method file structure
5685  */
5686 
5687 static int
5689 {
5690  int size;
5691 
5692  size = sizeof (SM_METHOD_FILE);
5693  size += strlen (method_file->name) + 1;
5694 
5695  if (method_file->expanded_name != NULL)
5696  {
5697  size += strlen (method_file->expanded_name) + 1;
5698  }
5699 
5700  if (method_file->source_name != NULL)
5701  {
5702  size += strlen (method_file->source_name) + 1;
5703  }
5704 
5705  return (size);
5706 }
5707 
5708 /* SM_REPR_ATTRIBUTE */
5709 /*
5710  * classobj_make_repattribute() - Creates a new representation attribute structure.
5711  * return: new repattribute structure
5712  * attid(in): attribute id
5713  * typeid(in): type id
5714  * domain(in):
5715  */
5716 
5718 classobj_make_repattribute (int attid, DB_TYPE type_id, TP_DOMAIN * domain)
5719 {
5720  SM_REPR_ATTRIBUTE *rat;
5721 
5722  rat = (SM_REPR_ATTRIBUTE *) db_ws_alloc (sizeof (SM_REPR_ATTRIBUTE));
5723 
5724  if (rat == NULL)
5725  {
5726  return NULL;
5727  }
5728  rat->next = NULL;
5729  rat->attid = attid;
5730  rat->typeid_ = type_id;
5731  /* think about consolidating the typeid & domain fields */
5732  rat->domain = domain;
5733 
5734  return (rat);
5735 }
5736 
5737 /*
5738  * classobj_free_repattribute() - Frees storage for a representation attribute.
5739  * return: none
5740  * rat(in): representation attribute
5741  */
5742 
5743 static void
5745 {
5746  if (rat != NULL)
5747  {
5748  db_ws_free (rat);
5749  }
5750 }
5751 
5752 /*
5753  * classobj_repattribute_size() - memory size of a representation attribute.
5754  * return: byte size of attribute
5755  */
5756 
5757 static int
5759 {
5760  int size = sizeof (SM_REPR_ATTRIBUTE);
5761 
5762  return (size);
5763 }
5764 
5765 /* SM_REPRESENTATION */
5766 /*
5767  * classobj_make_representation() - Create a new representation structure.
5768  * return: new representation
5769  */
5770 
5773 {
5774  SM_REPRESENTATION *rep;
5775 
5776  rep = (SM_REPRESENTATION *) db_ws_alloc (sizeof (SM_REPRESENTATION));
5777 
5778  if (rep == NULL)
5779  {
5780  return NULL;
5781  }
5782  rep->next = NULL;
5783  rep->id = -1;
5784  rep->fixed_count = 0;
5785  rep->variable_count = 0;
5786  rep->attributes = NULL;
5787 
5788  return (rep);
5789 }
5790 
5791 /*
5792  * classobj_free_representation() - Free a representation structure and any
5793  * associated memory.
5794  * return: none
5795  * rep(in): representation
5796  */
5797 
5798 void
5800 {
5801  if (rep != NULL)
5802  {
5804  db_ws_free (rep);
5805  }
5806 }
5807 
5808 /*
5809  * classobj_representation_size() - memory storage used by a representation.
5810  * return: byte size of representation
5811  * rep(in): representation strcuture
5812  */
5813 
5814 static int
5816 {
5817  SM_REPR_ATTRIBUTE *rat;
5818  int size;
5819 
5820  size = sizeof (SM_REPRESENTATION);
5821  for (rat = rep->attributes; rat != NULL; rat = rat->next)
5822  {
5823  size += classobj_repattribute_size ();
5824  }
5825 
5826  return (size);
5827 }
5828 
5829 /* SM_QUERY_SPEC */
5830 /*
5831  * classobj_make_query_spec() - Allocate and initialize a query_spec structure.
5832  * return: new query_spec structure
5833  * specification(in): query_spec string
5834  */
5835 
5836 SM_QUERY_SPEC *
5837 classobj_make_query_spec (const char *specification)
5838 {
5839  SM_QUERY_SPEC *query_spec;
5840 
5841  query_spec = (SM_QUERY_SPEC *) db_ws_alloc (sizeof (SM_QUERY_SPEC));
5842 
5843  if (query_spec == NULL)
5844  {
5845  return NULL;
5846  }
5847 
5848  query_spec->next = NULL;
5849  query_spec->specification = NULL;
5850 
5851  if (specification != NULL)
5852  {
5853  query_spec->specification = ws_copy_string (specification);
5854  if (query_spec->specification == NULL)
5855  {
5856  db_ws_free (query_spec);
5857  query_spec = NULL;
5858  }
5859  }
5860 
5861  return (query_spec);
5862 }
5863 
5864 /*
5865  * classobj_copy_query_spec_list() - Copy a list of SM_QUERY_SPEC structures.
5866  * return: new list
5867  * query_spec(in): source list
5868  */
5869 
5870 SM_QUERY_SPEC *
5872 {
5873  SM_QUERY_SPEC *p, *new_, *first, *last;
5874 
5875  first = last = NULL;
5876  for (p = query_spec; p != NULL; p = p->next)
5877  {
5879  if (new_ == NULL)
5880  {
5881  goto memory_error;
5882  }
5883  if (first == NULL)
5884  {
5885  first = new_;
5886  }
5887  else
5888  {
5889  last->next = new_;
5890  }
5891  last = new_;
5892  }
5893  return (first);
5894 
5895 memory_error:
5896  return NULL;
5897 }
5898 
5899 /*
5900  * classobj_free_query_spec() - Frees storage for a query_spec specification and
5901  * any associated memory.
5902  * return: none
5903  * query_spec(in): query_spec structure to free
5904  */
5905 
5906 void
5908 {
5909  if (query_spec != NULL)
5910  {
5911  if (query_spec->specification != NULL)
5912  {
5913  ws_free_string (query_spec->specification);
5914  }
5915  db_ws_free (query_spec);
5916  }
5917 }
5918 
5919 /*
5920  * classobj_query_spec_size() - Calculates the amount of storage used by
5921  * a query_spec structure.
5922  * return: byte size of query_spec
5923  * query_spec(in): query_spec structure
5924  */
5925 
5926 static int
5928 {
5929  int size;
5930 
5931  size = sizeof (SM_QUERY_SPEC);
5932  size += strlen (query_spec->specification) + 1;
5933 
5934  return (size);
5935 }
5936 
5937 /*
5938  * classobj_partition_info_size () - Calculates the amount of storage used by
5939  * a sm_partition structure
5940  * return: byte size of query_spec
5941  * partition_info(in): sm_partition structure
5942  */
5943 
5944 static int
5946 {
5947  int size;
5948  DB_VALUE val;
5949 
5950  size = sizeof (SM_PARTITION);
5951  if (partition_info->comment)
5952  {
5953  size += strlen (partition_info->comment) + 1;
5954  }
5955  if (partition_info->pname)
5956  {
5957  size += strlen (partition_info->pname) + 1;
5958  }
5959  if (partition_info->expr)
5960  {
5961  size += strlen (partition_info->expr) + 1;
5962  }
5963  db_make_sequence (&val, partition_info->values);
5964  size += or_packed_value_size (&val, 1, 1, 0);
5965 
5966  return (size);
5967 }
5968 
5969 /* SM_TEMPLATE */
5970 /*
5971  * classobj_free_template() - Frees a class template and any associated memory.
5972  * return: none
5973  * template(in): class editing template
5974  */
5975 
5976 void
5978 {
5979  if (template_ptr == NULL)
5980  {
5981  return;
5982  }
5983  ml_free (template_ptr->inheritance);
5984 
5986  ws_list_free ((DB_LIST *) template_ptr->class_attributes, (LFREEER) classobj_free_attribute);
5987  ws_list_free ((DB_LIST *) template_ptr->instance_attributes, (LFREEER) classobj_free_attribute);
5988  ws_list_free ((DB_LIST *) template_ptr->shared_attributes, (LFREEER) classobj_free_attribute);
5989  ws_list_free ((DB_LIST *) template_ptr->methods, (LFREEER) classobj_free_method);
5990  ws_list_free ((DB_LIST *) template_ptr->class_methods, (LFREEER) classobj_free_method);
5992  ws_list_free ((DB_LIST *) template_ptr->class_resolutions, (LFREEER) classobj_free_resolution);
5996  ws_free_string (template_ptr->loader_commands);
5997  ws_free_string (template_ptr->name);
5998 
5999  if (template_ptr->super_id_map != NULL)
6000  {
6001  db_ws_free (template_ptr->super_id_map);
6002  }
6003 
6004  classobj_free_prop (template_ptr->properties);
6005 
6006  ml_ext_free (template_ptr->ext_references);
6007 
6008  if (template_ptr->triggers != NULL)
6009  {
6010  tr_free_schema_cache ((TR_SCHEMA_CACHE *) template_ptr->triggers);
6011  }
6012 
6013  (void) area_free (Template_area, template_ptr);
6014 
6015 }
6016 
6017 /*
6018  * classobj_make_template() - Allocates and initializes a class editing template.
6019  * The class MOP and structure are optional, it supplied the template
6020  * will be initialized with the contents of the class. If not supplied
6021  * the template will be empty.
6022  * return: new template
6023  * name(in): class name
6024  * op(in): class MOP
6025  * class(in): class structure
6026  */
6027 
6028 SM_TEMPLATE *
6029 classobj_make_template (const char *name, MOP op, SM_CLASS * class_)
6030 {
6031  SM_TEMPLATE *template_ptr;
6032  int error = NO_ERROR;
6033 
6034  template_ptr = (SM_TEMPLATE *) area_alloc (Template_area);
6035  if (template_ptr == NULL)
6036  {
6037  return NULL;
6038  }
6039 
6040  template_ptr->class_type = SM_CLASS_CT;
6041  template_ptr->op = op;
6042  template_ptr->current = class_;
6043  template_ptr->tran_index = tm_Tran_index;
6044  template_ptr->name = NULL;
6045  template_ptr->inheritance = NULL;
6046  template_ptr->attributes = NULL;
6047  template_ptr->class_attributes = NULL;
6048  template_ptr->methods = NULL;
6049  template_ptr->class_methods = NULL;
6050  template_ptr->resolutions = NULL;
6051  template_ptr->class_resolutions = NULL;
6052  template_ptr->method_files = NULL;
6053  template_ptr->loader_commands = NULL;
6054  template_ptr->query_spec = NULL;
6055  template_ptr->instance_attributes = NULL;
6056  template_ptr->shared_attributes = NULL;
6057  template_ptr->ext_references = NULL;
6058  template_ptr->properties = NULL;
6059  template_ptr->super_id_map = NULL;
6060  template_ptr->triggers = NULL;
6061  template_ptr->partition_parent_atts = NULL;
6062  template_ptr->partition = NULL;
6063 
6064  if (name != NULL)
6065  {
6066  template_ptr->name = ws_copy_string (name);
6067  if (template_ptr->name == NULL)
6068  {
6069  goto memory_error;
6070  }
6071  }
6072 
6073  if (class_ != NULL)
6074  {
6075  template_ptr->class_type = class_->class_type;
6076 
6077  if (classobj_copy_attlist (class_->ordered_attributes, op, 1, &template_ptr->attributes))
6078  {
6079  goto memory_error;
6080  }
6081 
6082  if (classobj_copy_attlist (class_->class_attributes, op, 0, &template_ptr->class_attributes))
6083  {
6084  goto memory_error;
6085  }
6086 
6087  if (classobj_copy_methlist (class_->methods, op, &template_ptr->methods))
6088  {
6089  goto memory_error;
6090  }
6091 
6092  if (classobj_copy_methlist (class_->class_methods, op, &template_ptr->class_methods))
6093  {
6094  goto memory_error;
6095  }
6096 
6097  if (classobj_copy_reslist (class_->resolutions, ID_INSTANCE, &template_ptr->resolutions))
6098  {
6099  goto memory_error;
6100  }
6101 
6102  if (classobj_copy_reslist (class_->resolutions, ID_CLASS, &template_ptr->class_resolutions))
6103  {
6104  goto memory_error;
6105  }
6106 
6107  if (classobj_copy_methfiles (class_->method_files, op, &template_ptr->method_files))
6108  {
6109  goto memory_error;
6110  }
6111 
6112  if (class_->inheritance != NULL)
6113  {
6114  template_ptr->inheritance = ml_copy (class_->inheritance);
6115  if (template_ptr->inheritance == NULL)
6116  {
6117  goto memory_error;
6118  }
6119  }
6120  if (class_->loader_commands != NULL)
6121  {
6122  template_ptr->loader_commands = ws_copy_string (class_->loader_commands);
6123  if (template_ptr->loader_commands == NULL)
6124  {
6125  goto memory_error;
6126  }
6127  }
6128  if (class_->query_spec)
6129  {
6130  template_ptr->query_spec = classobj_copy_query_spec_list (class_->query_spec);
6131  if (template_ptr->query_spec == NULL)
6132  {
6133  goto memory_error;
6134  }
6135  }
6136  if (class_->properties != NULL)
6137  {
6138  error = classobj_copy_props (class_->properties, op, &template_ptr->properties);
6139  if (error != NO_ERROR)
6140  {
6141  goto memory_error;
6142  }
6143  }
6144  if (class_->triggers != NULL)
6145  {
6146  template_ptr->triggers = tr_copy_schema_cache (class_->triggers, op);
6147  if (template_ptr->triggers == NULL)
6148  {
6149  goto memory_error;
6150  }
6151  }
6152  if (class_->partition != NULL)
6153  {
6154  template_ptr->partition = classobj_copy_partition_info (class_->partition);
6155  if (template_ptr->partition == NULL)
6156  {
6157  goto memory_error;
6158  }
6159  }
6160 
6161  /* Formerly cl_make_id_map(class), forget what that was supposed to do. This isn't currently used. */
6162  template_ptr->super_id_map = NULL;
6163  }
6164 
6165  return (template_ptr);
6166 
6167 memory_error:
6168  if (template_ptr != NULL)
6169  {
6170  classobj_free_template (template_ptr);
6171  }
6172 
6173  return NULL;
6174 }
6175 
6176 /*
6177  * classobj_make_template_like() - Allocates and initializes a class template
6178  * based on an existing class.
6179  * The existing class attributes and constraints are duplicated so that the
6180  * new template can be used for the "CREATE LIKE" statement.
6181  * Triggers are not duplicated (this is the same as MySQL does).
6182  * Indexes cannot be duplicated by this function because class templates
6183  * don't allow index creation. The indexes will be duplicated after the class
6184  * is created.
6185  * Partitions are not yet duplicated by this function.
6186  * return: the new template
6187  * name(in): the name of the new class
6188  * class(in): class structure to duplicate
6189  */
6190 
6191 SM_TEMPLATE *
6192 classobj_make_template_like (const char *name, SM_CLASS * class_)
6193 {
6194  SM_TEMPLATE *template_ptr;
6195  const char *existing_name = NULL;
6196  SM_ATTRIBUTE *a;
6198 
6199  assert (name != NULL);
6200  assert (class_ != NULL);
6201  assert (class_->class_type == SM_CLASS_CT);
6202  assert (class_->query_spec == NULL);
6203 
6204  existing_name = sm_ch_name ((MOBJ) class_);
6205 
6206  if (class_->partition != NULL)
6207  {
6208  /* It is possible to support this but the code has not been written yet. */
6210  "CREATE TABLE ... PARTITION BY");
6211  return NULL;
6212  }
6213 
6214  if (class_->inheritance != NULL || class_->users != NULL || class_->resolutions != NULL)
6215  {
6216  /* Copying a class that is part of an inheritance chain would result in weird situations; we disallow this.
6217  * MySQL's CREATE LIKE did not need to interact with OO features anyway. */
6219  "CREATE CLASS ... UNDER");
6220  return NULL;
6221  }
6222 
6223  if (class_->methods != NULL || class_->class_methods != NULL || class_->method_files != NULL
6224  || class_->loader_commands != NULL)
6225  {
6226  /* It does not make sense to copy the methods that were designed for another class. We could silently ignore the
6227  * methods but we prefer to flag an error because CREATE LIKE will be used for MySQL type applications mostly and
6228  * will not interact with CUBRID features too often. */
6230  "CREATE CLASS ... METHOD");
6231  return NULL;
6232  }
6233 
6234  template_ptr = smt_def_class (name);
6235  if (template_ptr == NULL)
6236  {
6237  return NULL;
6238  }
6239 
6240  if (class_->attributes != NULL || class_->shared != NULL)
6241  {
6242  for (a = class_->ordered_attributes; a != NULL; a = a->order_link)
6243  {
6244  if (classobj_copy_attribute_like (template_ptr, a, existing_name) != NO_ERROR)
6245  {
6246  goto error_exit;
6247  }
6248  }
6249  }
6250 
6251  if (class_->class_attributes != NULL)
6252  {
6253  for (a = class_->class_attributes; a != NULL; a = (SM_ATTRIBUTE *) a->header.next)
6254  {
6255  if (classobj_copy_attribute_like (template_ptr, a, existing_name) != NO_ERROR)
6256  {
6257  goto error_exit;
6258  }
6259  }
6260  }
6261 
6262  if (class_->constraints != NULL)
6263  {
6264  for (c = class_->constraints; c; c = c->next)
6265  {
6267  {
6268  if (classobj_copy_constraint_like (template_ptr, c, existing_name) != NO_ERROR)
6269  {
6270  goto error_exit;
6271  }
6272  }
6273  else
6274  {
6275  /* NOT NULL have already been copied by classobj_copy_attribute_like. INDEX will be duplicated after the
6276  * class is created. */
6278  || c->type == SM_CONSTRAINT_NOT_NULL);
6279  }
6280  }
6281  }
6282 
6283  return template_ptr;
6284 
6285 error_exit:
6286  if (template_ptr != NULL)
6287  {
6288  classobj_free_template (template_ptr);
6289  }
6290 
6291  return NULL;
6292 }
6293 
6294 /*
6295  * classobj_copy_attribute_like() - Copies an attribute from an existing class
6296  * to a new class template.
6297  * Potential NOT NULL constraints on the attribute are copied also.
6298  * return: NO_ERROR on success, non-zero for ERROR
6299  * ctemplate(in): the template to copy to
6300  * attribute(in): the attribute to be duplicated
6301  * like_class_name(in): the name of the class that is duplicated
6302  */
6303 
6304 static int
6305 classobj_copy_attribute_like (DB_CTMPL * ctemplate, SM_ATTRIBUTE * attribute, const char *const like_class_name)
6306 {
6307  int error = NO_ERROR;
6308  const char *names[2];
6309 
6310  assert (like_class_name != NULL);
6311 
6312  if (attribute->flags & SM_ATTFLAG_AUTO_INCREMENT)
6313  {
6314  /* It is possible to support this but the code has not been written yet. The fact that CUBRID supports the
6315  * "AUTO_INCREMENT(start_at, increment)" syntax complicates the duplication of the attribute. */
6316  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CANT_COPY_WITH_FEATURE, 3, ctemplate->name, like_class_name,
6317  "AUTO_INCREMENT");
6318  return er_errid ();
6319  }
6320 
6321  error =
6322  smt_add_attribute_w_dflt (ctemplate, attribute->header.name, NULL, attribute->domain,
6323  &attribute->default_value.value, attribute->header.name_space,
6324  &attribute->default_value.default_expr,
6325  &attribute->on_update_default_expr, attribute->comment);
6326  if (error != NO_ERROR)
6327  {
6328  return error;
6329  }
6330 
6331  if (attribute->flags & SM_ATTFLAG_NON_NULL)
6332  {
6333  names[0] = attribute->header.name;
6334  names[1] = NULL;
6335  error =
6336  dbt_add_constraint (ctemplate, DB_CONSTRAINT_NOT_NULL, NULL, names,
6337  attribute->header.name_space == ID_CLASS_ATTRIBUTE ? 1 : 0, NULL);
6338  if (error != NO_ERROR)
6339  {
6340  return error;
6341  }
6342  }
6343 
6344  return error;
6345 }
6346 
6347 /*
6348  * classobj_point_at_att_names() - Allocates a NULL-terminated array of pointers
6349  * to the names of the attributes referenced in
6350  * a constraint.
6351  * return: the array on success, NULL on error
6352  * constraint(in): the constraint
6353  * count_ref(out): if supplied, the referenced integer will be modified to
6354  * contain the number of attributes
6355  */
6356 
6357 const char **
6358 classobj_point_at_att_names (SM_CLASS_CONSTRAINT * constraint, int *count_ref)
6359 {
6360  const char **att_names = NULL;
6361  SM_ATTRIBUTE **attribute_p = NULL;
6362  int count;
6363  int i;
6364 
6365  for (attribute_p = constraint->attributes, count = 0; *attribute_p; ++attribute_p)
6366  {
6367  ++count;
6368  }
6369  att_names = (const char **) malloc ((count + 1) * sizeof (const char *));
6370  if (att_names == NULL)
6371  {
6372  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (count + 1) * sizeof (const char *));
6373  return NULL;
6374  }
6375  for (attribute_p = constraint->attributes, i = 0; *attribute_p != NULL; ++attribute_p, ++i)
6376  {
6377  att_names[i] = (*attribute_p)->header.name;
6378  }
6379  att_names[i] = NULL;
6380 
6381  if (count_ref != NULL)
6382  {
6383  *count_ref = count;
6384  }
6385  return att_names;
6386 }
6387 
6388 /*
6389  * classobj_copy_constraint_like() - Copies a constraint from an existing
6390  * class to a new class template.
6391  * Constraint names are copied as they are, even if they are the defaults
6392  * given to unnamed constraints. The default names will be a bit misleading
6393  * since they will have the duplicated class name in their contents. MySQL
6394  * also copies the default name for indexes.
6395  * return: NO_ERROR on success, non-zero for ERROR
6396  * ctemplate(in): the template to copy to
6397  * constraint(in): the constraint to be duplicated
6398  * like_class_name(in): the name of the class that is duplicated
6399  */
6400 
6401 static int
6403  const char *const like_class_name)
6404 {
6405  int error = NO_ERROR;
6406  DB_CONSTRAINT_TYPE constraint_type = db_constraint_type (constraint);
6407  const char **att_names = NULL;
6408  const char **ref_attrs = NULL;
6409  int count = 0;
6410  int count_ref = 0;
6411  char *auto_cons_name = NULL;
6412  char *new_cons_name = NULL;
6413 
6414  assert (like_class_name != NULL);
6415 
6416  /* We are sure this will not be a class constraint (the only possible class constraints are NOT NULL constraints). */
6417  assert (constraint_type != DB_CONSTRAINT_NOT_NULL);
6418 
6419  /* We are sure this constraint can be processed by dbt_add_constraint (indexes cannot be added to templates). */
6420  assert (constraint_type != DB_CONSTRAINT_INDEX && constraint_type != DB_CONSTRAINT_REVERSE_INDEX);
6421 
6422  att_names = classobj_point_at_att_names (constraint, &count);
6423  if (att_names == NULL)
6424  {
6425  assert (er_errid () != NO_ERROR);
6426  return er_errid ();
6427  }
6428 
6429  auto_cons_name = sm_produce_constraint_name (like_class_name, constraint_type, att_names, constraint->asc_desc, NULL);
6430  if (auto_cons_name == NULL)
6431  {
6432  assert (er_errid () != NO_ERROR);
6433  error = er_errid ();
6434  goto error_exit;
6435  }
6436 
6437  /* check if constraint's name was generated automatically */
6438  if (strcmp (auto_cons_name, constraint->name) == 0)
6439  {
6440  /* regenerate name automatically for new class */
6441  new_cons_name =
6442  sm_produce_constraint_name_tmpl (ctemplate, constraint_type, att_names, constraint->asc_desc, NULL);
6443  if (new_cons_name == NULL)
6444  {
6445  assert (er_errid () != NO_ERROR);
6446  error = er_errid ();
6447  goto error_exit;
6448  }
6449  }
6450  else
6451  {
6452  /* use name given by user */
6453  new_cons_name = (char *) constraint->name;
6454  }
6455 
6456  if (auto_cons_name != NULL)
6457  {
6458  free_and_init (auto_cons_name);
6459  }
6460 
6461  if (constraint_type != DB_CONSTRAINT_FOREIGN_KEY)
6462  {
6463  error = smt_add_constraint (ctemplate, constraint_type, new_cons_name, att_names,
6464  (constraint_type == DB_CONSTRAINT_UNIQUE) ? constraint->asc_desc : NULL, NULL, 0,
6465  NULL, constraint->filter_predicate, constraint->func_index_info, constraint->comment,
6466  constraint->index_status);
6467  }
6468  else
6469  {
6470  MOP ref_clsop;
6471  SM_CLASS *ref_cls;
6473 
6474  assert (constraint->fk_info != NULL);
6475  ref_clsop = ws_mop (&(constraint->fk_info->ref_class_oid), NULL);
6476  if (ref_clsop == NULL)
6477  {
6478  assert (er_errid () != NO_ERROR);
6479  error = er_errid ();
6480  goto error_exit;
6481  }
6482  error = au_fetch_class_force (ref_clsop, &ref_cls, AU_FETCH_READ);
6483  if (error != NO_ERROR)
6484  {
6485  goto error_exit;
6486  }
6487  assert (ref_cls->constraints != NULL);
6488 
6490  if (c != NULL)
6491  {
6492  ref_attrs = classobj_point_at_att_names (c, &count_ref);
6493  if (ref_attrs == NULL)
6494  {
6495  goto error_exit;
6496  }
6497  assert (count == count_ref);
6498  }
6499  else
6500  {
6501  assert (false);
6503  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, sm_ch_name ((MOBJ) ref_cls));
6504  goto error_exit;
6505  }
6506 
6507  error =
6508  dbt_add_foreign_key (ctemplate, new_cons_name, att_names, sm_ch_name ((MOBJ) ref_cls), ref_attrs,
6509  constraint->fk_info->delete_action, constraint->fk_info->update_action,
6510  constraint->comment);
6511  free_and_init (ref_attrs);
6512  }
6513 
6514  free_and_init (att_names);
6515 
6516  if (new_cons_name != NULL && new_cons_name != constraint->name)
6517  {
6518  free_and_init (new_cons_name);
6519  }
6520 
6521  return error;
6522 
6523 error_exit:
6524 
6525  if (att_names != NULL)
6526  {
6527  free_and_init (att_names);
6528  }
6529 
6530  if (ref_attrs != NULL)
6531  {
6532  free_and_init (ref_attrs);
6533  }
6534 
6535  if (new_cons_name != NULL && new_cons_name != constraint->name)
6536  {
6537  free_and_init (new_cons_name);
6538  }
6539 
6540  return error;
6541 }
6542 
6543 
6544 #if defined(ENABLE_UNUSED_FUNCTION)
6545 /*
6546  * classobj_add_template_reference() - The template keeps a list of all MOPS that
6547  * are placed inside the template in an external objlist format so they will
6548  * serve as roots to the garbage collector. This prevents any MOPs in the
6549  * template from being reclaimed. See the discussion under
6550  * Template_area above for more information.
6551  * return: NO_ERROR on success, non-zero for ERROR
6552  * template(in/out): class editing template
6553  * obj(in): MOP to register
6554  */
6555 
6556 int
6557 classobj_add_template_reference (SM_TEMPLATE * template_ptr, MOP obj)
6558 {
6559  return ml_ext_add (&template_ptr->ext_references, obj, NULL);
6560 }
6561 #endif /* ENABLE_UNUSED_FUNCTION */
6562 
6563 /* SM_CLASS */
6564 /*
6565  * classobj_make_class() - Creates a new class structure.
6566  * return: new class structure
6567  * name(in): class name
6568  */
6569 
6570 SM_CLASS *
6571 classobj_make_class (const char *name)
6572 {
6573  SM_CLASS *class_;
6574 
6575  class_ = (SM_CLASS *) db_ws_alloc (sizeof (SM_CLASS));
6576  if (class_ == NULL)
6577  {
6578  return NULL;
6579  }
6580 
6581  class_->class_type = SM_CLASS_CT;
6582  class_->header.ch_obj_header.chn = NULL_CHN; /* start with NULL chn ? */
6583  class_->header.ch_type = SM_META_CLASS;
6584  class_->header.ch_name = NULL;
6585  /* shouldn't know how to initialize these, either need external init function */
6586  OID_SET_NULL (&(class_->header.ch_rep_dir));
6587  HFID_SET_NULL (&(class_->header.ch_heap));
6589 
6590  class_->repid = 0; /* initial rep is zero */
6591  class_->users = NULL;
6592  class_->representations = NULL;
6593  class_->inheritance = NULL;
6594 
6595  class_->object_size = 0;
6596  class_->att_count = 0;
6597  class_->attributes = NULL;
6598  class_->shared_count = 0;
6599  class_->shared = NULL;
6600  class_->class_attribute_count = 0;
6601  class_->class_attributes = NULL;
6602  class_->ordered_attributes = NULL;
6603 
6604  class_->method_count = 0;
6605  class_->methods = NULL;
6606  class_->class_method_count = 0;
6607  class_->class_methods = NULL;
6608  class_->method_files = NULL;
6609  class_->query_spec = NULL;
6610  class_->loader_commands = NULL;
6611  class_->resolutions = NULL;
6612  class_->partition = NULL;
6613 
6614  class_->fixed_count = 0;
6615  class_->variable_count = 0;
6616  class_->fixed_size = 0;
6617 
6618  class_->methods_loaded = 0;
6619  class_->post_load_cleanup = 0;
6620  class_->triggers_validated = 0;
6621  class_->has_active_triggers = 0;
6623  class_->recache_constraints = 0;
6624 
6625  class_->att_ids = 0;
6626  class_->method_ids = 0;
6627 
6628  class_->new_ = NULL;
6629  class_->stats = NULL;
6630  class_->owner = NULL;
6631  class_->collation_id = LANG_SYS_COLLATION;
6632  class_->auth_cache = NULL;
6633  class_->flags = 0;
6634 
6635  class_->properties = NULL;
6636  class_->virtual_cache_local_schema_id = 0;
6637  class_->virtual_cache_global_schema_id = 0;
6638  class_->virtual_cache_snapshot_version = 0;
6639  class_->virtual_query_cache = NULL;
6640  class_->triggers = NULL;
6641  class_->constraints = NULL;
6642  class_->comment = NULL;
6643 
6644  class_->tde_algorithm = (int) TDE_ALGORITHM_NONE;
6645 
6646  if (name != NULL)
6647  {
6648  class_->header.ch_name = ws_copy_string (name);
6649  if (class_->header.ch_name == NULL)
6650  {
6651  db_ws_free (class_);
6652  class_ = NULL;
6653  }
6654  }
6655 
6656  return (class_);
6657 }
6658 
6659 /*
6660  * classobj_free_class() - Frees a class and any associated memory.
6661  * return: none
6662  * class(in): class structure
6663  */
6664 
6665 void
6667 {
6668  if (class_ == NULL)
6669  {
6670  return;
6671  }
6672 
6675  ws_free_string_and_init (class_->comment);
6676  ml_free_and_init (class_->users);
6677  ml_free_and_init (class_->inheritance);
6678 
6684 
6690 
6691  /* this shouldn't happen here ? - make sure we can't GC this away in the middle of an edit. */
6692 #if 0
6693  if (class_->new_ != NULL)
6694  {
6695  classobj_free_template (class_->new_);
6696  }
6697 #endif /* 0 */
6698 
6699  if (class_->stats != NULL)
6700  {
6702  }
6703 
6704  if (class_->properties != NULL)
6705  {
6707  }
6708 
6709  if (class_->virtual_query_cache != NULL)
6710  {
6712  }
6713 
6714  if (class_->triggers != NULL)
6715  {
6717  }
6718 
6719  if (class_->auth_cache != NULL)
6720  {
6722  }
6723 
6724  if (class_->constraints != NULL)
6725  {
6727  }
6728 
6729  db_ws_free_and_init (class_);
6730 
6731 }
6732 
6733 /*
6734  * classobj_class_size() - Calculates the amount of memory used by a class structure.
6735  * return: byte size of class
6736  * class(in): class structure
6737  */
6738 
6739 int
6741 {
6742  SM_ATTRIBUTE *att;
6743  SM_METHOD *meth;
6744  int size;
6745 
6746  size = sizeof (SM_CLASS);
6747  size += strlen (sm_ch_name ((MOBJ) class_)) + 1;
6748  size += ws_list_total ((DB_LIST *) class_->representations, (LTOTALER) classobj_representation_size);
6749 
6750  size += ml_size (class_->users);
6751  size += ml_size (class_->inheritance);
6752 
6753  size += ws_list_total ((DB_LIST *) class_->resolutions, (LTOTALER) classobj_resolution_size);
6754  size += ws_list_total ((DB_LIST *) class_->method_files, (LTOTALER) classobj_method_file_size);
6755  size += ws_list_total ((DB_LIST *) class_->query_spec, (LTOTALER) classobj_query_spec_size);
6756 
6757  size += ws_list_total ((DB_LIST *) class_->partition, (LTOTALER) classobj_partition_info_size);
6758 
6759  if (class_->loader_commands != NULL)
6760  {
6761  size += strlen (class_->loader_commands) + 1;
6762  }
6763 
6764  if (class_->comment != NULL)
6765  {
6766  size += strlen (class_->comment) + 1;
6767  }
6768 
6769  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
6770  {
6771  size += classobj_attribute_size (att);
6772  }
6773 
6774  for (att = class_->shared; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
6775  {
6776  size += classobj_attribute_size (att);
6777  }
6778 
6779  for (att = class_->class_attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
6780  {
6781  size += classobj_attribute_size (att);
6782  }
6783 
6784  for (meth = class_->methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
6785  {
6786  size += classobj_method_size (meth);
6787  }
6788 
6789  for (meth = class_->class_methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
6790  {
6791  size += classobj_method_size (meth);
6792  }
6793 
6794  /* should have trigger cache here */
6795  /* should have constraint cache here */
6796 
6797  return (size);
6798 }
6799 
6800 /*
6801  * classobj_insert_ordered_attribute() - Inserts an attribute in a list ordered by
6802  * the "order" field in the attribute.
6803  * Work function for classobj_fixup_loaded_class.
6804  * return: none
6805  * attlist(in/out): pointer to attribute list root
6806  * att(in): attribute to insert
6807  */
6808 
6809 static void
6811 {
6812  SM_ATTRIBUTE *a, *prev;
6813 
6814  prev = NULL;
6815  for (a = *attlist; a != NULL && a->order < att->order; a = a->order_link)
6816  {
6817  prev = a;
6818  }
6819 
6820  att->order_link = a;
6821  if (prev == NULL)
6822  {
6823  *attlist = att;
6824  }
6825  else
6826  {
6827  prev->order_link = att;
6828  }
6829 }
6830 
6831 /*
6832  * classobj_fixup_loaded_class() - Orders the instance and shared attributes of
6833  * a class in a single list according to the order in which the attributes
6834  * were defined. This list is not stored with the disk representation of
6835  * a class, it is created in memory when the class is loaded.
6836  * The actual attribute lists are kept separate in storage order.
6837  * The transformer can call this for a newly loaded class or the
6838  * schema manager can call this after a class has been edited to
6839  * create the ordered list prior to returning control to the user.
6840  * This now also goes through and assigns storage_order because this
6841  * isn't currently stored as part of the disk representation.
6842  * return: none
6843  * class(in/out): class to order
6844  */
6845 
6846 void
6848 {
6849  SM_ATTRIBUTE *att;
6850  SM_METHOD *meth;
6851  int i, offset, fixed_count;
6852 
6853  class_->ordered_attributes = NULL;
6854 
6855  /* Calculate the number of fixed width attributes, Isn't this already set in the fixed_count field ? */
6856  fixed_count = 0;
6857  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
6858  {
6859  if (!att->domain->type->variable_p)
6860  {
6861  fixed_count++;
6862  }
6863  }
6864 
6865  /* calculate the instance memory offset to the first attribute */
6866  offset = sizeof (WS_OBJECT_HEADER);
6867 
6868  /* if we have at least one fixed width attribute, then we'll also need a bound bit array. */
6869  if (fixed_count)
6870  {
6871  offset += OBJ_BOUND_BIT_BYTES (fixed_count);
6872  }
6873 
6874  /* Make sure the first attribute is brought up to a longword alignment. */
6875  offset = DB_ATT_ALIGN (offset);
6876 
6877  /* set storage order index and calculate memory offsets */
6878  for (i = 0, att = class_->attributes; att != NULL; i++, att = (SM_ATTRIBUTE *) att->header.next)
6879  {
6880  att->storage_order = i;
6881 
6882  /* when we get to the end of the fixed attributes, bring the alignment up to a word boundary. */
6883  if (i == fixed_count)
6884  {
6885  offset = DB_ATT_ALIGN (offset);
6886  }
6887 
6888  att->offset = offset;
6889  offset += tp_domain_memory_size (att->domain);
6891  }
6892 
6893  offset = DB_ATT_ALIGN (offset);
6894  class_->object_size = offset;
6895 
6896  for (i = 0, att = class_->shared; att != NULL; i++, att = (SM_ATTRIBUTE *) att->header.next)
6897  {
6899  }
6900 
6901  /* the list is ordered, since during flattening there may have been "holes" in the order numbers due to conflicts in
6902  * multiple inheritance, whip through the list and re-number things */
6903 
6904  for (att = class_->ordered_attributes, i = 0; att != NULL; att = att->order_link, i++)
6905  {
6906  att->order = i;
6907  }
6908 
6909  /* for consistency, make sure the other lists are ordered according to definition as well */
6910 
6911  for (att = class_->class_attributes, i = 0; att != NULL; att = (SM_ATTRIBUTE *) att->header.next, i++)
6912  {
6913  att->order = i;
6914  }
6915 
6916  for (meth = class_->methods, i = 0; meth != NULL; meth = (SM_METHOD *) meth->header.next, i++)
6917  {
6918  meth->order = i;
6919  }
6920 
6921  for (meth = class_->class_methods, i = 0; meth != NULL; meth = (SM_METHOD *) meth->header.next, i++)
6922  {
6923  meth->order = i;
6924  }
6925 
6926  if (!class_->dont_decache_constraints_or_flush)
6927  {
6928  /* Cache constraints into both the class constraint list & the attribute constraint lists. */
6929  (void) classobj_cache_class_constraints (class_);
6930  (void) classobj_cache_constraints (class_);
6931  }
6932  else
6933  {
6934  class_->recache_constraints = 1;
6935  }
6936 }
6937 
6938 /*
6939  * classobj_capture_representation() - Builds a representation structure for
6940  * the current state of a class.
6941  * return: new representation structure
6942  * class(in): class structure
6943  */
6944 
6945 static SM_REPRESENTATION *
6947 {
6948  SM_REPRESENTATION *rep;
6949  SM_REPR_ATTRIBUTE *rat, *last;
6950  SM_ATTRIBUTE *att;
6951 
6953  if (rep == NULL)
6954  {
6955  return NULL;
6956  }
6957  rep->id = class_->repid;
6958  rep->fixed_count = class_->fixed_count;
6959  rep->variable_count = class_->variable_count;
6960  rep->next = class_->representations;
6961  rep->attributes = NULL;
6962 
6963  last = NULL;
6964  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
6965  {
6966  rat = classobj_make_repattribute (att->id, TP_DOMAIN_TYPE (att->domain), att->domain);
6967  if (rat == NULL)
6968  {
6969  goto memory_error;
6970  }
6971  if (last == NULL)
6972  {
6973  rep->attributes = rat;
6974  }
6975  else
6976  {
6977  last->next = rat;
6978  }
6979  last = rat;
6980  }
6981 
6982  return (rep);
6983 
6984 memory_error:
6985  if (rep != NULL)
6986  {
6988  }
6989  return NULL;
6990 }
6991 
6992 /*
6993  * classobj_sort_attlist * classobj_sort_methlist() - Work function for classobj_install_template
6994  * Destructively modifies a list so that it is ordered according
6995  * to the "order" field.
6996  * Rather than have two versions of this for attributes and methods,
6997  * can we make this part of the component header ?
6998  * return: none
6999  * source(in/out): list to sort
7000  */
7001 
7002 static void
7004 {
7005  SM_ATTRIBUTE *sorted, *next, *prev, *ins, *att;
7006 
7007  sorted = NULL;
7008  for (att = *source, next = NULL; att != NULL; att = next)
7009  {
7010  next = (SM_ATTRIBUTE *) att->header.next;
7011 
7012  prev = NULL;
7013  for (ins = sorted; ins != NULL && ins->order < att->order; ins = (SM_ATTRIBUTE *) ins->header.next)
7014  {
7015  prev = ins;
7016  }
7017 
7018  att->header.next = (SM_COMPONENT *) ins;
7019  if (prev == NULL)
7020  {
7021  sorted = att;
7022  }
7023  else
7024  {
7025  prev->header.next = (SM_COMPONENT *) att;
7026  }
7027  }
7028  *source = sorted;
7029 }
7030 
7031 /*
7032  * classobj_sort_methlist()
7033  * return: none
7034  * source(in/out): list to sort
7035  */
7036 
7037 static void
7039 {
7040  SM_METHOD *sorted, *next, *prev, *ins, *method;
7041 
7042  sorted = NULL;
7043  for (method = *source, next = NULL; method != NULL; method = next)
7044  {
7045  next = (SM_METHOD *) method->header.next;
7046 
7047  prev = NULL;
7048  for (ins = sorted; ins != NULL && ins->order < method->order; ins = (SM_METHOD *) ins->header.next)
7049  {
7050  prev = ins;
7051  }
7052 
7053  method->header.next = (SM_COMPONENT *) ins;
7054  if (prev == NULL)
7055  {
7056  sorted = method;
7057  }
7058  else
7059  {
7060  prev->header.next = (SM_COMPONENT *) method;
7061  }
7062  }
7063  *source = sorted;
7064 }
7065 
7066 /*
7067  * classobj_install_template() - This is called after a template has been flattened
7068  * and validated to install the new definitions in the class. If the newrep
7069  * argument is non zero, a representation will be saved from the current
7070  * class contents before installing the template.
7071  * NOTE: It is extremely important that as fields in the class structure
7072  * are being replaced, that the field be set to NULL.
7073  * This is particularly important for the attribute lists.
7074  * The reason is that garbage collection can happen during the template
7075  * installation and the attribute lists that are freed must not be
7076  * scanned by the gc class scanner.
7077  * It is critical that errors be handled here without damaging the
7078  * class structure. Perform all allocations before the class is touched
7079  * so we can make sure that if we return an error, the class is untouched.
7080  * return: NO_ERROR on success, non-zero for ERROR
7081  * class(in/out): class structure
7082  * flat(in/out): flattened template
7083  * saverep(in): flag indicating new representation
7084  */
7085 
7086 int
7087 classobj_install_template (SM_CLASS * class_, SM_TEMPLATE * flat, int saverep)
7088 {
7089  SM_ATTRIBUTE *att, *atts, *shared_atts, *class_atts;
7090  SM_METHOD *meth, *methods, *class_methods;
7091  SM_REPRESENTATION *oldrep;
7092  int fixed_size, fixed_count, variable_count;
7093  int att_count, shared_count, class_attribute_count;
7094  int method_count, class_method_count;
7095  int i;
7096 
7097  /* shapshot the representation if necessary */
7098  oldrep = NULL;
7099  if (saverep)
7100  {
7101  oldrep = classobj_capture_representation (class_);
7102  if (oldrep == NULL)
7103  {
7104  goto memory_error;
7105  }
7106  }
7107 
7108  atts = NULL;
7109  shared_atts = NULL;
7110  class_atts = NULL;
7111  methods = NULL;
7112  class_methods = NULL;
7113  fixed_count = 0;
7114  variable_count = 0;
7115  fixed_size = 0;
7116 
7117  att_count = ws_list_length ((DB_LIST *) flat->instance_attributes);
7118  if (att_count)
7119  {
7120  atts = (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), att_count);
7121  if (atts == NULL)
7122  {
7123  goto memory_error;
7124  }
7125 
7126  /* in order to properly calculate the memory offset, we must make an initial pass and count the number of fixed
7127  * width attributes */
7128  for (att = flat->instance_attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7129  {
7130  if (!att->domain->type->variable_p)
7131  {
7132  fixed_count++;
7133  }
7134  else
7135  {
7136  variable_count++;
7137  }
7138  }
7139 
7140  /* calculate the disk size of the fixed width attribute block */
7141  for (att = flat->instance_attributes, i = 0; att != NULL; att = (SM_ATTRIBUTE *) att->header.next, i++)
7142  {
7143  if (classobj_init_attribute (att, &atts[i], 0))
7144  {
7145  goto memory_error;
7146  }
7147  /* disk information */
7148  if (!att->domain->type->variable_p)
7149  {
7150  fixed_size += tp_domain_disk_size (att->domain);
7151  }
7152  }
7153  /* bring the size of the fixed block up to a word boundary */
7154  fixed_size = DB_ATT_ALIGN (fixed_size);
7155  }
7156 
7157  /* SHARED ATTRIBUTES */
7158  shared_count = ws_list_length ((DB_LIST *) flat->shared_attributes);
7159  if (shared_count)
7160  {
7161  shared_atts = (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), shared_count);
7162  if (shared_atts == NULL)
7163  {
7164  goto memory_error;
7165  }
7167  for (att = flat->shared_attributes, i = 0; att != NULL; att = (SM_ATTRIBUTE *) att->header.next, i++)
7168  {
7169  if (classobj_init_attribute (att, &shared_atts[i], 0))
7170  {
7171  goto memory_error;
7172  }
7173  }
7174  }
7175 
7176  /* CLASS ATTRIBUTES */
7177  class_attribute_count = ws_list_length ((DB_LIST *) flat->class_attributes);
7178  if (class_attribute_count)
7179  {
7180  class_atts = (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), class_attribute_count);
7181  if (class_atts == NULL)
7182  {
7183  goto memory_error;
7184  }
7186  for (att = flat->class_attributes, i = 0; att != NULL; att = (SM_ATTRIBUTE *) att->header.next, i++)
7187  {
7188  if (classobj_init_attribute (att, &class_atts[i], 0))
7189  {
7190  goto memory_error;
7191  }
7192  }
7193  }
7194 
7195  /* METHODS */
7196  method_count = ws_list_length ((DB_LIST *) flat->methods);
7197  if (method_count)
7198  {
7199  methods = (SM_METHOD *) classobj_alloc_threaded_array (sizeof (SM_METHOD), method_count);
7200  if (methods == NULL)
7201  {
7202  goto memory_error;
7203  }
7205  for (i = 0, meth = flat->methods; meth != NULL; meth = (SM_METHOD *) meth->header.next, i++)
7206  {
7207  if (classobj_init_method (meth, &methods[i], 0))
7208  {
7209  goto memory_error;
7210  }
7211  }
7212  }
7213 
7214  /* CLASS METHODS */
7215  class_method_count = ws_list_length ((DB_LIST *) flat->class_methods);
7216  if (class_method_count)
7217  {
7218  class_methods = (SM_METHOD *) classobj_alloc_threaded_array (sizeof (SM_METHOD), class_method_count);
7219  if (class_methods == NULL)
7220  {
7221  goto memory_error;
7222  }
7224  for (i = 0, meth = flat->class_methods; meth != NULL; meth = (SM_METHOD *) meth->header.next, i++)
7225  {
7226  if (classobj_init_method (meth, &class_methods[i], 0))
7227  {
7228  goto memory_error;
7229  }
7230  }
7231  }
7232 
7233  /* NO ERRORS ARE ALLOWED AFTER THIS POINT ! Modify the class structure to contain the new information. */
7234 
7235  class_->class_type = flat->class_type;
7236  class_->att_count = att_count;
7237  class_->shared_count = shared_count;
7238  class_->class_attribute_count = class_attribute_count;
7239  class_->method_count = method_count;
7240  class_->class_method_count = class_method_count;
7241  class_->fixed_count = fixed_count;
7242  class_->variable_count = variable_count;
7243  class_->fixed_size = fixed_size;
7244 
7245  /* install attribute/method lists */
7247  class_->attributes = atts;
7248  classobj_free_threaded_array ((DB_LIST *) class_->shared, (LFREEER) classobj_clear_attribute);
7249  class_->shared = shared_atts;
7250  classobj_free_threaded_array ((DB_LIST *) class_->class_attributes, (LFREEER) classobj_clear_attribute);
7251  class_->class_attributes = class_atts;
7253  class_->methods = methods;
7254  classobj_free_threaded_array ((DB_LIST *) class_->class_methods, (LFREEER) classobj_clear_method);
7255  class_->class_methods = class_methods;
7256 
7257  /* build the definition order list from the instance/shared attribute list */
7258  classobj_fixup_loaded_class (class_);
7259 
7260  /* save the old representation */
7261  if (oldrep != NULL)
7262  {
7263  oldrep->next = class_->representations;
7264  class_->representations = oldrep;
7265  class_->repid = class_->repid + 1;
7266  }
7267 
7268  /* install super class list, subclass list stays the same */
7269  ml_free (class_->inheritance);
7270  class_->inheritance = flat->inheritance;
7271  flat->inheritance = NULL;
7272 
7273  /* install loader commands */
7274  ws_free_string (class_->loader_commands);
7275  class_->loader_commands = flat->loader_commands;
7276  flat->loader_commands = NULL;
7277 
7278  /* install method files */
7280  class_->method_files = flat->method_files;
7281  flat->method_files = NULL;
7282 
7283  /* install the query spec */
7285  class_->query_spec = flat->query_spec;
7286  flat->query_spec = NULL;
7287 
7288  /* install the property list */
7289  classobj_free_prop (class_->properties);
7290  class_->properties = flat->properties;
7291  flat->properties = NULL;
7292 
7293  /* install resolution list, merge the res lists in the class for simplicity */
7296  flat->resolutions = NULL;
7297  flat->class_resolutions = NULL;
7298 
7299  /* install trigger cache */
7300  if (class_->triggers != NULL)
7301  {
7302  tr_free_schema_cache (class_->triggers);
7303  }
7304  class_->triggers = (tr_schema_cache *) flat->triggers;
7305  flat->triggers = NULL;
7306 
7308  class_->partition = flat->partition;
7309  flat->partition = NULL;
7310 
7311  if (!class_->dont_decache_constraints_or_flush)
7312  {
7313  /* Cache constraints into both the class constraint list & the attribute constraint lists. */
7314  if (classobj_cache_class_constraints (class_))
7315  {
7316  goto memory_error;
7317  }
7318  if (!classobj_cache_constraints (class_))
7319  {
7320  goto memory_error;
7321  }
7322  }
7323  else
7324  {
7325  class_->recache_constraints = 1;
7326  }
7327 
7328  return NO_ERROR;
7329 
7330 memory_error:
7331  /* This is serious, the caller probably should be prepared to abort the current transaction. The class state has
7332  * been preserved but a nested schema update may now be in an inconsistent state. */
7333  assert (er_errid () != NO_ERROR);
7334  return er_errid ();
7335 }
7336 
7337 /*
7338  * classobj_find_representation() - This searches a class for a representation
7339  * structure with a particular id. Called by the object transformer when
7340  * obsolete objects are encountered.
7341  * return: representation
7342  * class(in): class structure
7343  * id(in): representation id
7344  */
7345 
7348 {
7349  SM_REPRESENTATION *rep, *found;
7350 
7351  for (rep = class_->representations, found = NULL; rep != NULL && found == NULL; rep = rep->next)
7352  {
7353  if (rep->id == id)
7354  {
7355  found = rep;
7356  }
7357  }
7358 
7359  return (found);
7360 }
7361 
7362 /*
7363  * classobj_filter_components() - Extracts components from a list with a
7364  * certain name_space and returns a list of the extracted components.
7365  * The source list is destructively modified.
7366  * return: extracted components
7367  * complist(in/out): component list to filter
7368  * namespace(in): name_space of elements to remove
7369  */
7370 
7371 SM_COMPONENT *
7373 {
7374  SM_COMPONENT *filtered, *comp, *next, *prev;
7375 
7376  filtered = NULL;
7377 
7378  prev = NULL;
7379  for (comp = *complist, next = NULL; comp != NULL; comp = next)
7380  {
7381  next = comp->next;
7382  if (comp->name_space != name_space)
7383  {
7384  prev = comp;
7385  }
7386  else
7387  {
7388  if (prev == NULL)
7389  {
7390  *complist = next;
7391  }
7392  else
7393  {
7394  prev->next = next;
7395  }
7396  comp->next = filtered;
7397  filtered = comp;
7398  }
7399  }
7400  return (filtered);
7401 }
7402 
7403 #if defined (CUBRID_DEBUG)
7404 /*
7405  * classobj_print () - This debug function is used for printing out things
7406  * that aren't displayed by the help_ level utility functions.
7407  * return: none
7408  * class(in): class structure
7409  */
7410 
7411 void
7412 classobj_print (SM_CLASS * class_)
7413 {
7414  SM_ATTRIBUTE *att;
7415  SM_METHOD *meth;
7416 
7417  if (class_ == NULL)
7418  {
7419  return;
7420  }
7421 
7422  file_print_output output_ctx (stdout);
7423  output_ctx ("Class : %s\n", sm_ch_name ((MOBJ) class_));
7424 
7425  if (class_->properties != NULL)
7426  {
7427  output_ctx (" Properties : ");
7428  classobj_print_props (class_->properties);
7429  }
7430 
7431  if (class_->ordered_attributes != NULL)
7432  {
7433  output_ctx ("Attributes\n");
7434  for (att = class_->ordered_attributes; att != NULL; att = att->order_link)
7435  {
7436  output_ctx (" Name=%-25s, id=%3d", att->header.name, att->id);
7437  if (att->domain != NULL && att->domain->type != NULL)
7438  {
7439  output_ctx (", pr_type=%-10s", att->domain->type->name);
7440  }
7441  output_ctx ("\n");
7442  output_ctx (" mem_offset=%3d, order=%3d, storage_order=%3d\n", att->offset, att->order,
7443  att->storage_order);
7444 
7445  if (att->properties != NULL)
7446  {
7447  output_ctx (" Properties : ");
7449  }
7450  if (att->comment != NULL)
7451  {
7452  output_ctx (" ");
7453  help_print_describe_comment (output_ctx, att->comment);
7454  }
7455  output_ctx ("\n");
7456  }
7457  }
7458  if (class_->class_attributes != NULL)
7459  {
7460  output_ctx ("Class Attributes\n");
7461  for (att = class_->class_attributes; att != NULL; att = att->order_link)
7462  {
7463  output_ctx (" Name=%-25s, id=%3d", att->header.name, att->id);
7464  if (att->domain != NULL && att->domain->type != NULL)
7465  {
7466  output_ctx (", pr_type=%-10s", att->domain->type->name);
7467  }
7468  output_ctx ("\n");
7469  output_ctx (" mem_offset=%3d, order=%3d, storage_order=%3d\n", att->offset, att->order,
7470  att->storage_order);
7471 
7472  if (att->properties != NULL)
7473  {
7474  output_ctx (" Properties : ");
7476  }
7477  if (att->comment != NULL)
7478  {
7479  output_ctx (" ");
7480  help_print_describe_comment (output_ctx, att->comment);
7481  }
7482  output_ctx ("\n");
7483  }
7484  }
7485  if (class_->methods != NULL)
7486  {
7487  output_ctx ("Methods\n");
7488  for (meth = class_->methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
7489  {
7490  output_ctx (" %s\n", meth->header.name);
7491  if (meth->properties != NULL)
7492  {
7493  output_ctx (" Properties : ");
7495  }
7496  }
7497  }
7498  if (class_->class_methods != NULL)
7499  {
7500  output_ctx ("Class Methods\n");
7501  for (meth = class_->methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
7502  {
7503  output_ctx (" %s\n", meth->header.name);
7504  if (meth->properties != NULL)
7505  {
7506  output_ctx (" Properties : ");
7508  }
7509  }
7510  }
7511 
7512 }
7513 #endif
7514 
7515 /* MISC UTILITIES */
7516 /*
7517  * classobj_find_attribute() - Finds a named attribute within a class structure.
7518  * return: attribute descriptor
7519  * class(in): class structure
7520  * name(in): attribute name
7521  * class_attribute(in): non-zero if this is a class attribute
7522  */
7523 
7524 SM_ATTRIBUTE *
7525 classobj_find_attribute (SM_CLASS * class_, const char *name, int class_attribute)
7526 {
7527  SM_ATTRIBUTE *att;
7528 
7529  if (class_attribute)
7530  {
7531  for (att = class_->class_attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7532  {
7533  if (intl_identifier_casecmp (att->header.name, name) == 0)
7534  {
7535  return (att);
7536  }
7537  }
7538  }
7539  else
7540  {
7541  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7542  {
7543  if (intl_identifier_casecmp (att->header.name, name) == 0)
7544  {
7545  return (att);
7546  }
7547  }
7548  for (att = class_->shared; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7549  {
7550  if (intl_identifier_casecmp (att->header.name, name) == 0)
7551  {
7552  return (att);
7553  }
7554  }
7555  }
7556  return (NULL);
7557 }
7558 
7559 /*
7560  * classobj_find_attribute_id() - Finds an attribute within a class structure by id.
7561  * return: attribute descriptor
7562  * class(in): class structure
7563  * id(in): attribute id
7564  * class_attribute(in): non-zero if this is a class attribute
7565  */
7566 
7567 SM_ATTRIBUTE *
7568 classobj_find_attribute_id (SM_CLASS * class_, int id, int class_attribute)
7569 {
7570  SM_ATTRIBUTE *att;
7571 
7572  if (class_attribute)
7573  {
7574  for (att = class_->class_attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7575  {
7576  if (att->id == id)
7577  {
7578  return (att);
7579  }
7580  }
7581  }
7582  else
7583  {
7584  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7585  {
7586  if (att->id == id)
7587  {
7588  return (att);
7589  }
7590  }
7591  for (att = class_->shared; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
7592  {
7593  if (att->id == id)
7594  {
7595  return (att);
7596  }
7597  }
7598  }
7599  return (NULL);
7600 }
7601 
7602 /*
7603  * classobj_find_method() - Finds a named method within a class structure.
7604  * return: method structure
7605  * class(in): class structure
7606  * name(in): method name
7607  * class_method(in): non-zero if this is a class method
7608  */
7609 
7610 SM_METHOD *
7611 classobj_find_method (SM_CLASS * class_, const char *name, int class_method)
7612 {
7613  SM_METHOD *meth;
7614 
7615  if (class_method)
7616  {
7617  for (meth = class_->class_methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
7618  {
7619  if (intl_identifier_casecmp (meth->header.name, name) == 0)
7620  {
7621  return (meth);
7622  }
7623  }
7624  }
7625  else
7626  {
7627  for (meth = class_->methods; meth != NULL; meth = (SM_METHOD *) meth->header.next)
7628  {
7629  if (intl_identifier_casecmp (meth->header.name, name) == 0)
7630  {
7631  return (meth);
7632  }
7633  }
7634  }
7635  return (NULL);
7636 }
7637 
7638 /*
7639  * classobj_find_component() - This locates either an attribute or method with
7640  * the given name.
7641  * return: component (NULL if not found)
7642  * name(in): component name (attribute or method)
7643  * class_component(in): non-zero if looking in the class name_space
7644  */
7645 
7646 SM_COMPONENT *
7647 classobj_find_component (SM_CLASS * class_, const char *name, int class_component)
7648 {
7649  SM_COMPONENT *comp;
7650 
7651  if (class_component)
7652  {
7653  for (comp = (SM_COMPONENT *) class_->class_attributes; comp != NULL; comp = comp->next)
7654  {
7655  if (intl_identifier_casecmp (comp->name, name) == 0)
7656  {
7657  return (comp);
7658  }
7659  }
7660  for (comp = (SM_COMPONENT *) class_->class_methods; comp != NULL; comp = comp->next)
7661  {
7662  if (intl_identifier_casecmp (comp->name, name) == 0)
7663  {
7664  return (comp);
7665  }
7666  }
7667  }
7668  else
7669  {
7670  for (comp = (SM_COMPONENT *) class_->attributes; comp != NULL; comp = comp->next)
7671  {
7672  if (intl_identifier_casecmp (comp->name, name) == 0)
7673  {
7674  return (comp);
7675  }
7676  }
7677  for (comp = (SM_COMPONENT *) class_->shared; comp != NULL; comp = comp->next)
7678  {
7679  if (intl_identifier_casecmp (comp->name, name) == 0)
7680  {
7681  return (comp);
7682  }
7683  }
7684  for (comp = (SM_COMPONENT *) class_->methods; comp != NULL; comp = comp->next)
7685  {
7686  if (intl_identifier_casecmp (comp->name, name) == 0)
7687  {
7688  return (comp);
7689  }
7690  }
7691  }
7692  return (NULL);
7693 }
7694 
7695 /*
7696  * classobj_complist_search() - This is used to scan a list of components
7697  * using the usual rules for name comparison.
7698  * return: component pointer
7699  * list(in): list to search
7700  * name(in): name to look for
7701  */
7702 
7703 SM_COMPONENT *
7704 classobj_complist_search (SM_COMPONENT * list, const char *name)
7705 {
7706  SM_COMPONENT *comp;
7707 
7708  for (comp = list; comp != NULL; comp = comp->next)
7709  {
7710  if (intl_identifier_casecmp (comp->name, name) == 0)
7711  {
7712  return (comp);
7713  }
7714  }
7715  return (NULL);
7716 }
7717 
7718 /* DESCRIPTORS */
7719 /*
7720  * classobj_make_desclist() - Builds a descriptor list element and initializes
7721  * all the fields.
7722  * return: descriptor list element
7723  * classobj(in): class MOP
7724  * class(in): class structure
7725  * comp(in): component pointer (attribute or method)
7726  * write_access(in): non-zero if we already have write access
7727  */
7728 
7730 classobj_make_desclist (MOP classobj, SM_CLASS * class_, SM_COMPONENT * comp, int write_access)
7731 {
7732  SM_DESCRIPTOR_LIST *dl;
7733 
7734  dl = (SM_DESCRIPTOR_LIST *) malloc (sizeof (SM_DESCRIPTOR_LIST));
7735  if (dl == NULL)
7736  {
7737  return NULL;
7738  }
7739 
7740  dl->next = NULL;
7741  dl->classobj = classobj;
7742  dl->class_ = class_;
7743  dl->comp = comp;
7744  dl->write_access = write_access;
7745 
7746  return dl;
7747 }
7748 
7749 /*
7750  * classobj_free_desclist() - Frees a descriptor list
7751  * return: none
7752  * dl(in): descriptor list element
7753  */
7754 
7755 void
7757 {
7758  SM_DESCRIPTOR_LIST *next;
7759 
7760  for (next = NULL; dl != NULL; dl = next)
7761  {
7762  next = dl->next;
7763 
7764  /* make sure to NULL potential GC roots */
7765  dl->classobj = NULL;
7766  free_and_init (dl);
7767  }
7768 }
7769 
7770 /*
7771  * classobj_free_descriptor() - Frees a descriptor including all the map list entries
7772  * return: none
7773  * desc(in): descriptor
7774  */
7775 
7776 void
7778 {
7779  if (desc == NULL)
7780  {
7781  return;
7782  }
7783  classobj_free_desclist (desc->map);
7784 
7785  if (desc->name != NULL)
7786  {
7787  free_and_init (desc->name);
7788  }
7789 
7790  if (desc->valid != NULL)
7791  {
7793  free_and_init (desc->valid);
7794  }
7795 
7796  free_and_init (desc);
7797 
7798 }
7799 
7800 /*
7801  * classobj_make_descriptor() - Builds a descriptor structure including an initial
7802  * class map entry and initializes it with the supplied information.
7803  * return: descriptor structure
7804  * class_mop(in): class MOP
7805  * classobj(in): class structure
7806  * comp(in): component (attribute or method)
7807  * write_access(in): non-zero if we already have write access on the class
7808  */
7809 
7810 SM_DESCRIPTOR *
7811 classobj_make_descriptor (MOP class_mop, SM_CLASS * classobj, SM_COMPONENT * comp, int write_access)
7812 {
7813  SM_DESCRIPTOR *desc;
7814  SM_VALIDATION *valid;
7815 
7816  desc = (SM_DESCRIPTOR *) malloc (sizeof (SM_DESCRIPTOR));
7817  if (desc == NULL)
7818  {
7819  return NULL;
7820  }
7821 
7822  desc->next = NULL;
7823  desc->map = NULL;
7824  desc->class_mop = class_mop;
7825 
7826  if (comp != NULL)
7827  {
7828  /* save the component name so we can rebuild the map cache after schema/transaction changes */
7829  desc->name = (char *) malloc (strlen (comp->name) + 1);
7830  if (desc->name == NULL)
7831  {
7832  free_and_init (desc);
7833  return NULL;
7834  }
7835  strcpy (desc->name, comp->name);
7836  desc->name_space = comp->name_space;
7837  }
7838 
7839  /* create the initial map entry if we have the information */
7840  if (class_mop != NULL)
7841  {
7842  desc->map = classobj_make_desclist (class_mop, classobj, comp, write_access);
7843  if (desc->map == NULL)
7844  {
7845  classobj_free_descriptor (desc);
7846  desc = NULL;
7847  }
7848  }
7849 
7850  /* go ahead and make a validation cache all the time */
7851  valid = (SM_VALIDATION *) malloc (sizeof (SM_VALIDATION));
7852  if (valid == NULL)
7853  {
7855  classobj_free_descriptor (desc);
7856  desc = NULL;
7857  }
7858  else
7859  {
7860  if (desc == NULL)
7861  {
7862  free_and_init (valid);
7863  return desc;
7864  }
7865  else
7866  {
7867  desc->valid = valid;
7868  }
7869 
7870  valid->last_class = NULL;
7871  valid->validated_classes = NULL;
7872  valid->last_setdomain = NULL;
7873  /* don't use DB_TYPE_NULL as the "uninitialized" value here as it can prevent NULL constraint checking from
7874  * happening correctly. Should have a magic constant somewhere that could be used for this purpose. */
7875  valid->last_type = DB_TYPE_ERROR;
7876  valid->last_precision = 0;
7877  valid->last_scale = 0;
7878  }
7879 
7880  return desc;
7881 }
7882 
7883 /*
7884  * classobj_check_index_compatibility() - Check whether indexes are compatible.
7885  * return: share, not share, create new index.
7886  * constraint(in): the constraints list
7887  * constraint_type(in): the new constraint type
7888  * filter_predicate(in): the new expression from CREATE INDEX idx
7889  * ON tbl(col1, ...) WHERE filter_predicate
7890  * func_index_info (in): the new function index information
7891  * existing_con(in): the existed relative constraint
7892  * primary_con(out): the reference of existed primary key
7893  *
7894  * There are some rules about index compatibility.
7895  * 1.There is only one primary key allowed in a table.
7896  * 2 The Basic rules of index compatibility are defined in below table.
7897  * share : share index with existed index;
7898  * new idx: create new index;
7899  * error : not share index and return error msg.
7900  * 3 filter_predicate and func_index_info should be checked.
7901  * +---------------+-------------------------------------------------------+
7902  * | | Existed constraint or index |
7903  * | +----------+-----------+---------+----------+-----------+
7904  * | | PK(asc) | PK(desc) | FK | Idx(asc) | Idx(desc) |
7905  * | | /UK(asc) | /UK(desc) | | | /R-Idx |
7906  * | | | /R-UK | | | |
7907  * +---+-----------+----------+-----------+---------+----------+-----------+
7908  * | | PK(asc) | share | new idx | error | error | new idx |
7909  * | n | /UK(asc): | | | | | |
7910  * | e +-----------+----------+-----------+---------+----------+-----------+
7911  * | w | PK(desc) | | | | | |
7912  * | | /UK(desc) | new idx | share | new idx | new idx | error |
7913  * | i | /R-UK: | | | | | |
7914  * | n +-----------+----------+-----------+---------+----------+-----------+
7915  * | d | FK: | new idx | new idx | share | share | share |
7916  * | e +-----------+----------+-----------+---------+----------+-----------+
7917  * | x | idx(asc): | error | new idx | share | error | new idx |
7918  * | +-----------+----------+-----------+---------+----------+-----------+
7919  * | | idx(desc) | new idx | error | new idx | new idx | error |
7920  * | | /R-idx: | | | | | |
7921  * +---+-----------+----------+-----------+---------+----------+-----------+
7922  */
7925  const SM_PREDICATE_INFO * filter_predicate,
7926  const SM_FUNCTION_INFO * func_index_info, const SM_CLASS_CONSTRAINT * existing_con,
7927  SM_CLASS_CONSTRAINT ** primary_con)
7928 {
7930 
7931  /* only one primary key is allowed in a table. */
7932  if (constraint_type == DB_CONSTRAINT_PRIMARY_KEY)
7933  {
7934  SM_CLASS_CONSTRAINT *prim_con;
7935  prim_con = classobj_find_cons_primary_key (constraints);
7936  if (prim_con != NULL)
7937  {
7938  *primary_con = prim_con;
7940  }
7941  }
7942 
7943  if (existing_con == NULL)
7944  {
7945  return SM_CREATE_NEW_INDEX;
7946  }
7947 
7948  assert (existing_con != NULL);
7949  if (DB_IS_CONSTRAINT_UNIQUE_FAMILY (constraint_type) && SM_IS_CONSTRAINT_UNIQUE_FAMILY (existing_con->type))
7950  {
7951  ret = SM_SHARE_INDEX;
7952  goto check_filter_function;
7953  }
7954 
7955  if (constraint_type == DB_CONSTRAINT_FOREIGN_KEY)
7956  {
7957  if (SM_IS_CONSTRAINT_UNIQUE_FAMILY (existing_con->type))
7958  {
7959  ret = SM_CREATE_NEW_INDEX;
7960  return ret;
7961  }
7962  else if (SM_IS_SHARE_WITH_FOREIGN_KEY (existing_con->type))
7963  {
7964  ret = SM_SHARE_INDEX;
7965  if (existing_con->filter_predicate != NULL || existing_con->func_index_info != NULL)
7966  {
7967  ret = SM_CREATE_NEW_INDEX;
7968  }
7969  return ret;
7970  }
7971  }
7972 
7973  if (constraint_type == DB_CONSTRAINT_INDEX && existing_con->type == SM_CONSTRAINT_FOREIGN_KEY)
7974  {
7975  ret = SM_SHARE_INDEX;
7976  if (filter_predicate != NULL || func_index_info != NULL)
7977  {
7978  ret = SM_CREATE_NEW_INDEX;
7979  }
7980  return ret;
7981  }
7982 
7984 
7985 check_filter_function:
7986  if (func_index_info && existing_con->func_index_info)
7987  {
7988  /* expr_str are printed tree, identifiers are already lower case */
7989  if (!strcmp (func_index_info->expr_str, existing_con->func_index_info->expr_str)
7990  && (func_index_info->attr_index_start == existing_con->func_index_info->attr_index_start)
7991  && (func_index_info->col_id == existing_con->func_index_info->col_id)
7992  && (func_index_info->fi_domain->is_desc == existing_con->func_index_info->fi_domain->is_desc))
7993  {
7994  return ret;
7995  }
7996  else
7997  {
7998  return SM_CREATE_NEW_INDEX;
7999  }
8000  }
8001  if ((func_index_info != NULL) && (existing_con->func_index_info == NULL))
8002  {
8003  return SM_CREATE_NEW_INDEX;
8004  }
8005  if ((func_index_info == NULL) && (existing_con->func_index_info != NULL))
8006  {
8007  return SM_CREATE_NEW_INDEX;
8008  }
8009  return ret;
8010 }
8011 
8012 /*
8013  * classobj_check_index_exist() - Check index is duplicated.
8014  * return: NO_ERROR on success, non-zero for ERROR
8015  * constraint(in): the constraints list
8016  * out_shared_cons_name(out):
8017  * constraint_type: constraint type
8018  * constraint_name(in): Constraint name.
8019  * att_names(in): array of attribute names
8020  * asc_desc(in): asc/desc info list
8021  * filter_index(in): expression from CREATE INDEX idx
8022  * ON tbl(col1, ...) WHERE filter_predicate
8023  * func_index_info (in): function index information
8024  */
8025 int
8026 classobj_check_index_exist (SM_CLASS_CONSTRAINT * constraints, char **out_shared_cons_name, const char *class_name,
8027  DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **att_names,
8028  const int *asc_desc, const SM_PREDICATE_INFO * filter_index,
8029  const SM_FUNCTION_INFO * func_index_info)
8030 {
8031  int error = NO_ERROR;
8032  SM_CLASS_CONSTRAINT *existing_con, *prim_con = NULL;
8033  SM_CONSTRAINT_COMPATIBILITY compat_state;
8034 
8035  if (constraints == NULL)
8036  {
8037  return NO_ERROR;
8038  }
8039 
8040  /* check index name uniqueness */
8041  existing_con = classobj_find_constraint_by_name (constraints, constraint_name);
8042  if (existing_con)
8043  {
8044  ERROR2 (error, ER_SM_INDEX_EXISTS, class_name, existing_con->name);
8045  return error;
8046  }
8047 
8048  existing_con = classobj_find_constraint_by_attrs (constraints, constraint_type, att_names, asc_desc);
8049 #if defined (ENABLE_UNUSED_FUNCTION) /* to disable TEXT */
8050  if (existing_con != NULL)
8051  {
8052  if (existing_con->name && strstr (existing_con->name, TEXT_CONSTRAINT_PREFIX))
8053  {
8055  return error;
8056  }
8057  }
8058 #endif /* ENABLE_UNUSED_FUNCTION */
8059 
8060  compat_state = classobj_check_index_compatibility (constraints, constraint_type, filter_index, func_index_info,
8061  existing_con, &prim_con);
8062  switch (compat_state)
8063  {
8064  case SM_CREATE_NEW_INDEX:
8065  break;
8066 
8067  case SM_SHARE_INDEX:
8068  if (out_shared_cons_name != NULL)
8069  {
8070  *out_shared_cons_name = strdup (existing_con->name);
8071  }
8072  break;
8073 
8075  ERROR2 (error, ER_SM_INDEX_EXISTS, class_name, existing_con->name);
8076  break;
8077 
8079  assert (prim_con != NULL);
8080  ERROR2 (error, ER_SM_PRIMARY_KEY_EXISTS, class_name, prim_con->name);
8081  break;
8082 
8083  default:
8084  /* not suppose to here */
8085  assert (false);
8086  }
8087 
8088  return error;
8089 }
8090 
8091 /*
8092  * classobj_make_function_index_info() -
8093  * return:
8094  * func_seq(in):
8095  */
8096 static SM_FUNCTION_INFO *
8098 {
8099  SM_FUNCTION_INFO *fi_info = NULL;
8100  DB_VALUE val;
8101  const char *buffer;
8102  char *ptr;
8103  int size;
8104 
8105  if (func_seq == NULL)
8106  {
8107  return NULL;
8108  }
8109 
8110  fi_info = (SM_FUNCTION_INFO *) db_ws_alloc (sizeof (SM_FUNCTION_INFO));
8111  if (fi_info == NULL)
8112  {
8114  goto error;
8115  }
8116  memset (fi_info, 0, sizeof (SM_FUNCTION_INFO));
8117 
8118  if (set_get_element_nocopy (func_seq, 0, &val) != NO_ERROR)
8119  {
8121  goto error;
8122  }
8123  buffer = db_get_string (&val);
8124  size = db_get_string_size (&val);
8125  fi_info->expr_str = (char *) db_ws_alloc (size + 1);
8126  if (fi_info->expr_str == NULL)
8127  {
8128  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) (size + 1));
8129  goto error;
8130  }
8131  memset (fi_info->expr_str, 0, size + 1);
8132  memcpy (fi_info->expr_str, buffer, size);
8133 
8134  if (set_get_element_nocopy (func_seq, 1, &val) != NO_ERROR)
8135  {
8137  goto error;
8138  }
8139  buffer = db_get_string (&val);
8140  fi_info->expr_stream_size = db_get_string_size (&val);
8141  fi_info->expr_stream = (char *) db_ws_alloc (fi_info->expr_stream_size);
8142  if (fi_info->expr_stream == NULL)
8143  {
8144  goto error;
8145  }
8146  memcpy (fi_info->expr_stream, buffer, fi_info->expr_stream_size);
8147 
8148  if (set_get_element_nocopy (func_seq, 2, &val) != NO_ERROR)
8149  {
8151  goto error;
8152  }
8153  fi_info->col_id = db_get_int (&val);
8154 
8155  if (set_get_element_nocopy (func_seq, 3, &val) != NO_ERROR)
8156  {
8158  goto error;
8159  }
8160  fi_info->attr_index_start = db_get_int (&val);
8161 
8162  if (set_get_element_nocopy (func_seq, 4, &val) != NO_ERROR)
8163  {
8165  goto error;
8166  }
8167  buffer = db_get_string (&val);
8168  // use const_cast since of a limitation of or_unpack_* functions which do not accept const
8169  ptr = CONST_CAST (char *, buffer);
8170  ptr = or_unpack_domain (ptr, &(fi_info->fi_domain), NULL);
8171 
8172  return fi_info;
8173 
8174 error:
8175 
8176  if (fi_info)
8177  {
8178  if (fi_info->expr_str)
8179  {
8180  db_ws_free (fi_info->expr_str);
8181  }
8182  if (fi_info->expr_stream)
8183  {
8184  db_ws_free (fi_info->expr_stream);
8185  }
8186  db_ws_free (fi_info);
8187  }
8188 
8189  return NULL;
8190 }
8191 
8192 /*
8193  * classobj_make_function_index_info_seq()
8194  * return:
8195  * func_index_info(in):
8196  */
8197 static DB_SEQ *
8199 {
8200  DB_SEQ *fi_seq;
8201  DB_VALUE val;
8202  int fi_domain_size;
8203  char *fi_domain_buf = NULL, *ptr = NULL;
8204 
8205  if (func_index_info == NULL)
8206  {
8207  return NULL;
8208  }
8209 
8210  fi_domain_size = or_packed_domain_size (func_index_info->fi_domain, 0);
8211  fi_domain_buf = (char *) malloc (fi_domain_size);
8212  if (fi_domain_buf == NULL)
8213  {
8214  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) fi_domain_size);
8215  return NULL;
8216  }
8217  ptr = fi_domain_buf;
8218  ptr = or_pack_domain (ptr, func_index_info->fi_domain, 0, 0);
8219 
8220  fi_seq = set_create_sequence (5);
8221 
8222  db_make_string (&val, func_index_info->expr_str);
8223  set_put_element (fi_seq, 0, &val);
8224 
8225  db_make_char (&val, func_index_info->expr_stream_size, func_index_info->expr_stream,
8227  set_put_element (fi_seq, 1, &val);
8228 
8229  db_make_int (&val, func_index_info->col_id);
8230  set_put_element (fi_seq, 2, &val);
8231 
8232  db_make_int (&val, func_index_info->attr_index_start);
8233  set_put_element (fi_seq, 3, &val);
8234 
8235  db_make_char (&val, fi_domain_size, fi_domain_buf, fi_domain_size, LANG_SYS_CODESET, LANG_SYS_COLLATION);
8236  set_put_element (fi_seq, 4, &val);
8237 
8238  free_and_init (fi_domain_buf);
8239 
8240  return fi_seq;
8241 }
8242 
8243 /*
8244  * classobj_free_function_index_ref()
8245  * return: none
8246  * func_index_info(in):
8247  */
8248 void
8250 {
8251  ws_free_string (func_index_info->expr_str);
8252  ws_free_string (func_index_info->expr_stream);
8253  tp_domain_free (func_index_info->fi_domain);
8254  func_index_info->expr_str = NULL;
8255  func_index_info->expr_stream = NULL;
8256 }
8257 
8258 /*
8259  * classobj_check_function_constraint_info() - check function constraint info
8260  * return: error code
8261  * constraint_seq(in): constraint sequence
8262  * has_function_constraint(in): true, if function constraint sequence
8263  */
8264 static int
8265 classobj_check_function_constraint_info (DB_SEQ * constraint_seq, bool * has_function_constraint)
8266 {
8267  DB_VALUE bvalue, fvalue, avalue;
8268  int constraint_seq_len = set_size (constraint_seq);
8269  int j = 0;
8270 
8271  assert (constraint_seq != NULL && has_function_constraint != NULL);
8272 
8273  /* initializations */
8274  *has_function_constraint = false;
8275  db_make_null (&bvalue);
8276  db_make_null (&avalue);
8277  db_make_null (&fvalue);
8278 
8279  if (set_get_element (constraint_seq, constraint_seq_len - 3, &bvalue) != NO_ERROR)
8280  {
8281  goto structure_error;
8282  }
8283 
8284  if (DB_VALUE_TYPE (&bvalue) == DB_TYPE_SEQUENCE)
8285  {
8286  DB_SEQ *seq = db_get_set (&bvalue);
8287  if (set_get_element (seq, 0, &fvalue) != NO_ERROR)
8288  {
8289  pr_clear_value (&bvalue);
8290  goto structure_error;
8291  }
8292  if (DB_VALUE_TYPE (&fvalue) == DB_TYPE_INTEGER)
8293  {
8294  /* don't care about prefix length */
8295  }
8296  else if (DB_VALUE_TYPE (&fvalue) == DB_TYPE_SEQUENCE)
8297  {
8298  DB_SET *child_seq = db_get_set (&fvalue);
8299  int seq_size = set_size (seq);
8300 
8301  j = 0;
8302  while (true)
8303  {
8304  if (set_get_element (child_seq, 0, &avalue) != NO_ERROR)
8305  {
8306  goto structure_error;
8307  }
8308 
8309  if (DB_IS_NULL (&avalue) || DB_VALUE_TYPE (&avalue) != DB_TYPE_STRING)
8310  {
8311  goto structure_error;
8312  }
8313 
8314  if (strcmp (db_get_string (&avalue), SM_FUNCTION_INDEX_ID) == 0)
8315  {
8316  *has_function_constraint = true;
8317  pr_clear_value (&avalue);
8318  break;
8319  }
8320 
8321  pr_clear_value (&avalue);
8322 
8323  j++;
8324  if (j >= seq_size)
8325  {
8326  break;
8327  }
8328 
8329  pr_clear_value (&fvalue);
8330  if (set_get_element (seq, j, &fvalue) != NO_ERROR)
8331  {
8332  goto structure_error;
8333  }
8334 
8335  if (DB_VALUE_TYPE (&fvalue) != DB_TYPE_SEQUENCE)
8336  {
8337  goto structure_error;
8338  }
8339 
8340  child_seq = db_get_set (&fvalue);
8341  }
8342  }
8343  else
8344  {
8345  goto structure_error;
8346  }
8347 
8348  pr_clear_value (&fvalue);
8349  pr_clear_value (&bvalue);
8350  }
8351  else
8352  {
8353  goto structure_error;
8354  }
8355 
8356  return NO_ERROR;
8357 
8358 structure_error:
8359 
8361 
8362  /* clean up our values and return the error that has been set */
8363  pr_clear_value (&fvalue);
8364  pr_clear_value (&avalue);
8365  pr_clear_value (&bvalue);
8366 
8367  assert (er_errid () != NO_ERROR);
8368  return er_errid ();
8369 }
8370 
8371 /* SM_PARTITION */
8372 /*
8373  * classobj_make_partition_info () - Allocate and initialize a sm_partition
8374  * structure.
8375  * return: new partition structure
8376  */
8377 
8378 SM_PARTITION *
8380 {
8381  SM_PARTITION *partition_info;
8382 
8383  partition_info = (SM_PARTITION *) db_ws_alloc (sizeof (SM_PARTITION));
8384 
8385  if (partition_info == NULL)
8386  {
8387  return NULL;
8388  }
8389 
8390  partition_info->partition_type = -1;
8391  partition_info->values = NULL;
8392  partition_info->pname = NULL;
8393  partition_info->comment = NULL;
8394  partition_info->expr = NULL;
8395  partition_info->next = NULL;
8396 
8397  return (partition_info);
8398 }
8399 
8400 /*
8401  * classobj_free_partition_info () - free a sm_partition structure.
8402  * return:
8403  * partition_info (in):
8404  */
8405 void
8407 {
8408  if (partition_info == NULL)
8409  {
8410  return;
8411  }
8412 
8413  if (partition_info->comment != NULL)
8414  {
8415  ws_free_string (partition_info->comment);
8416  }
8417  if (partition_info->pname != NULL)
8418  {
8419  ws_free_string (partition_info->pname);
8420  }
8421  if (partition_info->expr != NULL)
8422  {
8423  ws_free_string (partition_info->expr);
8424  }
8425  if (partition_info->values != NULL)
8426  {
8427  set_free (partition_info->values);
8428  }
8429  db_ws_free (partition_info);
8430 }
8431 
8432 /*
8433  * classobj_copy_partition_info () - Copy a SM_PARTITION structure.
8434  * return: new structure
8435  * partition_info(in):
8436  */
8437 
8438 SM_PARTITION *
8440 {
8441  SM_PARTITION *new_partition_info;
8442 
8443  new_partition_info = classobj_make_partition_info ();
8444  if (new_partition_info == NULL)
8445  {
8447  goto error;
8448  }
8449 
8450  new_partition_info->partition_type = partition_info->partition_type;
8451 
8452  if (partition_info->comment != NULL)
8453  {
8454  new_partition_info->comment = ws_copy_string (partition_info->comment);
8455  if (new_partition_info->comment == NULL)
8456  {
8457  goto error;
8458  }
8459  }
8460 
8461  if (partition_info->expr != NULL)
8462  {
8463  new_partition_info->expr = ws_copy_string (partition_info->expr);
8464  if (new_partition_info->expr == NULL)
8465  {
8466  goto error;
8467  }
8468  }
8469 
8470  if (partition_info->pname != NULL)
8471  {
8472  new_partition_info->pname = ws_copy_string (partition_info->pname);
8473  if (new_partition_info->pname == NULL)
8474  {
8475  goto error;
8476  }
8477  }
8478 
8479  if (partition_info->values != NULL)
8480  {
8481  new_partition_info->values = db_seq_copy (partition_info->values);
8482  if (new_partition_info->values == NULL)
8483  {
8484  goto error;
8485  }
8486  }
8487 
8488  return new_partition_info;
8489 
8490 error:
8491  classobj_free_partition_info (new_partition_info);
8492  return NULL;
8493 }
8494 
8495 /*
8496  * classobj_copy_default_expr() - Copies default expression.
8497  * return: error code
8498  *
8499  * dest(out): destination default expression
8500  * src(in): source default expression
8501  */
8502 int
8504 {
8505  assert (dest != NULL && src != NULL);
8506 
8507  dest->default_expr_type = src->default_expr_type;
8508  dest->default_expr_op = src->default_expr_op;
8509  if (src->default_expr_format)
8510  {
8512  if (dest->default_expr_format == NULL)
8513  {
8515  return ER_OUT_OF_VIRTUAL_MEMORY;
8516  }
8517  }
8518  else
8519  {
8520  dest->default_expr_format = NULL;
8521  }
8522 
8523  return NO_ERROR;
8524 }
8525 
8526 int
8528 {
8529  DB_VALUE prop_val, cnstr_val, curr_status, new_status;
8530  DB_SEQ *prop_seq, *idx_seq;
8531  const char *property_type;
8532  int found = 0;
8533  int error = NO_ERROR;
8534  int len = 0;
8535 
8536  assert (properties != NULL && cons != NULL);
8537 
8538  db_make_null (&prop_val);
8539  db_make_null (&cnstr_val);
8540  db_make_null (&curr_status);
8541  db_make_null (&new_status);
8542 
8543  property_type = classobj_map_constraint_to_property (cons->type);
8544 
8545  found = classobj_get_prop (properties, property_type, &prop_val);
8546  if (found == 0)
8547  {
8549  error = ER_SM_INVALID_PROPERTY;
8550  goto end;
8551  }
8552 
8553  prop_seq = db_get_set (&prop_val);
8554  found = classobj_get_prop (prop_seq, cons->name, &cnstr_val);
8555  if (found == 0)
8556  {
8558  error = ER_SM_INVALID_PROPERTY;
8559  goto end;
8560  }
8561 
8562  idx_seq = db_get_set (&cnstr_val);
8563  len = set_size (idx_seq);
8564 
8565  /* status stands at the len - 2 of the seq */
8566  set_get_element (idx_seq, len - 2, &curr_status);
8567  if (!DB_IS_NULL (&curr_status) && DB_VALUE_TYPE (&curr_status) != DB_TYPE_INTEGER)
8568  {
8570  error = ER_SM_INVALID_PROPERTY;
8571  goto end;
8572  }
8573 
8574  db_make_int (&new_status, index_status);
8575  error = set_put_element (idx_seq, len - 2, &new_status);
8576  if (error != NO_ERROR)
8577  {
8578  goto end;
8579  }
8580 
8581  db_make_sequence (&cnstr_val, idx_seq);
8582  found = classobj_put_prop (prop_seq, cons->name, &cnstr_val);
8583  if (found == 0)
8584  {
8586  error = ER_SM_INVALID_PROPERTY;
8587  goto end;
8588  }
8589 
8590  db_make_sequence (&prop_val, prop_seq);
8591  found = classobj_put_prop (properties, property_type, &prop_val);
8592  if (found == 0)
8593  {
8595  error = ER_SM_INVALID_PROPERTY;
8596  goto end;
8597  }
8598 
8599 end:
8600  pr_clear_value (&prop_val);
8601  pr_clear_value (&cnstr_val);
8602  pr_clear_value (&curr_status);
8603  pr_clear_value (&new_status);
8604  return error;
8605 }
struct tr_schema_cache * triggers
Definition: class_object.h:463
char * sm_produce_constraint_name_tmpl(SM_TEMPLATE *tmpl, DB_CONSTRAINT_TYPE constraint_type, const char **att_names, const int *asc_desc, const char *given_name)
SM_REPRESENTATION * classobj_find_representation(SM_CLASS *class_, int id)
const char * name
Definition: class_object.h:631
SM_ATTRIBUTE * shared
Definition: class_object.h:722
static SM_METHOD_SIGNATURE * classobj_copy_method_signature(SM_METHOD_SIGNATURE *sig)
WS_OBJECT_HEADER ch_obj_header
Definition: class_object.h:347
int tp_domain_disk_size(TP_DOMAIN *domain)
const char * expr
Definition: class_object.h:697
bool classobj_has_unique_constraint(SM_CONSTRAINT *constraints)
static DB_SEQ * classobj_make_function_index_info_seq(SM_FUNCTION_INFO *func_index_info)
#define NO_ERROR
Definition: error_code.h:46
const char ** classobj_point_at_att_names(SM_CLASS_CONSTRAINT *constraint, int *count_ref)
int set_get_element_nocopy(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2616
static int classobj_query_spec_size(SM_QUERY_SPEC *query_spec)
#define ws_free_string_and_init(str)
Definition: work_space.h:376
int db_value_put_null(DB_VALUE *value)
Definition: db_macro.c:122
static void classobj_free_constraint(SM_CONSTRAINT *constraint)
int set_drop_seq_element(DB_COLLECTION *set, int index)
Definition: set_object.c:2902
int class_method_count
Definition: class_object.h:732
DB_COLLECTION * db_get_set(const DB_VALUE *value)
int dbt_add_foreign_key(DB_CTMPL *def, const char *constraint_name, const char **attnames, const char *ref_class, const char **ref_attrs, int del_action, int upd_action, const char *comment)
Definition: db_temp.c:524
#define LANG_SYS_COLLATION
#define DB_IS_CONSTRAINT_UNIQUE_FAMILY(c)
Definition: dbtype_def.h:170
SM_CLASS * current
Definition: class_object.h:783
int fixed_count
Definition: class_object.h:737
#define classobj_free_prop_and_init(properties)
Definition: class_object.h:916
SM_CLASS * classobj_make_class(const char *name)
void classobj_free_query_spec(SM_QUERY_SPEC *query_spec)
SM_CLASS_CONSTRAINT * classobj_find_constraint_by_attrs(SM_CLASS_CONSTRAINT *cons_list, DB_CONSTRAINT_TYPE new_cons, const char **att_names, const int *asc_desc)
SM_FOREIGN_KEY_INFO * fk_info
Definition: class_object.h:537
void classobj_initialize_attributes(SM_ATTRIBUTE *attributes)
static int classobj_put_seq_and_iterate(DB_SEQ *destination, int &index, DB_SEQ *element)
Definition: class_object.c:880
void classobj_free_method(SM_METHOD *meth)
DB_OBJLIST * inheritance
Definition: class_object.h:718
TP_DOMAIN * classobj_find_cons_index2_col_type_list(SM_CLASS_CONSTRAINT *cons, OID *root_oid)
static SM_CONSTRAINT_COMPATIBILITY classobj_check_index_compatibility(SM_CLASS_CONSTRAINT *constraints, const DB_CONSTRAINT_TYPE constraint_type, const SM_PREDICATE_INFO *filter_predicate, const SM_FUNCTION_INFO *func_index_info, const SM_CLASS_CONSTRAINT *existing_con, SM_CLASS_CONSTRAINT **primary_con)
static SM_FOREIGN_KEY_INFO * classobj_make_foreign_key_info(DB_SEQ *fk_seq, const char *cons_name, SM_ATTRIBUTE *attributes)
int or_packed_value_size(const DB_VALUE *value, int collapse_null, int include_domain, int include_domain_classoids)
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
static SM_PREDICATE_INFO * classobj_make_index_filter_pred_info(DB_SEQ *pred_seq)
SM_COMPONENT header
Definition: class_object.h:591
SM_PREDICATE_INFO * filter_predicate
Definition: class_object.h:536
static int classobj_method_arg_size(SM_METHOD_ARGUMENT *arg)
void area_destroy(AREA *area)
Definition: area_alloc.c:247
int classobj_install_template(SM_CLASS *class_, SM_TEMPLATE *flat, int saverep)
int classobj_copy_attlist(SM_ATTRIBUTE *attlist, MOP filter_class, int ordered, SM_ATTRIBUTE **copy_ptr)
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
PAGEID FILEID
SM_ATTRIBUTE * classobj_find_attribute_list(SM_ATTRIBUTE *attlist, const char *name, int id)
DB_ATTRIBUTE * partition_parent_atts
Definition: class_object.h:813
#define TP_IS_SET_TYPE(typenum)
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
void classobj_free_foreign_key_ref(SM_FOREIGN_KEY_INFO *fk_info)
const char * name
Definition: class_object.h:616
int db_get_int(const DB_VALUE *value)
static void classobj_sort_methlist(SM_METHOD **source)
int tm_Tran_index
SM_METATYPE ch_type
Definition: class_object.h:349
void *(* LCOPIER)(void *)
Definition: work_space.h:561
int classobj_area_init(void)
Definition: class_object.c:167
DB_TYPE
Definition: dbtype_def.h:670
#define ER_FAILED
Definition: error_code.h:47
DB_OBJLIST * inheritance
Definition: class_object.h:788
unsigned triggers_validated
Definition: class_object.h:772
struct tp_domain TP_DOMAIN
SM_METHOD * class_methods
Definition: class_object.h:795
int shared_count
Definition: class_object.h:723
struct sm_constraint SM_CONSTRAINT
Definition: class_object.h:362
SM_CLASS_CONSTRAINT * classobj_find_class_primary_key(SM_CLASS *class_)
DB_COLLECTION * set_copy(DB_COLLECTION *set)
Definition: set_object.c:2473
int n_btstats
Definition: statistics.h:80
SM_CLASS_CONSTRAINT * classobj_find_cons_primary_key(SM_CLASS_CONSTRAINT *cons_list)
static int classobj_copy_attribute_like(DB_CTMPL *ctemplate, SM_ATTRIBUTE *attribute, const char *const like_class_name)
struct tp_domain * setdomain
Definition: object_domain.h:82
SM_CONSTRAINT_COMPATIBILITY
Definition: class_object.c:61
TP_DOMAIN * domain
Definition: class_object.h:444
struct sm_partition SM_PARTITION
Definition: class_object.h:689
#define SM_FILTER_INDEX_ID
void classobj_initialize_methods(SM_METHOD *methods)
int classobj_get_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
struct ws_object_header WS_OBJECT_HEADER
Definition: work_space.h:184
SM_CONSTRAINT_TYPE
Definition: class_object.h:274
CLASS_STATS * stats
Definition: class_object.h:747
int classobj_copy_default_expr(DB_DEFAULT_EXPR *dest, const DB_DEFAULT_EXPR *src)
SM_FOREIGN_KEY_ACTION
void * auth_cache
Definition: class_object.h:751
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
struct setobj * set
Definition: db_set.h:43
struct sm_representation SM_REPRESENTATION
Definition: class_object.h:663
SM_COMPONENT * classobj_find_component(SM_CLASS *class_, const char *name, int class_component)
SM_PARTITION * partition
Definition: class_object.h:760
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_class_size(SM_CLASS *class_)
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)
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
#define classobj_free_class_constraints_and_init(constraints)
Definition: class_object.h:924
void * triggers
Definition: class_object.h:811
void classobj_free_desclist(SM_DESCRIPTOR_LIST *dl)
INT16 VOLID
SM_NAME_SPACE
struct sm_attribute SM_ATTRIBUTE
Definition: class_object.h:398
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
struct sm_descriptor * next
Definition: class_object.h:896
static int classobj_put_seq_with_name_and_iterate(DB_SEQ *destination, int &index, const char *name, DB_SEQ *seq)
Definition: class_object.c:900
TP_DOMAIN * key_type
Definition: statistics.h:65
const char * source_name
Definition: class_object.h:619
OID * ws_oid(MOP mop)
Definition: work_space.c:2884
int classobj_oid_from_property_value(DB_VALUE *value, OID *oid)
static int classobj_constraint_size(SM_CONSTRAINT *constraint)
int fixed_size
Definition: class_object.h:739
#define SM_IS_CONSTRAINT_UNIQUE_FAMILY(c)
Definition: class_object.h:111
static int classobj_method_size(SM_METHOD *meth)
SM_CLASS_CONSTRAINT * classobj_find_constraint_by_name(SM_CLASS_CONSTRAINT *cons_list, const char *name)
static AREA * Template_area
Definition: class_object.c:94
struct sm_component * next
Definition: class_object.h:384
static DB_SEQ * classobj_make_index_attr_prefix_seq(int num_attrs, const int *attrs_prefix_length)
Definition: class_object.c:772
#define OID_SET_NULL(oidp)
Definition: oid.h:85
TP_DOMAIN * domain
Definition: class_object.h:559
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
SM_FUNCTION_INFO * func_index_info
Definition: class_object.h:541
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)
const char * pname
Definition: class_object.h:694
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)
bool classobj_class_has_indexes(SM_CLASS *class_)
struct sm_method_file SM_METHOD_FILE
Definition: class_object.h:611
INT32 root_pageid
SM_METHOD_ARGUMENT * value
Definition: class_object.h:575
struct sm_class_constraint * next
Definition: class_object.h:530
#define BTID_IS_EQUAL(b1, b2)
SM_NAME_SPACE name_space
Definition: class_object.h:386
int er_errid(void)
static int classobj_check_function_constraint_info(DB_SEQ *constraint_seq, bool *has_function_constraint)
const char * comment
Definition: class_object.h:698
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
const char * name
int or_packed_domain_size(struct tp_domain *domain, int include_classoids)
int classobj_drop_foreign_key_ref(DB_SEQ **properties, const BTID *btid, const char *name)
int collation_id
Definition: class_object.h:750
SM_METHOD_ARGUMENT * classobj_make_method_arg(int index)
static void classobj_filter_attribute_props(DB_SEQ *props)
struct sm_foreign_key_info * next
Definition: class_object.h:474
static DB_SEQ * classobj_make_foreign_key_ref_seq(SM_FOREIGN_KEY_INFO *fk_info)
Definition: class_object.c:706
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
#define mq_free_virtual_query_cache_and_init(virtual_query_cache)
Definition: parser.h:45
struct parser_context * virtual_query_cache
Definition: class_object.h:755
void classobj_area_final(void)
Definition: class_object.c:184
struct sm_partition * next
Definition: class_object.h:693
AREA * area_create(const char *name, size_t element_size, size_t alloc_count)
Definition: area_alloc.c:146
static int * classobj_make_index_prefix_info(DB_SEQ *prefix_seq, int num_attrs)
SM_FOREIGN_KEY_ACTION update_action
Definition: class_object.h:482
void ws_free_string(const char *str)
Definition: work_space.c:3480
struct sm_representation * next
Definition: class_object.h:667
SM_VALIDATION * valid
Definition: class_object.h:901
#define ER_FK_REF_CLASS_HAS_NOT_PK
Definition: error_code.h:1150
SM_METHOD * methods
Definition: class_object.h:791
SM_CLASS_CONSTRAINT * classobj_find_class_constraint_by_btid(SM_CLASS_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type, BTID btid)
#define NULL_PAGEID
const char * expanded_name
Definition: class_object.h:618
SM_DESCRIPTOR_LIST * map
Definition: class_object.h:900
SM_PARTITION * classobj_copy_partition_info(SM_PARTITION *partition_info)
const char * comment
Definition: class_object.h:542
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
static SM_REPRESENTATION * classobj_capture_representation(SM_CLASS *class_)
int classobj_copy_props(DB_SEQ *properties, MOP filter_class, DB_SEQ **new_properties)
Definition: class_object.c:549
int classobj_cache_class_constraints(SM_CLASS *class_)
static SM_METHOD_ARGUMENT * classobj_copy_method_arg(SM_METHOD_ARGUMENT *src)
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
int att_count
Definition: class_object.h:720
int class_attribute_count
Definition: class_object.h:724
static int classobj_representation_size(SM_REPRESENTATION *rep)
const char TEXT_CONSTRAINT_PREFIX[]
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
struct sm_method_signature SM_METHOD_SIGNATURE
Definition: class_object.h:564
static SM_FOREIGN_KEY_INFO * classobj_make_foreign_key_ref_list(DB_SEQ *fk_container)
static void classobj_clear_attribute(SM_ATTRIBUTE *att)
static int classobj_domain_size(TP_DOMAIN *domain)
int classobj_decompose_property_oid(const char *buffer, int *volid, int *fileid, int *pageid)
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,...)
int classobj_put_foreign_key_ref(DB_SEQ **properties, SM_FOREIGN_KEY_INFO *fk_info)
static SM_CLASS_CONSTRAINT * classobj_make_class_constraint(const char *name, SM_CONSTRAINT_TYPE type)
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)
const char * sm_ch_name(const MOBJ clobj)
struct tr_schema_cache * triggers
Definition: class_object.h:756
SM_METHOD_SIGNATURE * classobj_make_method_signature(const char *name)
#define assert(x)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:369
void classobj_free_descriptor(SM_DESCRIPTOR *desc)
DB_CONSTRAINT_TYPE
Definition: dbtype_def.h:452
int classobj_copy_methfiles(SM_METHOD_FILE *files, MOP filter_class, SM_METHOD_FILE **copy_ptr)
int classobj_change_constraint_comment(DB_SEQ *properties, SM_CLASS_CONSTRAINT *cons, const char *comment)
int32_t fileid
Definition: dbtype_def.h:886
SM_PARTITION * partition
Definition: class_object.h:814
SM_ATTRIBUTE * shared_attributes
Definition: class_object.h:803
static bool classobj_cache_constraint_list(DB_SEQ *seq, SM_CLASS *class_, SM_CONSTRAINT_TYPE constraint_type)
unsigned int virtual_cache_snapshot_version
Definition: class_object.h:765
unsigned recache_constraints
Definition: class_object.h:775
#define ER_SM_CANT_COPY_WITH_FEATURE
Definition: error_code.h:1251
unsigned int virtual_cache_local_schema_id
Definition: class_object.h:763
#define stats_free_statistics_and_init(stats)
Definition: statistics.h:47
SM_PARTITION * classobj_make_partition_info(void)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
void ws_list_free(DB_LIST *list, LFREEER function)
Definition: work_space.c:3945
#define ERROR1(error, code, arg1)
Definition: error_manager.h:56
DB_OBJECT * class_mop
Definition: class_object.h:903
void stats_free_statistics(CLASS_STATS *stats)
SM_DESCRIPTOR * classobj_make_descriptor(MOP class_mop, SM_CLASS *classobj, SM_COMPONENT *comp, int write_access)
SM_REPRESENTATION * representations
Definition: class_object.h:716
void(* LFREEER)(void *)
Definition: work_space.h:562
static const char * Constraint_properties[]
Definition: class_object.c:80
unsigned dont_decache_constraints_or_flush
Definition: class_object.h:774
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
struct sm_query_spec * next
Definition: class_object.h:683
static SM_CONSTRAINT_TYPE Constraint_types[]
Definition: class_object.c:71
static int classobj_copy_constraint_like(DB_CTMPL *ctemplate, SM_CLASS_CONSTRAINT *constraint, const char *const like_class_name)
void classobj_free_class(SM_CLASS *class_)
DB_OBJLIST * ext_references
Definition: class_object.h:805
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)
static SM_METHOD_FILE * classobj_copy_methfile(SM_METHOD_FILE *src)
DB_VALUE original_value
Definition: class_object.h:393
unsigned is_desc
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:725
static int classobj_resolution_size(SM_RESOLUTION *res)
void classobj_free_method_file(SM_METHOD_FILE *file)
DB_SEQ * db_seq_copy(DB_SEQ *source)
Definition: db_set.c:428
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)
SM_METHOD_FILE * method_files
Definition: class_object.h:727
int method_ids
Definition: class_object.h:742
struct sm_descriptor_list * next
Definition: class_object.h:866
int stats_get_statistics(OID *classoid, unsigned int timestamp, CLASS_STATS **stats_p)
Definition: statistics_cl.c:54
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
SM_TEMPLATE * new_
Definition: class_object.h:746
static int classobj_init_attribute(SM_ATTRIBUTE *src, SM_ATTRIBUTE *dest, int copy)
DB_SEQ * values
Definition: class_object.h:696
static DB_SEQ * classobj_make_index_filter_pred_seq(SM_PREDICATE_INFO *filter_index_info)
Definition: class_object.c:809
METHOD_FUNCTION function
Definition: class_object.h:594
#define HFID_SET_NULL(hfid)
static void classobj_insert_ordered_attribute(SM_ATTRIBUTE **attlist, SM_ATTRIBUTE *att)
#define tr_free_schema_cache_and_init(cache)
SM_ATTRIBUTE * instance_attributes
Definition: class_object.h:802
unsigned methods_loaded
Definition: class_object.h:769
#define NUM_CONSTRAINT_TYPES
Definition: class_object.c:89
static SM_FUNCTION_INFO * classobj_make_function_index_info(DB_SEQ *func_seq)
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
void classobj_free_attribute(SM_ATTRIBUTE *att)
const char * function_name
Definition: class_object.h:570
int classobj_get_cached_constraint(SM_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type, BTID *id)
VFID vfid
#define TP_DOMAIN_TYPE(dom)
TP_DOMAIN * fi_domain
Definition: class_object.h:502
static bool classobj_is_possible_constraint(SM_CONSTRAINT_TYPE existed, DB_CONSTRAINT_TYPE new_)
SM_REPR_ATTRIBUTE * classobj_make_repattribute(int attid, DB_TYPE type_id, TP_DOMAIN *domain)
#define NULL
Definition: freelistheap.h:34
static int classobj_init_method(SM_METHOD *src, SM_METHOD *dest, int copy)
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
DB_SEQ * properties
Definition: class_object.h:598
#define ER_REGU_NOT_IMPLEMENTED
Definition: error_code.h:194
static DB_SEQ * classobj_make_foreign_key_info_seq(SM_FOREIGN_KEY_INFO *fk_info)
Definition: class_object.c:667
struct sm_repr_attribute * next
Definition: class_object.h:648
#define DB_ATT_ALIGN(offset)
Definition: memory_alloc.h:93
SM_QUERY_SPEC * classobj_copy_query_spec_list(SM_QUERY_SPEC *query_spec)
VFID vfid
#define SM_PROPERTY_UNIQUE
struct pr_type * type
Definition: class_object.h:443
#define SM_IS_SHARE_WITH_FOREIGN_KEY(c)
Definition: class_object.h:129
#define BTID_SET_NULL(btid)
void setobj_free(COL *col)
Definition: set_object.c:4338
#define ws_list_free_and_init(list, function)
Definition: work_space.h:392
#define SM_IS_CONSTRAINT_INDEX_FAMILY(c)
Definition: class_object.h:117
#define err(fd,...)
Definition: porting.h:431
struct sm_resolution SM_RESOLUTION
Definition: class_object.h:636
SM_COMPONENT * classobj_complist_search(SM_COMPONENT *list, const char *name)
void classobj_remove_class_constraint_node(SM_CLASS_CONSTRAINT **constraints, SM_CLASS_CONSTRAINT *node)
void PRIM_SET_NULL(DB_VALUE *value)
static void classobj_print_props(DB_SEQ *properties)
Definition: class_object.c:459
const char * loader_commands
Definition: class_object.h:799
void classobj_free_threaded_array(DB_LIST *array, LFREEER clear)
Definition: class_object.c:248
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
int ml_ext_add(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4877
#define CONST_CAST(dest_type, expr)
Definition: porting.h:1060
#define NULL_FILEID
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
void ml_free(DB_OBJLIST *list)
Definition: work_space.c:4654
METHOD_FUNCTION function
Definition: class_object.h:571
static void classobj_sort_attlist(SM_ATTRIBUTE **source)
SM_ATTRIBUTE * class_attributes
Definition: class_object.h:794
const char * classobj_map_constraint_to_property(SM_CONSTRAINT_TYPE constraint)
Definition: class_object.c:502
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int pr_clear_value(DB_VALUE *value)
SM_ATTRIBUTE * classobj_find_attribute_id(SM_CLASS *class_, int id, int class_attribute)
unsigned post_load_cleanup
Definition: class_object.h:770
DB_SEQ * properties
Definition: class_object.h:457
void classobj_free_representation(SM_REPRESENTATION *rep)
SM_CONSTRAINT * constraints
Definition: class_object.h:454
struct sm_method SM_METHOD
Definition: class_object.h:587
static bool classobj_cache_constraint_entry(const char *name, DB_SEQ *constraint_seq, SM_CLASS *class_, SM_CONSTRAINT_TYPE constraint_type)
SM_METHOD * class_methods
Definition: class_object.h:733
#define max(a, b)
SM_QUERY_SPEC * query_spec
Definition: class_object.h:745
SM_RESOLUTION * resolutions
Definition: class_object.h:792
#define WS_LIST_NCONC(lst1, lst2)
Definition: work_space.h:583
static void classobj_clear_method(SM_METHOD *meth)
SM_CLASS_CONSTRAINT * constraints
Definition: class_object.h:757
void classobj_free_class_constraints(SM_CLASS_CONSTRAINT *constraints)
int set_put_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2719
static void error(const char *msg)
Definition: gencat.c:331
static int classobj_method_signature_size(SM_METHOD_SIGNATURE *sig)
int classobj_btid_from_property_value(DB_VALUE *value, BTID *btid, char **shared_cons_name)
SM_COMPONENT * comp
Definition: class_object.h:870
SM_NAME_SPACE name_space
Definition: class_object.h:904
SM_DESCRIPTOR_LIST * classobj_make_desclist(MOP classobj, SM_CLASS *class_, SM_COMPONENT *comp, int write_access)
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_)
SM_CLASS_CONSTRAINT * classobj_find_class_constraint(SM_CLASS_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type, const char *name)
struct sm_method_signature * next
Definition: class_object.h:568
SM_REPR_ATTRIBUTE * attributes
Definition: class_object.h:669
SM_CLASS_HEADER header
Definition: class_object.h:710
SM_CLASS_CONSTRAINT * classobj_find_class_index(SM_CLASS *class_, const char *name)
SM_TEMPLATE * classobj_make_template_like(const char *name, SM_CLASS *class_)
const int SM_MAX_STRING_LENGTH
Definition: class_object.c:69
DB_OBJLIST * ml_copy(DB_OBJLIST *list)
Definition: work_space.c:4671
const char * sql_definition
Definition: class_object.h:573
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define classobj_free_threaded_array_and_init(list, clear)
Definition: class_object.h:908
DB_OBJLIST * validated_classes
Definition: class_object.h:880
SM_METHOD_FILE * method_files
Definition: class_object.h:798
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
#define SM_PROPERTY_INDEX
int dbt_add_constraint(DB_CTMPL *def, DB_CONSTRAINT_TYPE constraint_type, const char *constraint_name, const char **attnames, int class_attributes, const char *comment)
Definition: db_temp.c:423
const char * default_expr_format
Definition: dbtype_def.h:1206
DB_OBJECT * last_class
Definition: class_object.h:879
#define SM_PROPERTY_PRIMARY_KEY
int classobj_populate_class_properties(DB_SET **properties, SM_CLASS_CONSTRAINT *constraints, SM_CONSTRAINT_TYPE type)
const char * name
Definition: class_object.h:787
SM_FOREIGN_KEY_ACTION delete_action
Definition: class_object.h:481
BTREE_STATS * bt_stats
Definition: statistics.h:81
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)
static int classobj_cache_not_null_constraints(const char *class_name, SM_ATTRIBUTE *attributes, SM_CLASS_CONSTRAINT **con_ptr)
SM_METHOD_FILE * classobj_make_method_file(const char *name)
unsigned has_active_triggers
Definition: class_object.h:773
void classobj_free_partition_info(SM_PARTITION *partition_info)
int method_count
Definition: class_object.h:731
struct sm_class SM_CLASS
Definition: class_object.h:701
INT16 PGSLOTID
static int classobj_partition_info_size(SM_PARTITION *partition_info)
void classobj_decache_class_constraints(SM_CLASS *class_)
SM_METHOD * classobj_copy_method(SM_METHOD *src, const char *alias)
DB_DOMAIN * last_setdomain
Definition: class_object.h:882
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
struct sm_repr_attribute SM_REPR_ATTRIBUTE
Definition: class_object.h:644
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 ERROR2(error, code, arg1, arg2)
Definition: error_manager.h:64
void help_print_describe_comment(print_output &output_ctx, const char *comment)
Definition: object_print.c:716
static void classobj_clear_attribute_value(DB_VALUE *value)
bool classobj_has_class_unique_constraint(SM_CLASS_CONSTRAINT *constraints)
char * or_pack_domain(char *ptr, struct tp_domain *domain, int include_classoids, int is_null)
const char * ch_name
Definition: class_object.h:350
SM_COMPONENT * classobj_filter_components(SM_COMPONENT **complist, SM_NAME_SPACE name_space)
SM_RESOLUTION * classobj_make_resolution(MOP class_mop, const char *name, const char *alias, SM_NAME_SPACE name_space)
void classobj_free_prop(DB_SEQ *properties)
Definition: class_object.c:292
void set_print(DB_COLLECTION *set)
Definition: set_object.c:3731
void ml_ext_free(DB_OBJLIST *list)
Definition: work_space.c:4806
void * area_alloc(AREA *area)
Definition: area_alloc.c:360
SM_TEMPLATE * smt_def_class(const char *name)
static SM_CONSTRAINT * classobj_make_constraint(const char *name, SM_CONSTRAINT_TYPE type, BTID *id, bool has_function_constraint)
SM_ATTRIBUTE ** attributes
Definition: class_object.h:533
SM_CLASS_TYPE class_type
Definition: class_object.h:784
SM_CLASS_TYPE class_type
Definition: class_object.h:713
int db_get_string_size(const DB_VALUE *value)
void classobj_free_function_index_ref(SM_FUNCTION_INFO *func_index_info)
static int classobj_repattribute_size(void)
void * db_ws_alloc(size_t size)
Definition: quick_fit.c:73
SM_METHOD_ARGUMENT * args
Definition: class_object.h:577
int pr_value_mem_size(const DB_VALUE *value)
int area_free(AREA *area, void *ptr)
Definition: area_alloc.c:514
#define au_free_authorization_cache_and_init(cache)
Definition: authenticate.h:148
#define is_global(M)
SM_CONSTRAINT_TYPE type
Definition: class_object.h:540
const char * specification
Definition: class_object.h:685
unsigned int virtual_cache_global_schema_id
Definition: class_object.h:764
int classobj_copy_reslist(SM_RESOLUTION *src, SM_NAME_SPACE resspace, SM_RESOLUTION **copy_ptr)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
DB_OBJLIST * users
Definition: class_object.h:712
int i
Definition: dynamic_load.c:954
TR_SCHEMA_CACHE * tr_copy_schema_cache(TR_SCHEMA_CACHE *cache, MOP filter_class)
int db_make_null(DB_VALUE *value)
#define SM_FUNCTION_INDEX_ID
#define SM_PROPERTY_FOREIGN_KEY
#define DB_IS_NULL(value)
Definition: dbtype.h:63
bool classobj_has_function_constraint(SM_CONSTRAINT *constraints)
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
#define ER_SM_INVALID_CONSTRAINT
Definition: error_code.h:871
const char * name
Definition: class_object.h:385
char * strdup(const char *str)
Definition: porting.c:901
static void classobj_free_repattribute(SM_REPR_ATTRIBUTE *rat)
#define NULL_VOLID
SM_INDEX_STATUS index_status
Definition: class_object.h:544
DB_SEQ * classobj_make_prop()
Definition: class_object.c:280
struct sm_attribute * order_link
Definition: class_object.h:461
#define ER_SM_INDEX_EXISTS
Definition: error_code.h:344
int ws_list_length(DB_LIST *list)
Definition: work_space.c:3925
#define BTID_IS_NULL(btid)
static void classobj_put_value_and_iterate(DB_SEQ *destination, int &index, DB_VALUE &value)
Definition: class_object.c:870
int db_make_int(DB_VALUE *value, const int num)
int object_size
Definition: class_object.h:719
short volid
Definition: dbtype_def.h:887
DB_TYPE last_type
Definition: class_object.h:884
bool classobj_is_exist_foreign_key_ref(MOP refop, SM_FOREIGN_KEY_INFO *fk_info)
int db_make_char(DB_VALUE *value, const int char_length, DB_CONST_C_CHAR str, const int char_str_byte_size, const int codeset, const int collation_id)
#define db_ws_free_and_init(obj)
Definition: quick_fit.h:30
INT32 PAGEID
#define OID_ISNULL(oidp)
Definition: oid.h:81
#define SM_PREFIX_INDEX_ID
static SM_FOREIGN_KEY_INFO * classobj_make_foreign_key_ref(DB_SEQ *fk_seq)
int ml_size(DB_OBJLIST *list)
Definition: work_space.c:4711
#define LANG_SYS_CODESET
SM_CONSTRAINT_EXTRA_FLAG extra_status
Definition: class_object.h:543
#define SM_PROPERTY_REVERSE_INDEX
void tr_free_schema_cache(TR_SCHEMA_CACHE *cache)
static int classobj_attribute_size(SM_ATTRIBUTE *att)
char * ws_copy_string(const char *str)
Definition: work_space.c:3457
SM_RESOLUTION * class_resolutions
Definition: class_object.h:796
TP_DOMAIN * domain
Definition: class_object.h:652
struct sm_resolution * next
Definition: class_object.h:628
DB_LIST * ws_list_copy(DB_LIST *src, LCOPIER copier, LFREEER freeer)
Definition: work_space.c:3985
struct sm_constraint * next
Definition: class_object.h:366
SM_ATTRIBUTE * ordered_attributes
Definition: class_object.h:753
struct sm_method_argument SM_METHOD_ARGUMENT
Definition: class_object.h:552
#define OBJ_BOUND_BIT_BYTES
bool classobj_cache_constraints(SM_CLASS *class_)
char * or_unpack_domain(char *ptr, struct tp_domain **domain_ptr, int *is_null)
const char * comment
Definition: class_object.h:758
int * super_id_map
Definition: class_object.h:809
#define SM_PROPERTY_REVERSE_UNIQUE
DB_LIST * classobj_alloc_threaded_array(int size, int count)
Definition: class_object.c:211
void classobj_free_method_signature(SM_METHOD_SIGNATURE *sig)
static int classobj_method_file_size(SM_METHOD_FILE *file)
struct db_list * next
Definition: dbtype_def.h:417
SM_METHOD * methods
Definition: class_object.h:730
#define SM_PROPERTY_NOT_NULL
int ws_list_total(DB_LIST *list, LTOTALER function)
Definition: work_space.c:3964
static void classobj_free_method_arg(SM_METHOD_ARGUMENT *arg)
int(* LTOTALER)(void *)
Definition: work_space.h:563
SM_INDEX_STATUS
Definition: class_object.h:510
SM_ATTRIBUTE * classobj_copy_attribute(SM_ATTRIBUTE *src, const char *alias)
void classobj_fixup_loaded_class(SM_CLASS *class_)
SM_ATTRIBUTE * attributes
Definition: class_object.h:790
SM_REPRESENTATION * classobj_make_representation()
static int classobj_copy_methlist(SM_METHOD *methlist, MOP filter_class, SM_METHOD **copy_ptr)
char * classobj_describe_foreign_key_action(SM_FOREIGN_KEY_ACTION action)
Definition: class_object.c:748
const char * comment
Definition: class_object.h:467
ATTR_STATS * attr_stats
Definition: statistics.h:92
int au_fetch_class_force(MOP op, SM_CLASS **class_, AU_FETCHMODE fetchmode)
struct sm_method_file * next
Definition: class_object.h:615
const char ** p
Definition: dynamic_load.c:945
void tp_domain_free(TP_DOMAIN *dom)
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
const char * loader_commands
Definition: class_object.h:728
#define ml_free_and_init(list)
Definition: work_space.h:384
SM_METHOD_ARGUMENT * classobj_find_method_arg(SM_METHOD_ARGUMENT **arglist, int index, int create)
struct sm_method_argument * next
Definition: class_object.h:556
SM_RESOLUTION * classobj_find_resolution(SM_RESOLUTION *reslist, MOP class_mop, const char *name, SM_NAME_SPACE name_space)
const char * rel_major_release_string(void)
int classobj_drop_prop(DB_SEQ *properties, const char *name)
Definition: class_object.c:394
#define ER_SM_PRIMARY_KEY_EXISTS
Definition: error_code.h:1112
int tde_algorithm
Definition: class_object.h:767
int tp_domain_memory_size(TP_DOMAIN *domain)
const char * name
Definition: class_object.h:532
static META_ATTRIBUTE class_atts[]
Definition: transform.c:181
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
struct sm_query_spec SM_QUERY_SPEC
Definition: class_object.h:679
void clear(cub_regex_object *&regex, char *&pattern)
SM_METHOD * classobj_find_method(SM_CLASS *class_, const char *name, int class_method)
int variable_count
Definition: class_object.h:738
#define ER_SM_INVALID_PROPERTY
Definition: error_code.h:368
VOLID boot_User_volid
Definition: boot_cl.c:153
unsigned int flags
Definition: class_object.h:762