CUBRID Engine  latest
object_representation_sr.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  * object_representation_sr.c - Class representation parsing for the server only
21  * This is used for updating the catalog manager when class objects are
22  * flushed to the server.
23  */
24 
25 #ident "$Id$"
26 
28 
29 #include "btree_load.h"
30 #include "config.h"
31 #include "dbtype.h"
32 #include "error_manager.h"
33 #include "object_primitive.h"
34 #include "object_representation.h"
35 #include "set_object.h"
36 
37 #include <assert.h>
38 #include <new>
39 #include <stdio.h>
40 #include <string.h>
41 
42 #define DATA_INIT(data, type) memset(data, 0, sizeof(DB_DATA))
43 #define OR_ARRAY_EXTENT 10
44 
45 /*
46  * VARIABLE OFFSET TABLE ACCESSORS
47  * The variable offset table is present in the headers of objects and sets.
48  */
49 
50 #define OR_VAR_TABLE_ELEMENT_OFFSET(table, index) \
51  OR_VAR_TABLE_ELEMENT_OFFSET_INTERNAL(table, index, \
52  BIG_VAR_OFFSET_SIZE)
53 
54 #define OR_VAR_TABLE_ELEMENT_LENGTH(table, index) \
55  OR_VAR_TABLE_ELEMENT_LENGTH_INTERNAL(table, index, \
56  BIG_VAR_OFFSET_SIZE)
57 
60 {
61  const char *name;
64  int length;
65 };
66 
67 /* move the data inside the record */
68 #define HEAP_MOVE_INSIDE_RECORD(rec, dest_offset, src_offset) \
69  do \
70  { \
71  assert ((rec) != NULL && (dest_offset) >= 0 && (src_offset) >= 0); \
72  assert (((rec)->length - (src_offset)) >= 0); \
73  assert (((rec)->area_size <= 0) || ((rec)->area_size >= (rec)->length)); \
74  assert (((rec)->area_size <= 0) \
75  || (((rec)->length + ((dest_offset) - (src_offset))) \
76  <= (rec)->area_size)); \
77  if ((dest_offset) != (src_offset)) \
78  { \
79  memmove ((rec)->data + (dest_offset), (rec)->data + (src_offset), \
80  (rec)->length - (src_offset)); \
81  (rec)->length = (rec)->length + ((dest_offset) - (src_offset)); \
82  } \
83  } \
84  while (0)
85 
86 static int or_get_hierarchy_helper (THREAD_ENTRY * thread_p, OID * source_class, OID * class_, BTID * btid,
87  OID ** class_oids, HFID ** hfids, int *num_classes, int *max_classes,
88  int *partition_local_index);
89 static TP_DOMAIN *or_get_domain_internal (char *ptr);
90 static TP_DOMAIN *or_get_domain_and_cache (char *ptr);
91 static void or_get_att_index (char *ptr, BTID * btid);
92 static int or_get_default_value (OR_ATTRIBUTE * attr, char *ptr, int length);
93 static int or_get_current_default_value (OR_ATTRIBUTE * attr, char *ptr, int length);
94 static int or_cl_get_prop_nocopy (DB_SEQ * properties, const char *name, DB_VALUE * pvalue);
95 static void or_install_btids_foreign_key (const char *fkname, DB_SEQ * fk_seq, OR_INDEX * index);
96 static void or_install_btids_foreign_key_ref (DB_SEQ * fk_container, OR_INDEX * index);
97 static void or_install_btids_prefix_length (DB_SEQ * prefix_seq, OR_INDEX * index, int num_attrs);
98 static int or_install_btids_filter_pred (DB_SEQ * pred_seq, OR_INDEX * index);
99 static void or_install_btids_class (OR_CLASSREP * rep, BTID * id, DB_SEQ * constraint_seq, int seq_size,
100  BTREE_TYPE type, const char *cons_name);
101 static int or_install_btids_attribute (OR_CLASSREP * rep, int att_id, BTID * id);
102 static void or_install_btids_constraint (OR_CLASSREP * rep, DB_SEQ * constraint_seq, BTREE_TYPE type,
103  const char *cons_name);
104 static void or_install_btids_function_info (DB_SEQ * fi_seq, OR_INDEX * index);
105 static void or_install_btids (OR_CLASSREP * rep, DB_SEQ * props);
106 static OR_CLASSREP *or_get_current_representation (RECDES * record, int do_indexes);
107 static OR_CLASSREP *or_get_old_representation (RECDES * record, int repid, int do_indexes);
108 static const char *or_find_diskattr (RECDES * record, int attr_id);
109 static int or_get_attr_string (RECDES * record, int attr_id, int attr_index, char **string, int *alloced_string);
110 
111 static char or_mvcc_get_flag (RECDES * record);
112 static void or_mvcc_set_flag (RECDES * record, char flags);
113 static INLINE MVCCID or_mvcc_get_insid (OR_BUF * buf, int mvcc_flags, int *error) __attribute__ ((ALWAYS_INLINE));
115 static INLINE MVCCID or_mvcc_get_delid (OR_BUF * buf, int mvcc_flags, int *error) __attribute__ ((ALWAYS_INLINE));
116 static INLINE int or_mvcc_get_chn (OR_BUF * buf, int *error) __attribute__ ((ALWAYS_INLINE));
121 static INLINE int or_mvcc_get_prev_version_lsa (OR_BUF * buf, int mvcc_flags, LOG_LSA * prev_version_lsa)
123 
124 #if defined (ENABLE_UNUSED_FUNCTION)
125 /*
126  * orc_class_rep_dir () - Extracts the OID of representation
127  * directory record of a class
128  * return: void
129  * record(in): packed disk record containing class
130  * rep_dir_p(out): OID of representation directory record to be filled in
131  */
132 void
133 orc_class_rep_dir (RECDES * record, OID * rep_dir_p)
134 {
135  char *ptr;
136 
137  ptr = (char *) record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT) + ORC_REP_DIR_OFFSET;
138 
139  OR_GET_OID (ptr, rep_dir_p);
140 }
141 
142 /*
143  * orc_class_hfid_from_record () - Extracts just the HFID from the disk
144  * representation of a class
145  * return: void
146  * record(in): packed disk record containing class
147  * hfid(out): pointer to HFID structure to be filled in
148  *
149  * Note: It is used by the catalog manager to update the class information
150  * structure when the HFID is assigned. Since HFID's are assigned only
151  * when instances are created, a class may be entered into the catalog
152  * before the HFID is known.
153  */
154 void
155 orc_class_hfid_from_record (RECDES * record, HFID * hfid)
156 {
157  char *ptr;
158 
159  ptr = record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
161  hfid->vfid.volid = OR_GET_INT (ptr + ORC_HFID_VOLID_OFFSET);
162  hfid->hpgid = OR_GET_INT (ptr + ORC_HFID_PAGEID_OFFSET);
163 }
164 #endif
165 
166 /*
167  * orc_diskrep_from_record () - Calculate the corresponding DISK_REPR structure
168  * for the catalog
169  * return: disk representation structure
170  * record(in): disk record
171  */
172 DISK_REPR *
174 {
175  DISK_ATTR *att, *att_fixed, *att_variable;
176  OR_ATTRIBUTE *or_att;
177  int i, j, k, n_attributes, n_btstats;
178  BTREE_STATS *bt_statsp;
179 
180  DISK_REPR *rep = NULL;
181  OR_CLASSREP *or_rep = NULL;
182  OR_INDEX *or_idx = NULL;
183 
184  VPID root_vpid;
185  PAGE_PTR root;
186  BTREE_ROOT_HEADER *root_header = NULL;
188 
189  or_rep = or_get_classrep (record, NULL_REPRID);
190  if (or_rep == NULL)
191  {
192  goto error;
193  }
194 
195  rep = (DISK_REPR *) malloc (sizeof (DISK_REPR));
196  if (rep == NULL)
197  {
199  goto error;
200  }
201 
202  rep->id = or_rep->id;
203  rep->n_fixed = 0;
204  rep->n_variable = 0;
205  rep->fixed_length = or_rep->fixed_length;
206 #if 0 /* reserved for future use */
207  rep->repr_reserved_1 = 0;
208 #endif
209  rep->fixed = NULL;
210  rep->variable = NULL;
211 
212  /* Calculate the number of fixed and variable length attributes */
213  n_attributes = or_rep->n_attributes;
214  or_att = or_rep->attributes;
215  for (i = 0; i < n_attributes; i++, or_att++)
216  {
217  if (or_att->is_fixed)
218  {
219  (rep->n_fixed)++;
220  }
221  else
222  {
223  (rep->n_variable)++;
224  }
225  }
226 
227  if (rep->n_fixed)
228  {
229  rep->fixed = (DISK_ATTR *) malloc (sizeof (DISK_ATTR) * rep->n_fixed);
230  if (rep->fixed == NULL)
231  {
233  goto error;
234  }
235  memset (rep->fixed, 0x0, sizeof (DISK_ATTR) * rep->n_fixed);
236  }
237 
238  if (rep->n_variable)
239  {
240  rep->variable = (DISK_ATTR *) malloc (sizeof (DISK_ATTR) * rep->n_variable);
241  if (rep->variable == NULL)
242  {
244  goto error;
245  }
246  memset (rep->variable, 0x0, sizeof (DISK_ATTR) * rep->n_variable);
247  }
248 
249  /* Copy the attribute information */
250  att_fixed = rep->fixed;
251  att_variable = rep->variable;
252  or_att = or_rep->attributes;
253 
254  for (i = 0; i < n_attributes; i++, or_att++)
255  {
256  if (or_att->is_fixed)
257  {
258  att = att_fixed;
259  att_fixed++;
260  }
261  else
262  {
263  att = att_variable;
264  att_variable++;
265  }
266 
267  if (att == NULL)
268  {
269  goto error;
270  }
271 
272  att->type = or_att->type;
273  att->id = or_att->id;
274  att->location = or_att->location;
275  att->position = or_att->position;
276  att->val_length = or_att->default_value.val_length;
277  att->value = or_att->default_value.value;
278  or_att->default_value.value = NULL;
279  att->classoid = or_att->classoid;
280 
281  /* initialize B+tree statistics information */
282 
283  n_btstats = att->n_btstats = or_att->n_btids;
284  if (n_btstats > 0)
285  {
286  att->bt_stats = (BTREE_STATS *) malloc (sizeof (BTREE_STATS) * n_btstats);
287  if (att->bt_stats == NULL)
288  {
290  goto error;
291  }
292  memset (att->bt_stats, 0, sizeof (BTREE_STATS) * n_btstats);
293 
294  for (j = 0, bt_statsp = att->bt_stats; j < n_btstats; j++, bt_statsp++)
295  {
296  bt_statsp->btid = or_att->btids[j];
297 
298  bt_statsp->leafs = 0;
299  bt_statsp->pages = 0;
300  bt_statsp->height = 0;
301  bt_statsp->keys = 0;
302  bt_statsp->has_function = 0;
303  for (k = 0; k < or_rep->n_indexes; k++)
304  {
305  or_idx = &or_rep->indexes[k];
306  if (or_idx && BTID_IS_EQUAL (&or_idx->btid, &bt_statsp->btid) && or_idx->func_index_info
307  && or_idx->func_index_info->col_id == 0)
308  {
309  bt_statsp->has_function = 1;
310  break;
311  }
312  }
313 
314  bt_statsp->key_type = NULL;
315  bt_statsp->pkeys_size = 0;
316  bt_statsp->pkeys = NULL;
317 
318 #if 0 /* reserved for future use */
319  for (k = 0; k < BTREE_STATS_RESERVED_NUM; k++)
320  {
321  bt_statsp->reserved[k] = 0;
322  }
323 #endif
324 
325  /* read B+tree Root page header info */
326  root_vpid.pageid = bt_statsp->btid.root_pageid;
327  root_vpid.volid = bt_statsp->btid.vfid.volid;
328 
329  if (VPID_ISNULL (&root_vpid))
330  {
331  /* after create the catalog record of the class, and before create the catalog record of the
332  * constraints for the class currently, does not know BTID */
333  continue;
334  }
335 
336  root = pgbuf_fix (thread_p, &root_vpid, OLD_PAGE, PGBUF_LATCH_READ, PGBUF_UNCONDITIONAL_LATCH);
337  if (root == NULL)
338  {
339  goto error;
340  }
341 
342  (void) pgbuf_check_page_ptype (thread_p, root, PAGE_BTREE);
343 
344  root_header = btree_get_root_header (thread_p, root);
345  if (root_header == NULL)
346  {
347  pgbuf_unfix_and_init (thread_p, root);
348  goto error;
349  }
350 
351  /* construct BTID_INT structure */
352  btid_int.sys_btid = &bt_statsp->btid;
353  if (btree_glean_root_header_info (thread_p, root_header, &btid_int) != NO_ERROR)
354  {
355  pgbuf_unfix_and_init (thread_p, root);
356  goto error;
357  }
358 
359  pgbuf_unfix_and_init (thread_p, root);
360 
361  bt_statsp->key_type = btid_int.key_type;
362  if (TP_DOMAIN_TYPE (bt_statsp->key_type) == DB_TYPE_MIDXKEY)
363  {
364  bt_statsp->pkeys_size = tp_domain_size (bt_statsp->key_type->setdomain);
365  }
366  else
367  {
368  bt_statsp->pkeys_size = 1;
369  }
370 
371  /* cut-off to stats */
372  if (bt_statsp->pkeys_size > BTREE_STATS_PKEYS_NUM)
373  {
374  bt_statsp->pkeys_size = BTREE_STATS_PKEYS_NUM;
375  }
376 
377  bt_statsp->pkeys = (int *) malloc (bt_statsp->pkeys_size * sizeof (int));
378  if (bt_statsp->pkeys == NULL)
379  {
380  bt_statsp->pkeys_size = 0;
382  bt_statsp->pkeys_size * sizeof (int));
383  goto error;
384  }
385 
386  assert (bt_statsp->pkeys_size <= BTREE_STATS_PKEYS_NUM);
387  for (k = 0; k < bt_statsp->pkeys_size; k++)
388  {
389  bt_statsp->pkeys[k] = 0;
390  }
391  } /* for (j = 0, ...) */
392  }
393  else
394  {
395  att->bt_stats = NULL;
396  }
397  }
398 
399  or_free_classrep (or_rep);
400  return (rep);
401 
402 error:
403  if (rep != NULL)
404  {
405  orc_free_diskrep (rep);
406  }
407 
408  if (or_rep != NULL)
409  {
410  or_free_classrep (or_rep);
411  }
412 
413  return (NULL);
414 }
415 
416 /*
417  * orc_free_diskrep () - Frees a DISK_REPR structure that was built with
418  * orc_diskrep_from_record
419  * return: void
420  * rep(in): representation structure
421  */
422 void
424 {
425  int i, j;
426 
427  if (rep != NULL)
428  {
429  if (rep->fixed != NULL)
430  {
431  for (i = 0; i < rep->n_fixed; i++)
432  {
433  if (rep->fixed[i].value != NULL)
434  {
435  free_and_init (rep->fixed[i].value);
436  }
437 
438  if (rep->fixed[i].bt_stats != NULL)
439  {
440  for (j = 0; j < rep->fixed[i].n_btstats; j++)
441  {
442  if (rep->fixed[i].bt_stats[j].pkeys)
443  {
444  free_and_init (rep->fixed[i].bt_stats[j].pkeys);
445  }
446  }
447 
448  free_and_init (rep->fixed[i].bt_stats);
449  rep->fixed[i].bt_stats = NULL;
450  }
451  }
452 
453  free_and_init (rep->fixed);
454  }
455 
456  if (rep->variable != NULL)
457  {
458  for (i = 0; i < rep->n_variable; i++)
459  {
460  if (rep->variable[i].value != NULL)
461  {
462  free_and_init (rep->variable[i].value);
463  }
464 
465  if (rep->variable[i].bt_stats != NULL)
466  {
467  for (j = 0; j < rep->variable[i].n_btstats; j++)
468  {
469  if (rep->variable[i].bt_stats[j].pkeys)
470  {
471  free_and_init (rep->variable[i].bt_stats[j].pkeys);
472  }
473  }
474 
475  free_and_init (rep->variable[i].bt_stats);
476  rep->variable[i].bt_stats = NULL;
477  }
478  }
479 
480  free_and_init (rep->variable);
481  }
482 
483  free_and_init (rep);
484  }
485 }
486 
487 /*
488  * orc_class_info_from_record () - Extract the information necessary to build
489  * a CLS_INFO structure for the catalog
490  * return: class info structure
491  * record(in): disk record with class
492  */
493 CLS_INFO *
495 {
496  CLS_INFO *class_info_p;
497 
498  class_info_p = (CLS_INFO *) malloc (sizeof (CLS_INFO));
499  if (class_info_p == NULL)
500  {
502  return NULL;
503  }
504 
505  or_class_hfid (record, &(class_info_p->ci_hfid));
506 
507  class_info_p->ci_tot_pages = 0;
508  class_info_p->ci_tot_objects = 0;
509  class_info_p->ci_time_stamp = 0;
510 
511  or_class_rep_dir (record, &(class_info_p->ci_rep_dir));
512 
513  return class_info_p;
514 }
515 
516 /*
517  * orc_free_class_info () - Frees a CLS_INFO structure that was allocated by
518  * orc_class_info_from_record
519  * return: void
520  * info(in): class info structure
521  */
522 void
524 {
525  free_and_init (info);
526 }
527 
528 /*
529  * orc_subclasses_from_record () - Extracts the OID's of the immediate
530  * subclasses
531  * return: error code
532  * record(in): record containing a class
533  * array_size(out): pointer to int containing max size of array
534  * array_ptr(out): pointer to OID array
535  *
536  * Note: The array is maintained as an array of OID's, the last element in the
537  * array will satisfy the OID_ISNULL() test. The array_size has
538  * the number of actual elements allocated in the array which may be more
539  * than the number of slots that have non-NULL OIDs.
540  * The function adds the subclass oids to the existing array. If the
541  * array is not large enough, it is reallocated using realloc.
542  */
543 int
544 orc_subclasses_from_record (RECDES * record, int *array_size, OID ** array_ptr)
545 {
546  int error = NO_ERROR;
547  OID *array;
548  char *ptr;
549  int max, insert, i, newsize, nsubs;
550  char *subset = NULL;
551 
552  nsubs = 0;
553 
554  if (!OR_VAR_IS_NULL (record->data, ORC_SUBCLASSES_INDEX))
555  {
556  subset = (char *) (record->data) + OR_VAR_OFFSET (record->data, ORC_SUBCLASSES_INDEX);
557  nsubs = OR_SET_ELEMENT_COUNT (subset);
558  }
559 
560  if (nsubs)
561  {
562  max = *array_size;
563  array = *array_ptr;
564  if (array == NULL)
565  {
566  max = 0;
567  }
568 
569  /* find the last element in the array */
570  for (i = 0; i < max && !OID_ISNULL (&array[i]); i++)
571  {
572  ;
573  }
574  insert = i;
575 
576  /*
577  * check for array extension.
578  * Add one in the comparison since a NULL_OID is set at the end of the
579  * array
580  */
581  if (array == NULL || (insert + nsubs + 1) > max)
582  {
583  newsize = insert + nsubs + 10;
584  if (array == NULL)
585  {
586  array = (OID *) malloc (newsize * sizeof (OID));
587  }
588  else
589  {
590  array = (OID *) realloc (array, newsize * sizeof (OID));
591  }
592 
593  if (array == NULL)
594  {
597  }
598 
599  for (i = max; i < newsize; i++)
600  {
601  OID_SET_NULL (&array[i]);
602  }
603 
604  max = newsize;
605  }
606 
607  /* Advance past the set header, the domain size, and the "object" domain. Note that this assumes we are not using
608  * a bound bit array even though this is a fixed width homogeneous set. Probably not a good assumption. */
609  ptr = subset + OR_SET_HEADER_SIZE + OR_INT_SIZE + OR_INT_SIZE;
610 
611  assert (array != NULL);
612 
613  /* add the new OIDs */
614  for (i = 0; i < nsubs; i++)
615  {
616  OR_GET_OID (ptr, &array[insert + i]);
617  ptr += OR_OID_SIZE;
618  }
619 
620  OID_SET_NULL (&array[insert + nsubs]);
621 
622  /* return these in case there were changes */
623  *array_size = max;
624  *array_ptr = array;
625  }
626 
627  return error;
628 }
629 
630 /*
631  * orc_superclasses_from_record () - Extracts the OID's of the immediate
632  * superclasses
633  * return: error code
634  * record(in): record containing a class
635  * array_size(out): pointer to int containing max size of array
636  * array_ptr(out): pointer to OID array
637  *
638  * Note: The array is maintained as an array of OID's, the last element in the
639  * array will satisfy the OID_ISNULL() test. The array_size has
640  * the number of actual elements allocated in the array which may be
641  * more than the number of slots that have non-NULL OIDs.
642  * The function adds the subclass oids to the existing array. If the
643  * array is not large enough, it is reallocated using realloc.
644  */
645 int
646 orc_superclasses_from_record (RECDES * record, int *array_size, OID ** array_ptr)
647 {
648  int error = NO_ERROR;
649  OID *oid_array = NULL;
650  char *ptr = NULL;
651  int nsupers = 0, i = 0;
652  char *superset = NULL;
653 
654  assert (array_ptr != NULL);
655  assert (*array_ptr == NULL);
656  assert (array_size != NULL);
657 
658  nsupers = 0;
660  {
661  /* no superclasses, just return */
662  return NO_ERROR;
663  }
664 
665  superset = (char *) (record->data) + OR_VAR_OFFSET (record->data, ORC_SUPERCLASSES_INDEX);
666  nsupers = OR_SET_ELEMENT_COUNT (superset);
667  if (nsupers <= 0)
668  {
669  /* This is probably an error but there's no point in reporting it here. We just assume that there are no supers */
670  assert (false);
671  return NO_ERROR;
672  }
673 
674  oid_array = (OID *) malloc (nsupers * sizeof (OID));
675 
676  if (oid_array == NULL)
677  {
680  }
681 
682  /* Advance past the set header, the domain size, and the "object" domain. Note that this assumes we are not using a
683  * bound bit array even though this is a fixed width homogeneous set. Probably not a good assumption. */
684  ptr = superset + OR_SET_HEADER_SIZE + OR_INT_SIZE + OR_INT_SIZE;
685 
686  /* add the new OIDs */
687  for (i = 0; i < nsupers; i++)
688  {
689  OR_GET_OID (ptr, &oid_array[i]);
690  ptr += OR_OID_SIZE;
691  }
692 
693  /* return these in case there were changes */
694  *array_size = nsupers;
695  *array_ptr = oid_array;
696 
697  return error;
698 }
699 
700 /*
701  * or_class_rep_dir () - Extracts the OID of representation
702  * directory record of a class
703  * return: void
704  * record(in): packed disk record containing class
705  * rep_dir_p(out): OID of representation directory record to be filled in
706  */
707 void
708 or_class_rep_dir (RECDES * record, OID * rep_dir_p)
709 {
710  char *ptr;
711 
713 
714  ptr = (char *) record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT) + ORC_REP_DIR_OFFSET;
715 
716  OR_GET_OID (ptr, rep_dir_p);
717 }
718 
719 /*
720  * or_class_hfid () - Extracts just the HFID from the disk representation of
721  * a class
722  * return: void
723  * record(in): packed disk record containing class
724  * hfid(out): pointer to HFID structure to be filled in
725  *
726  * Note: It is used by the catalog manager to update the class information
727  * structure when the HFID is assigned. Since HFID's are assigned only
728  * when instances are created, a class may be entered into the catalog
729  * before the HFID is known.
730  */
731 void
733 {
734  char *ptr;
735 
737 
738  ptr = record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
740  hfid->vfid.volid = OR_GET_INT (ptr + ORC_HFID_VOLID_OFFSET);
741  hfid->hpgid = OR_GET_INT (ptr + ORC_HFID_PAGEID_OFFSET);
742 }
743 
744 /*
745  * or_class_tde_algorithm, () - Extracts the tde algorithm from the disk representation of a class
746  * return: void
747  * record(in): packed disk record containing class
748  * tde_algo (out): pointer to tde_algo to be filled in
749  *
750  */
751 void
753 {
754  char *ptr;
755 
757 
758  ptr = record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
759  *(int *) tde_algo = OR_GET_INT (ptr + ORC_CLASS_TDE_ALGORITHM);
760 }
761 
762 #if defined (ENABLE_UNUSED_FUNCTION)
763 /*
764  * or_class_statistics () - extracts the OID of the statistics instance for
765  * this class from the disk representation of a class
766  * return: void
767  * record(in): packed disk record containing class
768  * oid(in): pointer to OID structure to be filled in
769  */
770 void
771 or_class_statistics (RECDES * record, OID * oid)
772 {
773  char *ptr;
774 
776 
777  ptr = record->data + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
778 
779  /* this doesn't exist yet, return NULL */
780  OID_SET_NULL (oid);
781 }
782 
783 /*
784  * or_class_subclasses () - Extracts the OID's of the immediate subclasses
785  * return: error code
786  * record(in): record containing a class
787  * array_size(out): pointer to int containing max size of array
788  * array_ptr(out): pointer to OID array
789  *
790  * Note: The array is maintained as an array of OID's, the last element in the
791  * array will satisfy the OID_ISNULL() test. The array_size has
792  * the number of actual elements allocated in the array which may be more
793  * than the number of slots that have non-NULL OIDs.
794  * The function adds the subclass oids to the existing array. If the
795  * array is not large enough, it is reallocated using realloc.
796  */
797 int
798 or_class_subclasses (RECDES * record, int *array_size, OID ** array_ptr)
799 {
800  int error = NO_ERROR;
801  OID *array;
802  char *ptr;
803  int max, insert, i, newsize, nsubs;
804  char *subset = NULL;
805  size_t buf_size;
806 
807  nsubs = 0;
808  if (!OR_VAR_IS_NULL (record->data, ORC_SUBCLASSES_INDEX))
809  {
810  subset = (char *) (record->data) + OR_VAR_OFFSET (record->data, ORC_SUBCLASSES_INDEX);
811  nsubs = OR_SET_ELEMENT_COUNT (subset);
812  }
813 
814  if (nsubs)
815  {
816  max = *array_size;
817  array = *array_ptr;
818  if (array == NULL)
819  {
820  max = 0;
821  }
822 
823  /* find the last element in the array */
824  for (i = 0; i < max && !OID_ISNULL (&array[i]); i++)
825  {
826  ;
827  }
828  insert = i;
829 
830  /*
831  * check for array extension.
832  * Add one in the comparison since a NULL_OID is set at the end of the
833  * array
834  */
835  if ((insert + nsubs + 1) > max)
836  {
837  newsize = insert + nsubs + 10;
838 
839  buf_size = newsize * sizeof (OID);
840  if (array == NULL)
841  {
842  array = (OID *) malloc (buf_size);
843  }
844  else
845  {
846  array = (OID *) realloc (array, buf_size);
847  }
848 
849  if (array == NULL)
850  {
853  }
854 
855  for (i = max; i < newsize; i++)
856  {
857  OID_SET_NULL (&array[i]);
858  }
859  max = newsize;
860  }
861 
862  /* Advance past the set header, the domain size, and the "object" domain. Note that this assumes we are not using
863  * a bound bit array even though this is a fixed width homogeneous set. Probably not a good assumption. */
864  ptr = subset + OR_SET_HEADER_SIZE + OR_INT_SIZE + OR_INT_SIZE;
865 
866  if (array != NULL)
867  {
868  /* add the new OIDs */
869  for (i = 0; i < nsubs; i++)
870  {
871  OR_GET_OID (ptr, &array[insert + i]);
872  ptr += OR_OID_SIZE;
873  }
874  OID_SET_NULL (&array[insert + nsubs]);
875 
876  /* return these in case there were changes */
877  *array_size = max;
878  *array_ptr = array;
879  }
880  else
881  {
882  assert (false);
883  }
884  }
885 
886  return error;
887 }
888 #endif /* ENABLE_UNUSED_FUNCTION */
889 
890 /*
891  * or_get_hierarchy_helper () -
892  * return: error code
893  * source_class(in):
894  * class(in):
895  * btid(in):
896  * class_oids(out):
897  * hfids(out):
898  * num_classes(out):
899  * max_classes(out):
900  * partition_local_index(out):
901  *
902  * Note: This routine gets checks the class to see if it has an attribute named
903  * attr_name, that has a source class equal to source_class. This would
904  * mean that the given class participates in the hierachy. We add its
905  * heap and attribute id to the arrays and recurse for any subclasses
906  * that it might have.
907  */
908 static int
909 or_get_hierarchy_helper (THREAD_ENTRY * thread_p, OID * source_class, OID * class_, BTID * btid, OID ** class_oids,
910  HFID ** hfids, int *num_classes, int *max_classes, int *partition_local_index)
911 {
912  char *ptr;
913  char *subset = NULL;
914  OID sub_class;
915  int i, nsubs, found, newsize;
916  RECDES record = RECDES_INITIALIZER;
917  OR_CLASSREP *or_rep = NULL;
919  HFID hfid;
920  HEAP_SCANCACHE scan_cache;
921 
922  (void) heap_scancache_quick_start_root_hfid (thread_p, &scan_cache);
923 
924  if (heap_get_class_record (thread_p, class_, &record, &scan_cache, COPY) != S_SUCCESS)
925  {
926  goto error;
927  }
928 
929  or_rep = or_get_classrep (&record, NULL_REPRID);
930  if (or_rep == NULL)
931  {
932  goto error;
933  }
934 
935  found = 0;
936  or_index = &(or_rep->indexes[0]);
937  for (i = 0; i < or_rep->n_indexes && !found; i++, or_index++)
938  {
939  if (BTID_IS_EQUAL (&(or_index->btid), btid))
940  {
941  found = 1;
942  }
943  }
944 
945  if (!found)
946  {
947  /* check if we are dealing with a partition class in which the unique constraint stands as a local index and each
948  * partition has it's own btree */
949  if (or_rep->has_partition_info > 0 && partition_local_index != NULL)
950  {
951  *partition_local_index = 1;
952  }
953  else
954  {
955  goto success;
956  }
957  }
958 
959  /*
960  * For each subclass, recurse ...
961  * Unfortunately, this information is not available in the OR_CLASSREP
962  * structure, so we'll digress into the RECDES structure for it. It
963  * might be a good idea to add subclass information to the OR_CLASSREP
964  * structure.
965  */
966  nsubs = 0;
968  {
969  subset = (char *) (record.data) + OR_VAR_OFFSET (record.data, ORC_SUBCLASSES_INDEX);
970  nsubs = OR_SET_ELEMENT_COUNT (subset);
971  }
972 
973  if (nsubs)
974  {
975  /* Advance past the set header, the domain size, and the "object" domain. Note that this assumes we are not using
976  * a bound bit array even though this is a fixed width homogeneous set. Probably not a good assumption. */
977  ptr = subset + OR_SET_HEADER_SIZE + OR_INT_SIZE + OR_INT_SIZE;
978 
979  for (i = 0; i < nsubs; i++)
980  {
981  OR_GET_OID (ptr, &sub_class);
983  (thread_p, source_class, &sub_class, btid, class_oids, hfids, num_classes, max_classes,
984  partition_local_index) != NO_ERROR)
985  {
986  goto error;
987  }
988 
989  ptr += OR_OID_SIZE;
990  }
991  }
992 
993  /* If we have a valid HFID, then add this class to the array */
994  or_class_hfid (&record, &hfid);
995  if (HFID_IS_NULL (&hfid))
996  {
997  goto success;
998  }
999 
1000  /* Need to remove duplicates from a multiple inheritance hierarchy */
1001  for (i = 0; i < *num_classes; i++)
1002  {
1003  if (*class_oids != NULL && OID_EQ (class_, &((*class_oids)[i])))
1004  {
1005  goto success;
1006  }
1007  }
1008 
1009  /* do we need to extend the arrays? */
1010  if ((*num_classes + 1) > *max_classes)
1011  {
1012  newsize = *max_classes + OR_ARRAY_EXTENT;
1013 
1014  if (*class_oids == NULL)
1015  {
1016  *class_oids = (OID *) malloc (newsize * sizeof (OID));
1017  }
1018  else
1019  {
1020  *class_oids = (OID *) realloc (*class_oids, newsize * sizeof (OID));
1021  }
1022 
1023  if (*class_oids == NULL)
1024  {
1026  goto error;
1027  }
1028 
1029  if (*hfids == NULL)
1030  {
1031  *hfids = (HFID *) malloc (newsize * sizeof (HFID));
1032  }
1033  else
1034  {
1035  *hfids = (HFID *) realloc (*hfids, newsize * sizeof (HFID));
1036  }
1037 
1038  if (*hfids == NULL)
1039  {
1041  goto error;
1042  }
1043 
1044  *max_classes = newsize;
1045  }
1046 
1047  if (*class_oids == NULL || *hfids == NULL)
1048  {
1049  goto error;
1050  }
1051 
1052  COPY_OID (&((*class_oids)[*num_classes]), class_);
1053  (*hfids)[*num_classes] = hfid;
1054  *num_classes += 1;
1055 
1056 success:
1057  or_free_classrep (or_rep);
1058  (void) heap_scancache_end (thread_p, &scan_cache);
1059  return NO_ERROR;
1060 
1061 error:
1062  if (or_rep != NULL)
1063  {
1064  or_free_classrep (or_rep);
1065  }
1066 
1067  (void) heap_scancache_end (thread_p, &scan_cache);
1068 
1069  assert (er_errid () != NO_ERROR);
1070  return er_errid ();
1071 }
1072 
1073 /*
1074  * or_get_unique_hierarchy () -
1075  * return:
1076  * record(in): record containing a class
1077  * attrid(in): unique attrid (the one we'll get the hierarchy for)
1078  * btid(in):
1079  * class_oids(out):
1080  * hfids(out): pointer to HFID array
1081  * num_classes(out):
1082  * partition_local_index(out):
1083  *
1084  * Note: This function uses the attribute represented by the attrid and finds
1085  * the source class for that attribute (where it was defined in the class
1086  * hierarchy). Then the heap files for all the classes that are in the
1087  * hierarchy rooted at the source class that contain the (non shadowed)
1088  * attribute are returned in the hfids array and their respective attrids
1089  * are returned in the attrids array. num_heaps will indicate how many
1090  * positions of the arrays are valid.
1091  *
1092  * it is the callers responsibility to free the hfids and attrids
1093  * arrays if this routine returns successfully.
1094  *
1095  * <attrid> is currently used only to find the source class for
1096  * the BTID. The index attributes can be obtained through the
1097  * BTID if needed so it might be a good idea to get rid of the
1098  * attribute ID parameter since it no longer represents the
1099  * index well.
1100  */
1101 int
1102 or_get_unique_hierarchy (THREAD_ENTRY * thread_p, RECDES * record, int attrid, BTID * btid, OID ** class_oids,
1103  HFID ** hfids, int *num_classes, int *partition_local_index)
1104 {
1105  int n_attributes, n_fixed, n_variable, i;
1106  int id, found, max_classes;
1107  char *attr_name, *start, *ptr, *attset, *diskatt = NULL;
1108  OID source_class;
1109 
1110  *num_classes = 0;
1111  max_classes = 0;
1112  *class_oids = NULL;
1113  *hfids = NULL;
1114 
1115  if (partition_local_index != NULL)
1116  {
1117  *partition_local_index = 0;
1118  }
1119 
1120  /* find the source class of the attribute from the record */
1121  start = record->data;
1122 
1124 
1125  ptr = start + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
1126 
1127  n_fixed = OR_GET_INT (ptr + ORC_FIXED_COUNT_OFFSET);
1128  n_variable = OR_GET_INT (ptr + ORC_VARIABLE_COUNT_OFFSET);
1129  n_attributes = n_fixed + n_variable;
1130 
1131  /* find the start of the "set_of(attribute)" attribute inside the class */
1132  attset = start + OR_VAR_OFFSET (start, ORC_ATTRIBUTES_INDEX);
1133 
1134  /* loop over each attribute in the class record to find our attribute */
1135  for (i = 0, found = 0; i < n_attributes && !found; i++)
1136  {
1137  /* diskatt will now be pointing at the offset table for this attribute. this is logically the "start" of this
1138  * nested object. */
1139 
1140  diskatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
1141 
1142  /* set ptr to the beginning of the fixed attributes */
1143  ptr = diskatt + OR_VAR_TABLE_SIZE (ORC_ATT_VAR_ATT_COUNT);
1144 
1145  /* is this the attribute we want? */
1146  id = OR_GET_INT (ptr + ORC_ATT_ID_OFFSET);
1147  if (id == attrid)
1148  {
1149  found = 1;
1150  OR_GET_OID (ptr + ORC_ATT_CLASS_OFFSET, &source_class);
1151  }
1152  }
1153 
1154  /* diskatt now points to the attribute that we are interested in. Get the attribute name. */
1155  if (diskatt == NULL)
1156  {
1157  goto error;
1158  }
1159 
1160  attr_name = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_NAME_INDEX));
1161 
1162  if (!found || (OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_NAME_INDEX) == 0)
1163  || (or_get_hierarchy_helper (thread_p, &source_class, &source_class, btid, class_oids, hfids, num_classes,
1164  &max_classes, partition_local_index) != NO_ERROR))
1165  {
1166  goto error;
1167  }
1168 
1169  return NO_ERROR;
1170 
1171 error:
1172  if (*class_oids)
1173  {
1174  free_and_init (*class_oids);
1175  }
1176 
1177  if (*hfids)
1178  {
1179  free_and_init (*hfids);
1180  }
1181 
1183 
1184  return ER_GENERIC_ERROR;
1185 }
1186 
1187 /*
1188  * or_get_domain_internal () -
1189  * return: transient domain
1190  * ptr(in): pointer to the beginning of a domain in a class
1191  */
1192 static TP_DOMAIN *
1194 {
1195  TP_DOMAIN *domain, *last, *new_;
1196  int n_domains, offset, i, error = NO_ERROR;
1197  char *dstart, *fixed;
1198  DB_TYPE typeid_;
1199 
1200  domain = last = NULL;
1201 
1202  /* ptr has the beginning of a substructure set of domains */
1203  n_domains = OR_SET_ELEMENT_COUNT (ptr);
1204  for (i = 0; i < n_domains; i++)
1205  {
1206  /* find the start of the domain in the set */
1207  dstart = ptr + OR_SET_ELEMENT_OFFSET (ptr, i);
1208 
1209  /* dstart points to the offset table for this substructure, get the position of the first fixed attribute. */
1210  fixed = dstart + OR_VAR_TABLE_SIZE (ORC_DOMAIN_VAR_ATT_COUNT);
1211 
1212  typeid_ = (DB_TYPE) OR_GET_INT (fixed + ORC_DOMAIN_TYPE_OFFSET);
1213 
1214  new_ = tp_domain_new (typeid_);
1215  if (new_ == NULL)
1216  {
1217  goto error_cleanup;
1218  }
1219 
1220  if (last == NULL)
1221  {
1222  domain = new_;
1223  }
1224  else
1225  {
1226  last->next = new_;
1227  }
1228  last = new_;
1229 
1231  new_->scale = OR_GET_INT (fixed + ORC_DOMAIN_SCALE_OFFSET);
1232  new_->codeset = OR_GET_INT (fixed + ORC_DOMAIN_CODESET_OFFSET);
1233  if (typeid_ == DB_TYPE_ENUMERATION && new_->codeset == 0)
1234  {
1237  }
1239 
1240  OR_GET_OID (fixed + ORC_DOMAIN_CLASS_OFFSET, &new_->class_oid);
1241  /* can't swizzle the pointer on the server */
1242  new_->class_mop = NULL;
1243 
1245  {
1246  new_->setdomain = NULL;
1247  }
1248  else
1249  {
1251  new_->setdomain = or_get_domain_internal (dstart + offset);
1252  }
1253 
1254  DOM_SET_ENUM (new_, NULL, 0);
1256  {
1257  OR_BUF buf;
1258 
1260 
1261  or_init (&buf, dstart + offset, 0);
1262 
1263  new_->enumeration.collation_id = new_->collation_id;
1264 
1265  error = or_get_enumeration (&buf, &DOM_GET_ENUMERATION (new_));
1266  if (error != NO_ERROR)
1267  {
1268  goto error_cleanup;
1269  }
1270  }
1271 
1273  {
1274  OR_BUF buf;
1275 
1277  or_init (&buf, dstart + offset, 0);
1278 
1279  error = or_get_json_validator (&buf, domain->json_validator);
1280  if (error != NO_ERROR)
1281  {
1282  goto error_cleanup;
1283  }
1284  }
1285  }
1286 
1287  return domain;
1288 
1289 error_cleanup:
1290  while (domain != NULL)
1291  {
1292  TP_DOMAIN *next = domain->next;
1293  tp_domain_free (domain);
1294  domain = next;
1295  }
1296  return NULL;
1297 }
1298 
1299 /*
1300  * or_get_domain_and_cache () -
1301  * return:
1302  * ptr(in):
1303  */
1304 static TP_DOMAIN *
1306 {
1307  TP_DOMAIN *domain;
1308 
1309  domain = or_get_domain_internal (ptr);
1310  if (domain != NULL)
1311  {
1312  domain = tp_domain_cache (domain);
1313  }
1314 
1315  return domain;
1316 }
1317 
1318 /*
1319  * or_get_att_index () - Extracts a BTID from the disk representation of an
1320  * attribute
1321  * return: void
1322  * ptr(in): buffer pointer
1323  * btid(out): btree identifier
1324  */
1325 static void
1327 {
1328  unsigned int uval;
1329 
1330  btid->vfid.fileid = (FILEID) OR_GET_INT (ptr);
1331  ptr += OR_INT_SIZE;
1332  btid->root_pageid = (PAGEID) OR_GET_INT (ptr);
1333  ptr += OR_INT_SIZE;
1334  uval = (unsigned int) OR_GET_INT (ptr);
1335  btid->vfid.volid = (VOLID) (uval & 0xFFFF);
1336 }
1337 
1338 /*
1339  * or_get_default_value () - Copies the default value of an attribute from disk
1340  * return: zero to indicate error
1341  * attr(in): disk attribute structure
1342  * ptr(in): pointer to beginning of value
1343  * length(in): length of value on disk
1344  *
1345  * Note: The data manipulation for this is a bit odd, owing to the "rich"
1346  * and varied history of default value manipulation in the catalog.
1347  * The callers expect to be given a value buffer in disk representation
1348  * format, which as it turns out they will immediately turn around and
1349  * use the "readval" function on to get it into a DB_VALUE. This prevents
1350  * us from actually returning the value in a DB_VALUE here because then
1351  * the callers would have to deal with two different value formats,
1352  * diskrep for non-default values and DB_VALUE rep for default values.
1353  * This might not be hard to do and should be considered at some point.
1354  *
1355  * As it stands, we have to perform some of the same operations as
1356  * or_get_value here and return a buffer containing a copy of the disk
1357  * representation of the value only (not the domain).
1358  */
1359 static int
1360 or_get_default_value (OR_ATTRIBUTE * attr, char *ptr, int length)
1361 {
1362  int success, is_null;
1363  TP_DOMAIN *domain;
1364  char *vptr;
1365 
1366  if (length == 0)
1367  {
1368  return 1;
1369  }
1370 
1371  /* skip over the domain tag, check for tagged NULL */
1372  success = 0;
1373  domain = NULL;
1374  vptr = or_unpack_domain (ptr, &domain, &is_null);
1375  if (domain == NULL)
1376  {
1377  return 0;
1378  }
1379 
1380  /* reduce the expected size by the amount consumed with the domain tag */
1381  length -= (int) (vptr - ptr);
1382 
1383  if (is_null || length == 0)
1384  {
1385  success = 1;
1386  }
1387  else
1388  {
1390  attr->default_value.value = malloc (length);
1391  if (attr->default_value.value != NULL)
1392  {
1393  memcpy (attr->default_value.value, vptr, length);
1394  success = 1;
1395  }
1396  }
1397 
1398  return success;
1399 }
1400 
1401 /*
1402  * or_get_current_default_value () - Copies the current default value of an
1403  * attribute from disk
1404  * return: zero to indicate error
1405  * attr(in): disk attribute structure
1406  * ptr(in): pointer to beginning of value
1407  * length(in): length of value on disk
1408  */
1409 static int
1411 {
1412  int success, is_null;
1413  TP_DOMAIN *domain;
1414  char *vptr;
1415 
1416  if (length == 0)
1417  {
1418  return 1;
1419  }
1420 
1421  /* skip over the domain tag, check for tagged NULL */
1422  success = 0;
1423  domain = NULL;
1424  vptr = or_unpack_domain (ptr, &domain, &is_null);
1425  if (domain == NULL)
1426  {
1427  return 0;
1428  }
1429 
1430  /* reduce the expected size by the amount consumed with the domain tag */
1431  length -= (int) (vptr - ptr);
1432 
1433  if (is_null || length == 0)
1434  {
1435  success = 1;
1436  }
1437  else
1438  {
1440  attr->current_default_value.value = malloc (length);
1441  if (attr->current_default_value.value != NULL)
1442  {
1443  memcpy (attr->current_default_value.value, vptr, length);
1444  success = 1;
1445  }
1446  }
1447 
1448  return success;
1449 }
1450 
1451 /*
1452  * or_cl_get_prop_nocopy () - Modified version of classobj_get_prop that tries to
1453  * avoid copying of the values
1454  * return: non-zero if the property was found
1455  * properties(in): property sequence
1456  * name(in): name of property to find
1457  * pvalue(in): property value
1458  *
1459  * Note: This was written for object_representation_sr.c but could be used in other cases if
1460  * you're careful.
1461  * Uses the hacked set_get_element_nocopy function above, this is
1462  * probably what we should be doing anyway, it would make property list
1463  * operations faster.
1464  */
1465 static int
1466 or_cl_get_prop_nocopy (DB_SEQ * properties, const char *name, DB_VALUE * pvalue)
1467 {
1468  int error;
1469  int found, max, i;
1470  DB_VALUE value;
1471  const char *prop_name;
1472 
1473  error = NO_ERROR;
1474  found = 0;
1475 
1476  if (properties != NULL && name != NULL && pvalue != NULL)
1477  {
1478  max = set_size (properties);
1479  for (i = 0; i < max && !found && error == NO_ERROR; i += 2)
1480  {
1481  error = set_get_element_nocopy (properties, i, &value);
1482  if (error == NO_ERROR)
1483  {
1484  if (DB_VALUE_TYPE (&value) != DB_TYPE_STRING || db_get_string (&value) == NULL)
1485  {
1486  error = ER_SM_INVALID_PROPERTY;
1487  }
1488  else
1489  {
1490  prop_name = db_get_string (&value);
1491  if (strcmp (name, prop_name) == 0)
1492  {
1493  if ((i + 1) >= max)
1494  {
1495  error = ER_SM_INVALID_PROPERTY;
1496  }
1497  else
1498  {
1499  error = set_get_element_nocopy (properties, i + 1, pvalue);
1500  if (error == NO_ERROR)
1501  found = i + 1;
1502  }
1503  }
1504  }
1505  }
1506  }
1507  }
1508 
1509  if (error)
1510  {
1511  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1512  }
1513 
1514  return (found);
1515 }
1516 
1517 /*
1518  * or_install_btids_foreign_key () -
1519  * return:
1520  * fkname(in):
1521  * fk_seq(in):
1522  * index(in):
1523  */
1524 static void
1525 or_install_btids_foreign_key (const char *fkname, DB_SEQ * fk_seq, OR_INDEX * index)
1526 {
1527  DB_VALUE val;
1528  int args;
1529  int pageid, slotid, volid, fileid;
1530 
1531  index->fk = (OR_FOREIGN_KEY *) malloc (sizeof (OR_FOREIGN_KEY));
1532  if (index->fk == NULL)
1533  {
1534  assert (false); /* TODO */
1535  return;
1536  }
1537 
1538  if (set_get_element_nocopy (fk_seq, 0, &val) != NO_ERROR)
1539  {
1540  return;
1541  }
1542 
1543  index->fk->next = NULL;
1544  index->fk->fkname = strdup (fkname);
1545 
1546  args = classobj_decompose_property_oid (db_get_string (&val), &pageid, &slotid, &volid);
1547  if (args != 3)
1548  {
1549  return;
1550  }
1551 
1552  index->fk->ref_class_oid.pageid = (PAGEID) pageid;
1553  index->fk->ref_class_oid.slotid = (PGSLOTID) slotid;
1554  index->fk->ref_class_oid.volid = (VOLID) volid;
1555 
1556  if (set_get_element_nocopy (fk_seq, 1, &val) != NO_ERROR)
1557  {
1558  return;
1559  }
1560 
1561  args = classobj_decompose_property_oid (db_get_string (&val), &volid, &fileid, &pageid);
1562 
1563  if (args != 3)
1564  {
1565  return;
1566  }
1567 
1568  index->fk->ref_class_pk_btid.vfid.volid = (VOLID) volid;
1569  index->fk->ref_class_pk_btid.root_pageid = (PAGEID) pageid;
1570  index->fk->ref_class_pk_btid.vfid.fileid = (FILEID) fileid;
1571 
1572  set_get_element_nocopy (fk_seq, 2, &val);
1573  index->fk->del_action = db_get_int (&val);
1574 
1575  set_get_element_nocopy (fk_seq, 3, &val);
1576  index->fk->upd_action = db_get_int (&val);
1577 }
1578 
1579 /*
1580  * or_install_btids_foreign_key_ref () -
1581  * return:
1582  * fk_container(in):
1583  * index(in):
1584  */
1585 static void
1587 {
1588  DB_VALUE val, fkval;
1589  int args, size, i;
1590  int pageid, slotid, volid, fileid;
1591  DB_SEQ *fk_seq;
1592  OR_FOREIGN_KEY *fk, *p = NULL;
1593  const char *fkname;
1594 
1595  size = set_size (fk_container);
1596 
1597  for (i = 0; i < size; i++)
1598  {
1599  if (set_get_element_nocopy (fk_container, i, &fkval) != NO_ERROR)
1600  {
1601  return;
1602  }
1603 
1604  fk_seq = db_get_set (&fkval);
1605 
1606  fk = (OR_FOREIGN_KEY *) malloc (sizeof (OR_FOREIGN_KEY));
1607  if (fk == NULL)
1608  {
1609  assert (false); /* TODO */
1610  return;
1611  }
1612 
1613  fk->next = NULL;
1614 
1615  if (set_get_element_nocopy (fk_seq, 0, &val) != NO_ERROR)
1616  {
1617  free_and_init (fk);
1618  return;
1619  }
1620 
1621  args = classobj_decompose_property_oid (db_get_string (&val), &pageid, &slotid, &volid);
1622 
1623  if (args != 3)
1624  {
1625  free_and_init (fk);
1626  return;
1627  }
1628 
1629  fk->self_oid.pageid = (PAGEID) pageid;
1630  fk->self_oid.slotid = (PGSLOTID) slotid;
1631  fk->self_oid.volid = (VOLID) volid;
1632 
1633  if (set_get_element_nocopy (fk_seq, 1, &val) != NO_ERROR)
1634  {
1635  free_and_init (fk);
1636  return;
1637  }
1638 
1639  args = classobj_decompose_property_oid (db_get_string (&val), &volid, &fileid, &pageid);
1640 
1641  if (args != 3)
1642  {
1643  free_and_init (fk);
1644  return;
1645  }
1646 
1647  fk->self_btid.vfid.volid = (VOLID) volid;
1648  fk->self_btid.root_pageid = (PAGEID) pageid;
1649  fk->self_btid.vfid.fileid = (FILEID) fileid;
1650 
1651  if (set_get_element_nocopy (fk_seq, 2, &val) != NO_ERROR)
1652  {
1653  free_and_init (fk);
1654  return;
1655  }
1656  fk->del_action = db_get_int (&val);
1657 
1658  if (set_get_element_nocopy (fk_seq, 3, &val) != NO_ERROR)
1659  {
1660  free_and_init (fk);
1661  return;
1662  }
1663  fk->upd_action = db_get_int (&val);
1664 
1665  if (set_get_element_nocopy (fk_seq, 4, &val) != NO_ERROR)
1666  {
1667  free_and_init (fk);
1668  return;
1669  }
1670  fkname = db_get_string (&val);
1671  fk->fkname = strdup (fkname);
1672 
1673  if (i == 0)
1674  {
1675  index->fk = fk;
1676  p = index->fk;
1677  }
1678  else
1679  {
1680  if (p != NULL)
1681  {
1682  p->next = fk;
1683  p = p->next;
1684  }
1685  else
1686  {
1687  free_and_init (fk->fkname);
1688  free_and_init (fk);
1689  }
1690  }
1691  }
1692 }
1693 
1694 /*
1695  * or_install_btids_prefix_length () - Load prefix length information
1696  * return:
1697  * prefix_seq(in): sequence which contains the prefix length
1698  * index(in): index info structure
1699  * num_attrs(in): key attribute count
1700  */
1701 static void
1702 or_install_btids_prefix_length (DB_SEQ * prefix_seq, OR_INDEX * index, int num_attrs)
1703 {
1704  DB_VALUE val;
1705  int i;
1706 
1707  assert (prefix_seq != NULL && set_size (prefix_seq) == num_attrs);
1708  index->attrs_prefix_length = (int *) malloc (sizeof (int) * num_attrs);
1709  if (index->attrs_prefix_length == NULL)
1710  {
1711  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (int) * num_attrs);
1712  return;
1713  }
1714 
1715  for (i = 0; i < num_attrs; i++)
1716  {
1717  if (set_get_element_nocopy (prefix_seq, i, &val) != NO_ERROR)
1718  {
1720  return;
1721  }
1722 
1723  index->attrs_prefix_length[i] = db_get_int (&val);
1724  }
1725 }
1726 
1727 /*
1728  * or_install_btids_filter_pred () - Load index filter predicate information
1729  * return: error code
1730  * pred_seq(in): sequence which contains the filter predicate
1731  * index(in): index info structure
1732  */
1733 static int
1735 {
1736  DB_VALUE val1, val2;
1737  int error = NO_ERROR;
1738  int buffer_len = 0;
1739  const char *buffer = NULL;
1740  OR_PREDICATE *filter_predicate = NULL;
1741 
1742  index->filter_predicate = NULL;
1743  if (set_get_element_nocopy (pred_seq, 0, &val1) != NO_ERROR)
1744  {
1746  return ER_SM_INVALID_PROPERTY;
1747  }
1748 
1749  switch (DB_VALUE_TYPE (&val1))
1750  {
1751  case DB_TYPE_NULL:
1752  return NO_ERROR;
1753 
1754  case DB_TYPE_STRING:
1755  /* continue */
1756  break;
1757 
1758  default:
1759  error = ER_SM_INVALID_PROPERTY;
1761  return ER_SM_INVALID_PROPERTY;
1762  }
1763 
1764  if (set_get_element_nocopy (pred_seq, 1, &val2) != NO_ERROR)
1765  {
1766  error = ER_SM_INVALID_PROPERTY;
1768  return ER_SM_INVALID_PROPERTY;
1769  }
1770 
1771  switch (DB_VALUE_TYPE (&val2))
1772  {
1773  case DB_TYPE_NULL:
1774  return NO_ERROR;
1775 
1776  case DB_TYPE_CHAR:
1777  /* continue */
1778  break;
1779 
1780  default:
1781  error = ER_SM_INVALID_PROPERTY;
1783  return ER_SM_INVALID_PROPERTY;
1784  }
1785 
1786  /* currently, element 2 from pred_seq is used only on client side */
1787 
1788  filter_predicate = (OR_PREDICATE *) malloc (sizeof (OR_PREDICATE));
1789  if (filter_predicate == NULL)
1790  {
1791  error = ER_OUT_OF_VIRTUAL_MEMORY;
1793  return ER_OUT_OF_VIRTUAL_MEMORY;
1794  }
1795 
1796  filter_predicate->pred_string = strdup (db_get_string (&val1));
1797  if (filter_predicate->pred_string == NULL)
1798  {
1799  error = ER_OUT_OF_VIRTUAL_MEMORY;
1801  strlen (db_get_string (&val1)) * sizeof (char));
1802  goto err;
1803  }
1804 
1805  buffer = db_get_string (&val2);
1806  buffer_len = db_get_string_size (&val2);
1807  filter_predicate->pred_stream = (char *) malloc (buffer_len * sizeof (char));
1808  if (filter_predicate->pred_stream == NULL)
1809  {
1810  error = ER_OUT_OF_VIRTUAL_MEMORY;
1811  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, buffer_len * sizeof (char));
1812  goto err;
1813  }
1814 
1815  memcpy (filter_predicate->pred_stream, buffer, buffer_len);
1816  filter_predicate->pred_stream_size = buffer_len;
1817  index->filter_predicate = filter_predicate;
1818  return NO_ERROR;
1819 
1820 err:
1821  if (filter_predicate)
1822  {
1823  if (filter_predicate->pred_string)
1824  {
1825  free_and_init (filter_predicate->pred_string);
1826  }
1827 
1828  if (filter_predicate->pred_stream)
1829  {
1830  free_and_init (filter_predicate->pred_stream);
1831  }
1832 
1833  free_and_init (filter_predicate);
1834  }
1835  return error;
1836 }
1837 
1838 /*
1839  * or_install_btids_class () - Install (add) the B-tree ID to the index
1840  * structure of the class representation
1841  * return: void
1842  * rep(in): Class representation
1843  * id(in): B-tree ID
1844  * constraint_seq(in): Set which contains the attribute ID's
1845  * max(in): Number of elements in the set
1846  * type(in):
1847  * cons_name(in):
1848  *
1849  * Note: The index structure (OR_INDEX) is assumed to
1850  * be allocated before this function is called. We will allocate
1851  * room for the attribute pointer array which will be filled with
1852  * pointers to attributes (also from the class representation) which
1853  * share this B-tree ID (and associated constraint).
1854  *
1855  * The purpose of this function is to provide a list of B-tree IDs at
1856  * that belong to the class and to provide a reference to the attributes
1857  * that are associated with each B-tree ID. This complements the other
1858  * structures which are in place that provide a list of B-tree IDs
1859  * associated with an attribute in each attribute structure
1860  * (OR_ATTRIBUTE).
1861  * { [attrID, asc_desc]+,
1862  * {fk_info} or {key prefix length} or {function index} or {filter index}+,
1863  * comment
1864  * }
1865  */
1866 static void
1867 or_install_btids_class (OR_CLASSREP * rep, BTID * id, DB_SEQ * constraint_seq, int seq_size, BTREE_TYPE type,
1868  const char *cons_name)
1869 {
1870  DB_VALUE att_val;
1871  int i, j, e;
1872  int att_id, att_cnt;
1873  OR_ATTRIBUTE *att;
1874  OR_ATTRIBUTE *ptr = NULL;
1875  OR_INDEX *index;
1876  DB_VALUE stat_val;
1877 
1878  db_make_null (&stat_val);
1879 
1880  if (seq_size < 2)
1881  {
1882  /* No attributes IDs here */
1883  return;
1884  }
1885 
1886  index = &(rep->indexes[rep->n_indexes]);
1887 
1888  att_cnt = (seq_size - 3) / 2;
1889 
1890  index->atts = (OR_ATTRIBUTE **) malloc (sizeof (OR_ATTRIBUTE *) * att_cnt);
1891  if (index->atts == NULL)
1892  {
1894  return;
1895  }
1896 
1897  index->asc_desc = (int *) malloc (sizeof (int) * att_cnt);
1898  if (index->asc_desc == NULL)
1899  {
1900  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (int) * att_cnt);
1901  return;
1902  }
1903 
1904  (rep->n_indexes)++;
1905  index->btid = *id;
1906  index->n_atts = 0;
1907  index->type = type;
1908  index->fk = NULL;
1909  index->attrs_prefix_length = NULL;
1910  index->filter_predicate = NULL;
1911  index->func_index_info = NULL;
1912  index->index_status = OR_NO_INDEX;
1913 
1914  /*
1915  * For each attribute ID in the set,
1916  * Extract the attribute ID,
1917  * Find the matching attribute and insert the pointer into the array.
1918  */
1919 
1920  /* Remember that the attribute IDs start in the second position. */
1921  e = 1;
1922 
1923  for (i = 0; i < att_cnt; i++)
1924  {
1925  if (set_get_element_nocopy (constraint_seq, e++, &att_val) == NO_ERROR)
1926  {
1927  if (DB_VALUE_TYPE (&att_val) == DB_TYPE_SEQUENCE)
1928  {
1929  break;
1930  }
1931 
1932  att_id = db_get_int (&att_val);
1933 
1934  for (j = 0, att = rep->attributes, ptr = NULL; j < rep->n_attributes && ptr == NULL; j++, att++)
1935  {
1936  if (att->id == att_id)
1937  {
1938  ptr = att;
1939  index->atts[index->n_atts] = ptr;
1940  (index->n_atts)++;
1941  }
1942  }
1943 
1944  }
1945 
1946  /* asc_desc info */
1947  if (set_get_element_nocopy (constraint_seq, e++, &att_val) == NO_ERROR)
1948  {
1949  index->asc_desc[i] = db_get_int (&att_val);
1950  }
1951  }
1952  index->btname = strdup (cons_name);
1953 
1954  /* Get the index status. */
1955  set_get_element_nocopy (constraint_seq, seq_size - 2, &stat_val);
1956  index->index_status = (OR_INDEX_STATUS) (db_get_int (&stat_val));
1957 
1958  if (type == BTREE_FOREIGN_KEY)
1959  {
1960  if (set_get_element_nocopy (constraint_seq, seq_size - 3, &att_val) == NO_ERROR)
1961  {
1962  or_install_btids_foreign_key (cons_name, db_get_set (&att_val), index);
1963  }
1964  }
1965  else if (type == BTREE_PRIMARY_KEY)
1966  {
1967  if (set_get_element_nocopy (constraint_seq, seq_size - 3, &att_val) == NO_ERROR)
1968  {
1969  if (DB_VALUE_TYPE (&att_val) == DB_TYPE_SEQUENCE)
1970  {
1971  or_install_btids_foreign_key_ref (db_get_set (&att_val), index);
1972  }
1973  }
1974  }
1975  else
1976  {
1977  if (set_get_element_nocopy (constraint_seq, seq_size - 3, &att_val) == NO_ERROR)
1978  {
1979  if (DB_VALUE_TYPE (&att_val) == DB_TYPE_SEQUENCE)
1980  {
1981  DB_SEQ *seq = db_get_set (&att_val);
1982  DB_VALUE val;
1983 
1984  if (set_get_element_nocopy (seq, 0, &val) == NO_ERROR)
1985  {
1986  if (DB_VALUE_TYPE (&val) == DB_TYPE_INTEGER)
1987  {
1988  or_install_btids_prefix_length (db_get_set (&att_val), index, att_cnt);
1989  }
1990  else if (DB_VALUE_TYPE (&val) == DB_TYPE_SEQUENCE)
1991  {
1992  DB_VALUE avalue;
1993  DB_SET *child_seq = db_get_set (&val);
1994  int seq_size = set_size (seq);
1995  int flag;
1996 
1997  j = 0;
1998  while (true)
1999  {
2000  flag = 0;
2001  if (set_get_element_nocopy (child_seq, 0, &avalue) != NO_ERROR)
2002  {
2003  goto next_child;
2004  }
2005 
2006  if (DB_IS_NULL (&avalue) || DB_VALUE_TYPE (&avalue) != DB_TYPE_STRING)
2007  {
2008  goto next_child;
2009  }
2010 
2011  if (strcmp (db_get_string (&avalue), SM_FILTER_INDEX_ID) == 0)
2012  {
2013  flag = 0x01;
2014  }
2015  else if (strcmp (db_get_string (&avalue), SM_FUNCTION_INDEX_ID) == 0)
2016  {
2017  flag = 0x02;
2018  }
2019  else if (strcmp (db_get_string (&avalue), SM_PREFIX_INDEX_ID) == 0)
2020  {
2021  flag = 0x03;
2022  }
2023 
2024  if (set_get_element_nocopy (child_seq, 1, &avalue) != NO_ERROR)
2025  {
2026  goto next_child;
2027  }
2028 
2029  if (DB_VALUE_TYPE (&avalue) != DB_TYPE_SEQUENCE)
2030  {
2031  goto next_child;
2032  }
2033 
2034  switch (flag)
2035  {
2036  case 0x01:
2037  or_install_btids_filter_pred (db_get_set (&avalue), index);
2038  break;
2039 
2040  case 0x02:
2041  or_install_btids_function_info (db_get_set (&avalue), index);
2042  break;
2043 
2044  case 0x03:
2045  or_install_btids_prefix_length (db_get_set (&avalue), index, att_cnt);
2046  break;
2047 
2048  default:
2049  break;
2050  }
2051 
2052  next_child:
2053  j++;
2054  if (j >= seq_size)
2055  {
2056  break;
2057  }
2058 
2059  if (set_get_element_nocopy (seq, j, &val) != NO_ERROR)
2060  {
2061  continue;
2062  }
2063 
2064  if (DB_VALUE_TYPE (&val) != DB_TYPE_SEQUENCE)
2065  {
2066  continue;
2067  }
2068 
2069  child_seq = db_get_set (&val);
2070  }
2071 
2072  if (index->func_index_info)
2073  {
2074  /* function index and prefix length not allowed, yet */
2075  index->attrs_prefix_length = (int *) malloc (sizeof (int) * att_cnt);
2076  if (index->attrs_prefix_length == NULL)
2077  {
2079  sizeof (int) * att_cnt);
2080  return;
2081  }
2082  for (i = 0; i < att_cnt; i++)
2083  {
2084  index->attrs_prefix_length[i] = -1;
2085  }
2086  }
2087  }
2088  else
2089  {
2090  assert (0);
2091  }
2092  }
2093  }
2094  else
2095  {
2096  assert (0);
2097  }
2098  }
2099  }
2100 }
2101 
2102 /*
2103  * or_install_btids_attribute () - Install (add) the B-tree ID to the
2104  * appropriate attribute in the class
2105  * representation
2106  * return:
2107  * rep(in): Class representation
2108  * att_id(in): Attribute ID
2109  * id(in): B-tree ID
2110  */
2111 static int
2113 {
2114  int i;
2115  OR_ATTRIBUTE *att;
2116  int success = 1;
2117  OR_ATTRIBUTE *ptr = NULL;
2118  int size;
2119 
2120  /* Find the attribute with the matching attribute ID */
2121  for (i = 0, att = rep->attributes; i < rep->n_attributes && ptr == NULL; i++, att++)
2122  {
2123  if (att->id == att_id)
2124  {
2125  ptr = att;
2126  }
2127  }
2128 
2129  /* Allocate storage for the ID and store it */
2130  if (ptr != NULL)
2131  {
2132  if (ptr->btids == NULL)
2133  {
2134  /* we've never had one before, use the local pack */
2135  ptr->btids = ptr->btid_pack;
2137  }
2138  else
2139  {
2140  /* we've already got one, continue to use the local pack until that runs out and then start mallocing. */
2141  if (ptr->n_btids >= ptr->max_btids)
2142  {
2143  if (ptr->btids == ptr->btid_pack)
2144  {
2145  /* allocate a bigger array and copy over our local pack */
2146  size = ptr->n_btids + OR_ATT_BTID_PREALLOC;
2147  ptr->btids = (BTID *) malloc (sizeof (BTID) * size);
2148  if (ptr->btids != NULL)
2149  {
2150  memcpy (ptr->btids, ptr->btid_pack, (sizeof (BTID) * ptr->n_btids));
2151  }
2152  ptr->max_btids = size;
2153  }
2154  else
2155  {
2156  /* we already have an externally allocated array, make it bigger */
2157  size = ptr->n_btids + OR_ATT_BTID_PREALLOC;
2158  ptr->btids = (BTID *) realloc (ptr->btids, size * sizeof (BTID));
2159  ptr->max_btids = size;
2160  }
2161  }
2162  }
2163 
2164  if (ptr->btids)
2165  {
2166  ptr->btids[ptr->n_btids] = *id;
2167  ptr->n_btids += 1;
2168  }
2169  else
2170  {
2171  success = 0;
2172  }
2173  }
2174 
2175  return success;
2176 }
2177 
2178 /*
2179  * or_install_btids_constraint () - Install the constraint into the appropriate
2180  * attributes
2181  * return:
2182  * rep(in): Class representation
2183  * constraint_seq(in): Constraint
2184  * type(in):
2185  * cons_name(in):
2186  *
2187  * Note: The constraint may be associated with multiple attributes.
2188  * The form of the constraint is:
2189  *
2190  * {btid, [attribute_ID, asc_desc]+ {fk_info}, comment}
2191  */
2192 static void
2193 or_install_btids_constraint (OR_CLASSREP * rep, DB_SEQ * constraint_seq, BTREE_TYPE type, const char *cons_name)
2194 {
2195  int att_id;
2196  int i, seq_size, args;
2197  int volid, fileid, pageid;
2198  BTID id;
2199  DB_VALUE id_val, att_val;
2200 
2201  /* Extract the first element of the sequence which is the encoded B-tree ID */
2202  /* { btid, [attrID, asc_desc]+, {fk_info} or {key prefix length}, status, comment} */
2203  seq_size = set_size (constraint_seq);
2204 
2205  if (set_get_element_nocopy (constraint_seq, 0, &id_val) != NO_ERROR)
2206  {
2207  return;
2208  }
2209 
2210  if (DB_VALUE_TYPE (&id_val) != DB_TYPE_STRING || db_get_string (&id_val) == NULL)
2211  {
2212  return;
2213  }
2214 
2215  args = classobj_decompose_property_oid (db_get_string (&id_val), &volid, &fileid, &pageid);
2216 
2217  if (args != 3)
2218  {
2219  return;
2220  }
2221 
2222  /*
2223  * Assign the B-tree ID.
2224  * For the first attribute name in the constraint,
2225  * cache the constraint in the attribute.
2226  */
2227  id.vfid.volid = (VOLID) volid;
2228  id.root_pageid = (PAGEID) pageid;
2229  id.vfid.fileid = (FILEID) fileid;
2230 
2231  i = 1;
2232  if (set_get_element_nocopy (constraint_seq, i, &att_val) == NO_ERROR)
2233  {
2234  assert (DB_VALUE_TYPE (&att_val) == DB_TYPE_INTEGER);
2235  att_id = db_get_int (&att_val); /* The first attrID */
2236  (void) or_install_btids_attribute (rep, att_id, &id);
2237  }
2238 
2239  /*
2240  * Assign the B-tree ID to the class.
2241  * Cache the constraint in the class with pointer to the attributes.
2242  * This is just a different way to store the BTID's.
2243  */
2244  or_install_btids_class (rep, &id, constraint_seq, seq_size, type, cons_name);
2245 }
2246 
2247 /*
2248  * or_install_btids () - Install the constraints found on the property list
2249  * into the class and attribute structures
2250  * return: void
2251  * rep(in): Class representation
2252  * props(in): Class property list
2253  */
2254 static void
2256 {
2264  };
2265 
2267  int i;
2268  int n_btids;
2269 
2270  /*
2271  * The first thing to do is to determine how many unique and index
2272  * BTIDs we have. We need this up front so that we can allocate
2273  * the OR_INDEX structure in the class (rep).
2274  */
2275  n_btids = 0;
2276  for (i = 0; i < SM_PROPERTY_NUM_INDEX_FAMILY; i++)
2277  {
2278  if (props != NULL && or_cl_get_prop_nocopy (props, property_vars[i].name, &vals[i]))
2279  {
2280  if (DB_VALUE_TYPE (&vals[i]) == DB_TYPE_SEQUENCE)
2281  {
2282  property_vars[i].seq = db_get_set (&vals[i]);
2283  }
2284 
2285  if (property_vars[i].seq)
2286  {
2287  property_vars[i].length = set_size (property_vars[i].seq);
2288  n_btids += property_vars[i].length;
2289  }
2290  }
2291  }
2292 
2293  n_btids /= 2;
2294 
2295  if (n_btids > 0)
2296  {
2297  rep->indexes = (OR_INDEX *) malloc (sizeof (OR_INDEX) * n_btids);
2298  if (rep->indexes == NULL)
2299  {
2301  return;
2302  }
2303  memset (rep->indexes, 0, sizeof (OR_INDEX) * n_btids);
2304  }
2305 
2306  /* Now extract the unique and index BTIDs from the property list and install them into the class and attribute
2307  * structures. */
2308  for (i = 0; i < SM_PROPERTY_NUM_INDEX_FAMILY; i++)
2309  {
2310  if (property_vars[i].seq)
2311  {
2312  int j;
2313  DB_VALUE ids_val, cons_name_val;
2314  DB_SEQ *ids_seq;
2315  const char *cons_name = NULL;
2316  int error = NO_ERROR;
2317 
2318  for (j = 0; j < property_vars[i].length && error == NO_ERROR; j += 2)
2319  {
2320  error = set_get_element_nocopy (property_vars[i].seq, j, &cons_name_val);
2321  if (error == NO_ERROR)
2322  {
2323  cons_name = db_get_string (&cons_name_val);
2324  }
2325 
2326  error = set_get_element_nocopy (property_vars[i].seq, j + 1, &ids_val);
2327  if (error == NO_ERROR && cons_name != NULL)
2328  {
2329  if (DB_VALUE_TYPE (&ids_val) == DB_TYPE_SEQUENCE)
2330  {
2331  ids_seq = db_get_set (&ids_val);
2332  or_install_btids_constraint (rep, ids_seq, property_vars[i].type, cons_name);
2333  }
2334  }
2335  }
2336  }
2337  }
2338 }
2339 
2340 /*
2341  * or_get_current_representation () - build an OR_CLASSREP structure for the
2342  * most recent representation
2343  * return: disk representation structure
2344  * record(in): disk record
2345  * do_indexes(in):
2346  *
2347  * Note: This is similar to the old function orc_diskrep_from_record, but is
2348  * a little simpler now that we don't need to maintain a separate
2349  * list for the fixed and variable length attributes.
2350  *
2351  * The logic is different from the logic in get_old_representation
2352  * because the structures used to hold the most recent representation
2353  * are different than the simplified structures used to hold the old
2354  * representations.
2355  */
2356 static OR_CLASSREP *
2357 or_get_current_representation (RECDES * record, int do_indexes)
2358 {
2359  OR_CLASSREP *rep;
2360  OR_ATTRIBUTE *att;
2361  OID oid;
2362  char *start, *ptr, *attset, *diskatt, *original_val_ptr, *dptr, *properties_val_ptr, *current_val_ptr;
2363  int i, start_offset, offset, original_val_len, n_fixed, n_variable, properties_val_len, current_val_len;
2364  int n_shared_attrs, n_class_attrs;
2365  OR_BUF buf;
2366  DB_VALUE properties_val, def_expr_op, def_expr, def_expr_type, def_expr_format;
2367  const char *def_expr_format_str = NULL;
2368  DB_SEQ *att_props = NULL, *def_expr_set = NULL;
2369 
2370  rep = (OR_CLASSREP *) malloc (sizeof (OR_CLASSREP));
2371  if (rep == NULL)
2372  {
2374  return NULL;
2375  }
2376 
2377  start = record->data;
2378 
2380 
2381  ptr = start + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
2382 
2383  rep->id = or_rep_id (record);
2385  rep->attributes = NULL;
2386  rep->shared_attrs = NULL;
2387  rep->class_attrs = NULL;
2388  rep->indexes = NULL;
2389 
2390  n_fixed = OR_GET_INT (ptr + ORC_FIXED_COUNT_OFFSET);
2391  n_variable = OR_GET_INT (ptr + ORC_VARIABLE_COUNT_OFFSET);
2392  n_shared_attrs = OR_GET_INT (ptr + ORC_SHARED_COUNT_OFFSET);
2393  n_class_attrs = OR_GET_INT (ptr + ORC_CLASS_ATTR_COUNT_OFFSET);
2394 
2395  rep->n_attributes = n_fixed + n_variable;
2396  rep->n_variable = n_variable;
2397  rep->n_shared_attrs = n_shared_attrs;
2398  rep->n_class_attrs = n_class_attrs;
2399  rep->n_indexes = 0;
2400 
2401  if (rep->n_attributes > 0)
2402  {
2403  rep->attributes = (OR_ATTRIBUTE *) malloc (sizeof (OR_ATTRIBUTE) * rep->n_attributes);
2404  if (rep->attributes == NULL)
2405  {
2407  sizeof (OR_ATTRIBUTE) * rep->n_attributes);
2408  goto error_cleanup;
2409  }
2410  memset (rep->attributes, 0, sizeof (OR_ATTRIBUTE) * rep->n_attributes);
2411  }
2412 
2413  if (rep->n_shared_attrs > 0)
2414  {
2415  rep->shared_attrs = (OR_ATTRIBUTE *) malloc (sizeof (OR_ATTRIBUTE) * rep->n_shared_attrs);
2416  if (rep->shared_attrs == NULL)
2417  {
2419  sizeof (OR_ATTRIBUTE) * rep->n_shared_attrs);
2420  goto error_cleanup;
2421  }
2422  memset (rep->shared_attrs, 0, sizeof (OR_ATTRIBUTE) * rep->n_shared_attrs);
2423  }
2424 
2425  if (rep->n_class_attrs > 0)
2426  {
2427  rep->class_attrs = (OR_ATTRIBUTE *) malloc (sizeof (OR_ATTRIBUTE) * rep->n_class_attrs);
2428  if (rep->class_attrs == NULL)
2429  {
2431  sizeof (OR_ATTRIBUTE) * rep->n_class_attrs);
2432  goto error_cleanup;
2433  }
2434  memset (rep->class_attrs, 0, sizeof (OR_ATTRIBUTE) * rep->n_class_attrs);
2435  }
2436 
2437 
2438  /* find the beginning of the "set_of(attribute)" attribute inside the class */
2439  attset = start + OR_VAR_OFFSET (start, ORC_ATTRIBUTES_INDEX);
2440 
2441  /* calculate the offset to the first fixed width attribute in instances of this class. */
2442  start_offset = offset = 0;
2443 
2444  for (i = 0, att = rep->attributes; i < rep->n_attributes; i++, att++)
2445  {
2446  /* diskatt will now be pointing at the offset table for this attribute. this is logically the "start" of this
2447  * nested object. */
2448  diskatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
2449 
2450  /* find out where the original default value is kept */
2451  original_val_ptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_ORIGINAL_VALUE_INDEX));
2452  original_val_len = OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_ORIGINAL_VALUE_INDEX);
2453 
2454  current_val_ptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_CURRENT_VALUE_INDEX));
2455  current_val_len = OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_CURRENT_VALUE_INDEX);
2456 
2457  properties_val_ptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_PROPERTIES_INDEX));
2458  properties_val_len = OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_PROPERTIES_INDEX);
2459 
2460  or_init (&buf, properties_val_ptr, properties_val_len);
2461 
2462  /* set ptr to the beginning of the fixed attributes */
2463  ptr = diskatt + OR_VAR_TABLE_SIZE (ORC_ATT_VAR_ATT_COUNT);
2464 
2466  {
2467  att->is_autoincrement = 1;
2468  }
2469  else
2470  {
2471  att->is_autoincrement = 0;
2472  }
2473 
2475  {
2476  att->is_notnull = 1;
2477  }
2478  else
2479  {
2480  att->is_notnull = 0;
2481  }
2482 
2483  att->type = (DB_TYPE) OR_GET_INT (ptr + ORC_ATT_TYPE_OFFSET);
2484  att->id = OR_GET_INT (ptr + ORC_ATT_ID_OFFSET);
2486  att->position = i;
2487  att->default_value.val_length = 0;
2488  att->default_value.value = NULL;
2491  OR_GET_OID (ptr + ORC_ATT_CLASS_OFFSET, &oid);
2492  att->classoid = oid;
2493 
2494  // *INDENT-OFF*
2495  new (&att->auto_increment.serial_obj) std::atomic<or_aligned_oid> (oid_Null_oid);
2496  // *INDENT-ON*
2497  /* get the btree index id if an index has been assigned */
2499 
2500  /* We won't know if there are any B-tree ID's for unique constraints until we read the class property list later
2501  * on */
2502  att->n_btids = 0;
2503  att->btids = NULL;
2504 
2505  /* Extract the full domain for this attribute, think about caching here it will add some time that may not be
2506  * necessary. */
2508  {
2509  /* shouldn't happen, fake one up from the type ! */
2510  att->domain = tp_domain_resolve_default (att->type);
2511  }
2512  else
2513  {
2514  dptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_DOMAIN_INDEX));
2515  att->domain = or_get_domain_and_cache (dptr);
2516  }
2517 
2518  if (i < n_fixed)
2519  {
2520  att->is_fixed = 1;
2521  att->location = offset;
2522  offset += tp_domain_disk_size (att->domain);
2523  }
2524  else
2525  {
2526  att->is_fixed = 0;
2527  att->location = i - n_fixed;
2528  }
2529 
2530  /* get the current default value - constant */
2531  if (current_val_len > 0)
2532  {
2533  if (or_get_current_default_value (att, current_val_ptr, current_val_len) == 0)
2534  {
2535  goto error_cleanup;
2536  }
2537  }
2538 
2539  /* get the default value - constant, this could be using a new DB_VALUE ? */
2540  if (original_val_len > 0)
2541  {
2542  if (or_get_default_value (att, original_val_ptr, original_val_len) == 0)
2543  {
2544  goto error_cleanup;
2545  }
2546  }
2547 
2548  /* get the default expression. */
2551  if (properties_val_len > 0)
2552  {
2553  db_make_null (&properties_val);
2554  db_make_null (&def_expr);
2555  db_make_null (&def_expr_op);
2556  db_make_null (&def_expr_format);
2557 
2558  or_get_value (&buf, &properties_val, tp_domain_resolve_default (DB_TYPE_SEQUENCE), properties_val_len, true);
2559  att_props = db_get_set (&properties_val);
2560 
2561  if (att_props != NULL && classobj_get_prop (att_props, "default_expr", &def_expr) > 0)
2562  {
2563  /* We have two cases: simple and complex expression. */
2564  if (DB_VALUE_TYPE (&def_expr) == DB_TYPE_SEQUENCE)
2565  {
2566  /*
2567  * We can't have an attribute with default expression and default value simultaneously. However,
2568  * in some situations attr->default_value.value contains the value of default expression. This happens
2569  * when the client executes the query on broker side and use attr->default_value.value to cache
2570  * the default expression value. Then the broker can modify the schema and send to server the default
2571  * expression and its cached value. Another option may be to clear default value on broker side,
2572  * but may lead to inconsistency.
2573  */
2574 
2575  /* Currently, we allow only (T_TO_CHAR(int), default_expr(int), default_expr_format(string)) */
2576  assert (set_size (db_get_set (&def_expr)) == 3);
2577 
2578  def_expr_set = db_get_set (&def_expr);
2579 
2580  /* get and cache default expression operator - op of expr */
2581  if (set_get_element_nocopy (def_expr_set, 0, &def_expr_op) != NO_ERROR)
2582  {
2583  assert (false);
2584  pr_clear_value (&def_expr);
2585  pr_clear_value (&properties_val);
2586  goto error_cleanup;
2587  }
2588  assert (DB_VALUE_TYPE (&def_expr_op) == DB_TYPE_INTEGER
2589  && db_get_int (&def_expr_op) == (int) T_TO_CHAR);
2590  att->default_value.default_expr.default_expr_op = db_get_int (&def_expr_op);
2592 
2593  /* get and cache default expression type - arg1 of expr */
2594  if (set_get_element_nocopy (def_expr_set, 1, &def_expr_type) != NO_ERROR)
2595  {
2596  assert (false);
2597  pr_clear_value (&def_expr);
2598  pr_clear_value (&properties_val);
2599  goto error_cleanup;
2600  }
2601  assert (DB_VALUE_TYPE (&def_expr_type) == DB_TYPE_INTEGER);
2603  (DB_DEFAULT_EXPR_TYPE) db_get_int (&def_expr_type);
2605  (DB_DEFAULT_EXPR_TYPE) db_get_int (&def_expr_type);
2606 
2607  /* get and cache default expression format - arg2 of expr */
2608  if (set_get_element_nocopy (def_expr_set, 2, &def_expr_format) != NO_ERROR)
2609  {
2610  assert (false);
2611  pr_clear_value (&def_expr);
2612  pr_clear_value (&properties_val);
2613  goto error_cleanup;
2614  }
2615 
2616  if (!db_value_is_null (&def_expr_format))
2617  {
2618 #if !defined (NDEBUG)
2619  DB_TYPE db_value_type_local = db_value_type (&def_expr_format);
2620  assert (db_value_type_local == DB_TYPE_NULL || TP_IS_CHAR_TYPE (db_value_type_local));
2621 #endif
2622  def_expr_format_str = db_get_string (&def_expr_format);
2623  att->default_value.default_expr.default_expr_format = strdup (def_expr_format_str);
2624  att->current_default_value.default_expr.default_expr_format = strdup (def_expr_format_str);
2625  }
2626  }
2627  else
2628  {
2629  /* simple expressions like SYS_DATE */
2630  assert (DB_VALUE_TYPE (&def_expr) == DB_TYPE_INTEGER);
2631 
2634  (DB_DEFAULT_EXPR_TYPE) db_get_int (&def_expr);
2635  }
2636  }
2637  pr_clear_value (&def_expr);
2638 
2639  if (att_props != NULL && classobj_get_prop (att_props, "update_default", &def_expr) > 0)
2640  {
2641  /* simple expressions like SYS_DATE */
2642  assert (DB_VALUE_TYPE (&def_expr) == DB_TYPE_INTEGER);
2643  att->on_update_expr = (DB_DEFAULT_EXPR_TYPE) db_get_int (&def_expr);
2644  }
2645 
2646  pr_clear_value (&def_expr);
2647  pr_clear_value (&properties_val);
2648  }
2649  }
2650 
2651  /* find the beginning of the "set_of(shared attributes)" attribute inside the class */
2652  attset = start + OR_VAR_OFFSET (start, ORC_SHARED_ATTRS_INDEX);
2653 
2654  for (i = 0, att = rep->shared_attrs; i < rep->n_shared_attrs; i++, att++)
2655  {
2656  /* diskatt will now be pointing at the offset table for this attribute. this is logically the "start" of this
2657  * nested object. */
2658  diskatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
2659 
2660  /* find out where the current default value is kept */
2661  current_val_ptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_CURRENT_VALUE_INDEX));
2662  current_val_len = OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_CURRENT_VALUE_INDEX);
2663 
2664  /* set ptr to the beginning of the fixed attributes */
2665  ptr = diskatt + OR_VAR_TABLE_SIZE (ORC_ATT_VAR_ATT_COUNT);
2666 
2667  att->is_autoincrement = 0;
2669  {
2670  att->is_notnull = 1;
2671  }
2672  else
2673  {
2674  att->is_notnull = 0;
2675  }
2676 
2677  att->type = (DB_TYPE) OR_GET_INT (ptr + ORC_ATT_TYPE_OFFSET);
2678  att->id = OR_GET_INT (ptr + ORC_ATT_ID_OFFSET);
2680  att->position = i;
2681  att->default_value.val_length = 0;
2682  att->default_value.value = NULL;
2688 
2689  OR_GET_OID (ptr + ORC_ATT_CLASS_OFFSET, &oid);
2690  att->classoid = oid; /* structure copy */
2691 
2692  /* get the btree index id if an index has been assigned */
2694 
2695  /* there won't be any indexes or uniques for shared attrs */
2696  att->n_btids = 0;
2697  att->btids = NULL;
2698 
2699  /* Extract the full domain for this attribute, think about caching here it will add some time that may not be
2700  * necessary. */
2702  {
2703  /* shouldn't happen, fake one up from the type ! */
2704  att->domain = tp_domain_resolve_default (att->type);
2705  }
2706  else
2707  {
2708  dptr = diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_DOMAIN_INDEX);
2709  att->domain = or_get_domain_and_cache (dptr);
2710  }
2711 
2712  att->is_fixed = 0;
2713  att->location = 0;
2714 
2715  /* get the default value, it is the container for the shared value */
2716  if (current_val_len > 0)
2717  {
2718  if (or_get_default_value (att, current_val_ptr, current_val_len) == 0)
2719  {
2720  goto error_cleanup;
2721  }
2722 
2723  if (att->default_value.val_length > 0)
2724  {
2725  att->current_default_value.value = malloc (att->default_value.val_length);
2726  if (att->current_default_value.value == NULL)
2727  {
2728  goto error_cleanup;
2729  }
2730 
2733  }
2734  }
2735  }
2736 
2737  /* find the beginning of the "set_of(class_attrs)" attribute inside the class */
2738  attset = start + OR_VAR_OFFSET (start, ORC_CLASS_ATTRS_INDEX);
2739 
2740  for (i = 0, att = rep->class_attrs; i < rep->n_class_attrs; i++, att++)
2741  {
2742  /* diskatt will now be pointing at the offset table for this attribute. this is logically the "start" of this
2743  * nested object. */
2744  diskatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
2745 
2746  /* find out where the current default value is kept */
2747  current_val_ptr = (diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_CURRENT_VALUE_INDEX));
2748  current_val_len = OR_VAR_TABLE_ELEMENT_LENGTH (diskatt, ORC_ATT_CURRENT_VALUE_INDEX);
2749 
2750  /* set ptr to the beginning of the fixed attributes */
2751  ptr = diskatt + OR_VAR_TABLE_SIZE (ORC_ATT_VAR_ATT_COUNT);
2752 
2753  att->is_autoincrement = 0;
2754  att->is_notnull = 0;
2755 
2756  att->type = (DB_TYPE) OR_GET_INT (ptr + ORC_ATT_TYPE_OFFSET);
2757  att->id = OR_GET_INT (ptr + ORC_ATT_ID_OFFSET);
2759  att->position = i;
2760  att->default_value.val_length = 0;
2761  att->default_value.value = NULL;
2767  OR_GET_OID (ptr + ORC_ATT_CLASS_OFFSET, &oid);
2768  att->classoid = oid;
2769 
2770  /* get the btree index id if an index has been assigned */
2772 
2773  /* there won't be any indexes or uniques for shared attrs */
2774  att->n_btids = 0;
2775  att->btids = NULL;
2776 
2777  /* Extract the full domain for this attribute, think about caching here it will add some time that may not be
2778  * necessary. */
2780  {
2781  /* shouldn't happen, fake one up from the type ! */
2782  att->domain = tp_domain_resolve_default (att->type);
2783  }
2784  else
2785  {
2786  dptr = diskatt + OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, ORC_ATT_DOMAIN_INDEX);
2787  att->domain = or_get_domain_and_cache (dptr);
2788  }
2789 
2790  att->is_fixed = 0;
2791  att->location = 0;
2792 
2793  /* get the default value, it is the container for the class attr value */
2794  if (current_val_len > 0)
2795  {
2796  if (or_get_default_value (att, current_val_ptr, current_val_len) == 0)
2797  {
2798  goto error_cleanup;
2799  }
2800  if (att->default_value.val_length > 0)
2801  {
2802  att->current_default_value.value = malloc (att->default_value.val_length);
2803  if (att->current_default_value.value == NULL)
2804  {
2805  goto error_cleanup;
2806  }
2807 
2810  }
2811  }
2812  }
2813 
2814  /* Read the B-tree IDs from the class property list */
2815  if (do_indexes)
2816  {
2817  char *propptr;
2818  DB_SET *props;
2819 
2820  if (!OR_VAR_IS_NULL (record->data, ORC_PROPERTIES_INDEX))
2821  {
2822  propptr = record->data + OR_VAR_OFFSET (record->data, ORC_PROPERTIES_INDEX);
2823  (void) or_unpack_setref (propptr, &props);
2824  or_install_btids (rep, props);
2825  db_set_free (props);
2826  }
2827  rep->needs_indexes = 0;
2828  }
2829  else
2830  {
2831  rep->needs_indexes = 1;
2832  }
2833 
2834  if (OR_VAR_IS_NULL (record->data, ORC_PARTITION_INDEX))
2835  {
2836  rep->has_partition_info = 0;
2837  }
2838  else
2839  {
2840  rep->has_partition_info = 1;
2841  }
2842 
2843  return rep;
2844 
2845 error_cleanup:
2846 
2847  if (rep->attributes)
2848  {
2849  free_and_init (rep->attributes);
2850  }
2851 
2852  if (rep->shared_attrs)
2853  {
2854  free_and_init (rep->shared_attrs);
2855  }
2856 
2857  if (rep->class_attrs)
2858  {
2859  free_and_init (rep->class_attrs);
2860  }
2861 
2862  free_and_init (rep);
2863 
2864  return NULL;
2865 }
2866 
2867 /*
2868  * or_get_old_representation () - Extracts the description of an old
2869  * representation from the disk image of a
2870  * class
2871  * return:
2872  * record(in): record with class diskrep
2873  * repid(in): representation id to extract
2874  * do_indexes(in):
2875  *
2876  * Note: It is similar to get_current_representation
2877  * except that it must get its information out of the compressed
2878  * SM_REPRESENTATION & SM_REPR_ATTRIBUTE structures which are used for
2879  * storing the old representations. The current representation is stored
2880  * in top-level SM_ATTRIBUTE structures which are much larger.
2881  *
2882  * If repid is -1 here, it returns the current representation.
2883  * It returns NULL on error. This can happen during memory allocation
2884  * failure but is more likely to happen if the repid given was not
2885  * found within the class.
2886  */
2887 static OR_CLASSREP *
2888 or_get_old_representation (RECDES * record, int repid, int do_indexes)
2889 {
2890  OR_CLASSREP *rep;
2891  OR_ATTRIBUTE *att;
2892  char *repset, *disk_rep, *attset, *repatt, *dptr;
2893  int rep_count, i, n_fixed, n_variable, offset, start, id;
2894  char *fixed = NULL;
2895 
2896  if (repid == NULL_REPRID)
2897  {
2898  return or_get_current_representation (record, do_indexes);
2899  }
2900 
2901  /* find the beginning of the "set_of(representation)" attribute inside the class. If this attribute is NULL, we're
2902  * missing the representations, its an error. */
2904  {
2905  return NULL;
2906  }
2907 
2909 
2910  repset = (record->data + OR_VAR_OFFSET (record->data, ORC_REPRESENTATIONS_INDEX));
2911 
2912  /* repset now points to the beginning of a complex set representation, find out how many elements are in the set. */
2913  rep_count = OR_SET_ELEMENT_COUNT (repset);
2914 
2915  /* locate the beginning of the representation in this set whose id matches the given repid. */
2916  disk_rep = NULL;
2917  for (i = 0; i < rep_count; i++)
2918  {
2919  /* set disk_rep to the beginning of the i'th set element */
2920  disk_rep = repset + OR_SET_ELEMENT_OFFSET (repset, i);
2921 
2922  /* move ptr up to the beginning of the fixed width attributes in this object */
2923  fixed = disk_rep + OR_VAR_TABLE_SIZE (ORC_REP_VAR_ATT_COUNT);
2924 
2925  /* extract the id of this representation */
2926  id = OR_GET_INT (fixed + ORC_REP_ID_OFFSET);
2927 
2928  if (id == repid)
2929  {
2930  break;
2931  }
2932  else
2933  {
2934  disk_rep = NULL;
2935  }
2936  }
2937 
2938  if (disk_rep == NULL)
2939  {
2941  return NULL;
2942  }
2943 
2944  /* allocate a new memory structure for this representation */
2945  rep = (OR_CLASSREP *) malloc (sizeof (OR_CLASSREP));
2946  if (rep == NULL)
2947  {
2948  return NULL;
2949  }
2950 
2951  rep->attributes = NULL;
2952  rep->shared_attrs = NULL;
2953  rep->class_attrs = NULL;
2954  rep->indexes = NULL;
2955 
2956  /* at this point, disk_rep points to the beginning of the representation object and "fixed" points at the first fixed
2957  * width attribute. */
2958 
2959  n_fixed = OR_GET_INT (fixed + ORC_REP_FIXED_COUNT_OFFSET);
2960  n_variable = OR_GET_INT (fixed + ORC_REP_VARIABLE_COUNT_OFFSET);
2961 
2962  rep->id = repid;
2963  rep->fixed_length = 0;
2964  rep->n_attributes = n_fixed + n_variable;
2965  rep->n_variable = n_variable;
2966  rep->n_indexes = 0;
2967 
2968  if (!rep->n_attributes)
2969  {
2970  /* its an empty representation, return it */
2971  return rep;
2972  }
2973 
2974  rep->attributes = (OR_ATTRIBUTE *) malloc (sizeof (OR_ATTRIBUTE) * rep->n_attributes);
2975  if (rep->attributes == NULL)
2976  {
2977  free_and_init (rep);
2978  return NULL;
2979  }
2980  memset (rep->attributes, 0, sizeof (OR_ATTRIBUTE) * rep->n_attributes);
2981 
2982  /* Calculate the beginning of the set_of(rep_attribute) in the representation object. Assume that the start of the
2983  * disk_rep points directly at the the substructure's variable offset table (which it does) and use
2984  * OR_VAR_TABLE_ELEMENT_OFFSET. */
2985  attset = disk_rep + OR_VAR_TABLE_ELEMENT_OFFSET (disk_rep, ORC_REP_ATTRIBUTES_INDEX);
2986 
2987  /* Calculate the offset to the first fixed width attribute in instances of this class. Save the start of this region
2988  * so we can calculate the total fixed witdh size. */
2989  start = offset = 0;
2990 
2991  /* build up the attribute descriptions */
2992  for (i = 0, att = rep->attributes; i < rep->n_attributes; i++, att++)
2993  {
2994  /* set repatt to the beginning of the rep_attribute object in the set */
2995  repatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
2996 
2997  /* set fixed to the beginning of the fixed width attributes for this object */
2998  fixed = repatt + OR_VAR_TABLE_SIZE (ORC_REPATT_VAR_ATT_COUNT);
2999 
3000  att->id = OR_GET_INT (fixed + ORC_REPATT_ID_OFFSET);
3001  att->type = (DB_TYPE) OR_GET_INT (fixed + ORC_REPATT_TYPE_OFFSET);
3002  att->position = i;
3003  att->default_value.val_length = 0;
3004  att->default_value.value = NULL;
3009 
3010  /* We won't know if there are any B-tree ID's for unique constraints until we read the class property list later
3011  * on */
3012  att->n_btids = 0;
3013  att->btids = NULL;
3014 
3015  /* not currently available, will this be a problem ? */
3016  OID_SET_NULL (&(att->classoid));
3017  BTID_SET_NULL (&(att->index));
3018 
3019  /* Extract the full domain for this attribute, think about caching here it will add some time that may not be
3020  * necessary. */
3022  {
3023  /* shouldn't happen, fake one up from the type ! */
3024  att->domain = tp_domain_resolve_default (att->type);
3025  }
3026  else
3027  {
3028  dptr = repatt + OR_VAR_TABLE_ELEMENT_OFFSET (repatt, ORC_REPATT_DOMAIN_INDEX);
3029  att->domain = or_get_domain_and_cache (dptr);
3030  }
3031 
3032  if (i < n_fixed)
3033  {
3034  att->is_fixed = 1;
3035  att->location = offset;
3036  offset += tp_domain_disk_size (att->domain);
3037  }
3038  else
3039  {
3040  att->is_fixed = 0;
3041  att->location = i - n_fixed;
3042  }
3043  }
3044 
3045  /* Offset at this point contains the total fixed size of the representation plus the starting offset, remove the
3046  * starting offset to get the length of just the fixed width attributes. */
3047  /* must align up to a word boundar ! */
3048  rep->fixed_length = DB_ATT_ALIGN (offset - start);
3049 
3050  /* Read the B-tree IDs from the class property list */
3051  if (do_indexes)
3052  {
3053  char *propptr;
3054  DB_SET *props;
3055 
3056  if (!OR_VAR_IS_NULL (record->data, ORC_PROPERTIES_INDEX))
3057  {
3058  propptr = record->data + OR_VAR_OFFSET (record->data, ORC_PROPERTIES_INDEX);
3059  (void) or_unpack_setref (propptr, &props);
3060  or_install_btids (rep, props);
3061  db_set_free (props);
3062  }
3063  rep->needs_indexes = 0;
3064  }
3065  else
3066  {
3067  rep->needs_indexes = 1;
3068  }
3069 
3070  if (OR_VAR_IS_NULL (record->data, ORC_PARTITION_INDEX))
3071  {
3072  rep->has_partition_info = 0;
3073  }
3074  else
3075  {
3076  rep->has_partition_info = 1;
3077  }
3078 
3079  return rep;
3080 }
3081 
3082 /*
3083  * or_get_all_representation () - Extracts the description of all
3084  * representation from the disk image of a
3085  * class.
3086  * return:
3087  * record(in): record with class diskrep
3088  * count(out): the number of representation to be returned
3089  * do_indexes(in):
3090  */
3091 OR_CLASSREP **
3092 or_get_all_representation (RECDES * record, bool do_indexes, int *count)
3093 {
3094  OR_ATTRIBUTE *att;
3095  OR_CLASSREP *rep, **rep_arr = NULL;
3096  char *repset = NULL, *disk_rep, *attset, *repatt, *dptr, *fixed = NULL;
3097  int old_rep_count = 0, i, j, offset, start, n_variable, n_fixed;
3098 
3099  if (count)
3100  {
3101  *count = 0;
3102  }
3103 
3105 
3107  {
3108  repset = (record->data + OR_VAR_OFFSET (record->data, ORC_REPRESENTATIONS_INDEX));
3109  old_rep_count = OR_SET_ELEMENT_COUNT (repset);
3110  }
3111 
3112  /* add one for current representation */
3113  rep_arr = (OR_CLASSREP **) malloc (sizeof (OR_CLASSREP *) * (old_rep_count + 1));
3114  if (rep_arr == NULL)
3115  {
3117  (sizeof (OR_CLASSREP *) * (old_rep_count + 1)));
3118  return NULL;
3119  }
3120 
3121  memset (rep_arr, 0x0, sizeof (OR_CLASSREP *) * (old_rep_count + 1));
3122 
3123  /* current representation */
3124  rep_arr[0] = or_get_current_representation (record, 1);
3125  if (rep_arr[0] == NULL)
3126  {
3127  goto error;
3128  }
3129 
3130  disk_rep = NULL;
3131  for (i = 0; i < old_rep_count && repset != NULL; i++)
3132  {
3133  rep_arr[i + 1] = (OR_CLASSREP *) malloc (sizeof (OR_CLASSREP));
3134  if (rep_arr[i + 1] == NULL)
3135  {
3137  goto error;
3138  }
3139  rep = rep_arr[i + 1];
3140 
3141  /* set disk_rep to the beginning of the i'th set element */
3142  disk_rep = repset + OR_SET_ELEMENT_OFFSET (repset, i);
3143 
3144  /* move ptr up to the beginning of the fixed width attributes in this object */
3145  fixed = disk_rep + OR_VAR_TABLE_SIZE (ORC_REP_VAR_ATT_COUNT);
3146 
3147  /* extract the id of this representation */
3148  rep->id = OR_GET_INT (fixed + ORC_REP_ID_OFFSET);
3149 
3150  n_fixed = OR_GET_INT (fixed + ORC_REP_FIXED_COUNT_OFFSET);
3151  n_variable = OR_GET_INT (fixed + ORC_REP_VARIABLE_COUNT_OFFSET);
3152 
3153  rep->n_variable = n_variable;
3154  rep->n_attributes = n_fixed + n_variable;
3155  rep->n_indexes = 0;
3156  rep->n_shared_attrs = 0;
3157  rep->n_class_attrs = 0;
3158  rep->fixed_length = 0;
3159 
3160  rep->next = NULL;
3161  rep->attributes = NULL;
3162  rep->shared_attrs = NULL;
3163  rep->class_attrs = NULL;
3164  rep->indexes = NULL;
3165 
3166  if (rep->n_attributes == 0)
3167  {
3168  continue;
3169  }
3170 
3171  rep->attributes = (OR_ATTRIBUTE *) malloc (sizeof (OR_ATTRIBUTE) * rep->n_attributes);
3172  if (rep->attributes == NULL)
3173  {
3175  (sizeof (OR_ATTRIBUTE) * rep->n_attributes));
3176  goto error;
3177  }
3178  memset (rep->attributes, 0, sizeof (OR_ATTRIBUTE) * rep->n_attributes);
3179 
3180  /* Calculate the beginning of the set_of(rep_attribute) in the representation object. Assume that the start of
3181  * the disk_rep points directly at the the substructure's variable offset table (which it does) and use
3182  * OR_VAR_TABLE_ELEMENT_OFFSET. */
3183  attset = disk_rep + OR_VAR_TABLE_ELEMENT_OFFSET (disk_rep, ORC_REP_ATTRIBUTES_INDEX);
3184 
3185  /* Calculate the offset to the first fixed width attribute in instances of this class. Save the start of this
3186  * region so we can calculate the total fixed width size. */
3187  start = offset = 0;
3188 
3189  /* build up the attribute descriptions */
3190  for (j = 0, att = rep->attributes; j < rep->n_attributes; j++, att++)
3191  {
3192  /* set repatt to the beginning of the rep_attribute object in the set */
3193  repatt = attset + OR_SET_ELEMENT_OFFSET (attset, j);
3194 
3195  /* set fixed to the beginning of the fixed width attributes for this object */
3196  fixed = repatt + OR_VAR_TABLE_SIZE (ORC_REPATT_VAR_ATT_COUNT);
3197 
3198  att->id = OR_GET_INT (fixed + ORC_REPATT_ID_OFFSET);
3199  att->type = (DB_TYPE) OR_GET_INT (fixed + ORC_REPATT_TYPE_OFFSET);
3200  att->position = j;
3201  att->default_value.val_length = 0;
3202  att->default_value.value = NULL;
3207 
3208  /* We won't know if there are any B-tree ID's for unique constraints until we read the class property list
3209  * later on */
3210  att->n_btids = 0;
3211  att->btids = NULL;
3212 
3213  /* not currently available, will this be a problem ? */
3214  OID_SET_NULL (&(att->classoid));
3215  BTID_SET_NULL (&(att->index));
3216 
3217  /* Extract the full domain for this attribute, think about caching here it will add some time that may not be
3218  * necessary. */
3220  {
3221  /* shouldn't happen, fake one up from the type ! */
3222  att->domain = tp_domain_resolve_default (att->type);
3223  }
3224  else
3225  {
3226  dptr = repatt + OR_VAR_TABLE_ELEMENT_OFFSET (repatt, ORC_REPATT_DOMAIN_INDEX);
3227  att->domain = or_get_domain_and_cache (dptr);
3228  }
3229 
3230  if (j < n_fixed)
3231  {
3232  att->is_fixed = 1;
3233  att->location = offset;
3234  offset += tp_domain_disk_size (att->domain);
3235  }
3236  else
3237  {
3238  att->is_fixed = 0;
3239  att->location = j - n_fixed;
3240  }
3241  }
3242 
3243  /* Offset at this point contains the total fixed size of the representation plus the starting offset, remove the
3244  * starting offset to get the length of just the fixed width attributes. */
3245  /* must align up to a word boundar ! */
3246  rep->fixed_length = DB_ATT_ALIGN (offset - start);
3247 
3248  /* Read the B-tree IDs from the class property list */
3249  if (do_indexes)
3250  {
3251  char *propptr;
3252  DB_SET *props;
3253 
3254  if (!OR_VAR_IS_NULL (record->data, ORC_PROPERTIES_INDEX))
3255  {
3256  propptr = record->data + OR_VAR_OFFSET (record->data, ORC_PROPERTIES_INDEX);
3257  (void) or_unpack_setref (propptr, &props);
3258  or_install_btids (rep, props);
3259  db_set_free (props);
3260  }
3261  rep->needs_indexes = 0;
3262  }
3263  else
3264  {
3265  rep->needs_indexes = 1;
3266  }
3267 
3268  if (OR_VAR_IS_NULL (record->data, ORC_PARTITION_INDEX))
3269  {
3270  rep->has_partition_info = 0;
3271  }
3272  else
3273  {
3274  rep->has_partition_info = 1;
3275  }
3276  }
3277 
3278  if (count)
3279  {
3280  *count = old_rep_count + 1;
3281  }
3282  return rep_arr;
3283 
3284 error:
3285  for (i = 0; i < old_rep_count + 1; i++)
3286  {
3287  or_free_classrep (rep_arr[i]);
3288  }
3289  free_and_init (rep_arr);
3290 
3291  return NULL;
3292 }
3293 
3294 /*
3295  * or_get_classrep () - builds an in-memory OR_CLASSREP that describes the
3296  * class
3297  * return: OR_CLASSREP structure
3298  * record(in): disk record
3299  * repid(in): representation of interest (-1) for current
3300  *
3301  * Note: This structure is in turn used to navigate over the instances of this
3302  * class stored in the heap.
3303  * It calls either get_current_representation or get_old_representation
3304  * to do the work.
3305  */
3306 OR_CLASSREP *
3307 or_get_classrep (RECDES * record, int repid)
3308 {
3309  OR_CLASSREP *rep;
3310  int current;
3311 
3313 
3314  if (repid == NULL_REPRID)
3315  {
3316  rep = or_get_current_representation (record, 1);
3317  }
3318  else
3319  {
3320  /* find out what the most recent representation is */
3321  current = or_rep_id (record);
3322 
3323  if (current == repid)
3324  {
3325  rep = or_get_current_representation (record, 1);
3326  }
3327  else
3328  {
3329  rep = or_get_old_representation (record, repid, 1);
3330  }
3331  }
3332 
3333  return rep;
3334 }
3335 
3336 /*
3337  * or_get_classrep_noindex () -
3338  * return:
3339  * record(in):
3340  * repid(in):
3341  */
3342 OR_CLASSREP *
3343 or_get_classrep_noindex (RECDES * record, int repid)
3344 {
3345  OR_CLASSREP *rep;
3346  int current;
3347 
3349 
3350  if (repid == NULL_REPRID)
3351  {
3352  rep = or_get_current_representation (record, 0);
3353  }
3354  else
3355  {
3356  /* find out what the most recent representation is */
3357  current = or_rep_id (record);
3358 
3359  if (current == repid)
3360  {
3361  rep = or_get_current_representation (record, 0);
3362  }
3363  else
3364  {
3365  rep = or_get_old_representation (record, repid, 0);
3366  }
3367  }
3368  return rep;
3369 }
3370 
3371 /*
3372  * or_classrep_load_indexes () -
3373  * return:
3374  * rep(in):
3375  * record(in):
3376  */
3377 OR_CLASSREP *
3379 {
3380  REPR_ID id;
3381 
3382  /* eventually could be smarter about trying to reuse the existing structure. */
3383  if (rep->needs_indexes)
3384  {
3385  id = rep->id;
3386  or_free_classrep (rep);
3387  rep = or_get_classrep (record, id);
3388  }
3389 
3390  return rep;
3391 }
3392 
3393 /*
3394  * or_class_get_partition_info () - Get partition information from a record
3395  * descriptor of a class record
3396  * return : error code or NO_ERROR
3397  * record (in) : record descriptor
3398  * partition_info (in/out): partition information
3399  * repr_id (in/out): representation id from record
3400  * has_partition_info (out): whether this class has partition information or not
3401  *
3402  * Note: This function extracts the partition information from a class record.
3403  *
3404  * If the class is not a partition or is not a partitioned class,
3405  * has_partition_info will have the value zero.
3406  */
3407 int
3408 or_class_get_partition_info (RECDES * record, OR_PARTITION * partition_info, REPR_ID * repr_id, int *has_partition_info)
3409 {
3410  char *partition_ptr = NULL, *ptr = NULL;
3411  OR_BUF buf;
3412  DB_VALUE val;
3413 
3414  assert (record != NULL);
3415  assert (partition_info != NULL);
3416  assert (repr_id != NULL);
3417  assert (has_partition_info != NULL);
3418 
3419  *has_partition_info = 0;
3420  *repr_id = or_rep_id (record);
3421 
3422  if (OR_VAR_IS_NULL (record->data, ORC_PARTITION_INDEX))
3423  {
3424  return NO_ERROR;
3425  }
3426 
3427  partition_ptr = (char *) (record->data) + OR_VAR_OFFSET (record->data, ORC_PARTITION_INDEX);
3428 
3429  partition_ptr += OR_SET_ELEMENT_OFFSET (partition_ptr, 0);
3430 
3431  /* set ptr to the beginning of the fixed attributes */
3432  ptr = partition_ptr + OR_VAR_TABLE_SIZE (ORC_PARTITION_VAR_ATT_COUNT);
3433 
3434  partition_info->partition_type = OR_GET_INT (ptr);
3435 
3436  or_init (&buf, partition_ptr + OR_VAR_TABLE_ELEMENT_OFFSET (partition_ptr, ORC_PARTITION_VALUES_INDEX),
3438  if (or_get_value (&buf, &val, NULL, CAST_BUFLEN (buf.endptr - buf.ptr), true) != NO_ERROR)
3439  {
3440  return ER_FAILED;
3441  }
3442  partition_info->values = db_seq_copy (db_get_set (&val));
3443  if (partition_info->values == NULL)
3444  {
3445  pr_clear_value (&val);
3446  return ER_FAILED;
3447  }
3448 
3449  pr_clear_value (&val);
3450 
3451  or_class_hfid (record, &partition_info->class_hfid);
3452  partition_info->rep_id = *repr_id;
3453  *has_partition_info = 1;
3454 
3455  return NO_ERROR;
3456 }
3457 
3458 /*
3459  * or_get_constraint_comment () - Get constraint/index comment from a record
3460  * descriptor of a class record
3461  * return : comment
3462  * record(in): record descriptor
3463  * constraint_name(in): constraint/index name
3464  *
3465  * Note: The "comment" returned is a duplicated string containing the comment string.
3466  * It's up to the caller to free the returned pointer.
3467  * If the given constraint/index name does not exist for current
3468  * representation, NULL is returned.
3469  */
3470 const char *
3471 or_get_constraint_comment (RECDES * record, const char *constraint_name)
3472 {
3473  int error = NO_ERROR;
3474  int i, j, len, info_len, num;
3475  char *subset, *comment = NULL;
3476  DB_SET *info, *props, *setref;
3477  DB_VALUE value, uvalue, cvalue;
3478  bool found = false;
3479 
3480  info = props = setref = NULL;
3481 
3482  if (OR_VAR_IS_NULL (record->data, ORC_PROPERTIES_INDEX))
3483  {
3484  return NULL;
3485  }
3486 
3487  subset = (char *) (record->data) + OR_VAR_OFFSET (record->data, ORC_PROPERTIES_INDEX);
3488 
3489  or_unpack_setref (subset, &setref);
3490  if (setref == NULL)
3491  {
3492  return NULL;
3493  }
3494 
3495  num = set_size (setref);
3496  for (i = 0; i < num && found == false; i += 2)
3497  {
3498  const char *prop_name = NULL;
3499  error = set_get_element_nocopy (setref, i, &value);
3500  if (error != NO_ERROR || DB_VALUE_TYPE (&value) != DB_TYPE_STRING)
3501  {
3502  goto error_exit;
3503  }
3504 
3505  prop_name = db_get_string (&value);
3506  if (prop_name == NULL)
3507  {
3508  goto error_exit;
3509  }
3510 
3511  if (strcmp (prop_name, SM_PROPERTY_PRIMARY_KEY) != 0 && strcmp (prop_name, SM_PROPERTY_UNIQUE) != 0
3512  && strcmp (prop_name, SM_PROPERTY_REVERSE_UNIQUE) != 0 && strcmp (prop_name, SM_PROPERTY_INDEX) != 0
3513  && strcmp (prop_name, SM_PROPERTY_REVERSE_INDEX) != 0 && strcmp (prop_name, SM_PROPERTY_FOREIGN_KEY) != 0)
3514  {
3515  continue;
3516  }
3517 
3518  error = set_get_element_nocopy (setref, i + 1, &value);
3519  if (error != NO_ERROR || DB_VALUE_TYPE (&value) != DB_TYPE_SEQUENCE)
3520  {
3521  goto error_exit;
3522  }
3523 
3524  /* this sequence is an alternating pair of constraint name & info sequence, as by: { name, { BTID, [att_name,
3525  * asc_dsc], {fk_info | pk_info | prefix_length}, filter_predicate, comment}, name, { BTID, [att_name, asc_dsc],
3526  * {fk_info | pk_info | prefix_length}, filter_predicate, comment}, ... } */
3527  props = db_get_set (&value);
3528  len = set_size (props);
3529  for (j = 0; j < len; j += 2)
3530  {
3531  /* get the name */
3532  if (set_get_element_nocopy (props, j, &uvalue) || DB_VALUE_TYPE (&uvalue) != DB_TYPE_STRING)
3533  {
3534  goto error_exit;
3535  }
3536 
3537  if (strcmp (constraint_name, db_get_string (&uvalue)) != 0)
3538  {
3539  continue;
3540  }
3541 
3542  found = true;
3543 
3544  if (set_get_element_nocopy (props, j + 1, &uvalue))
3545  {
3546  goto error_exit;
3547  }
3548  if (DB_VALUE_TYPE (&uvalue) != DB_TYPE_SEQUENCE)
3549  {
3550  goto error_exit;
3551  }
3552 
3553  info = db_get_set (&uvalue);
3554  info_len = set_size (info);
3555 
3556  if (set_get_element_nocopy (info, info_len - 1, &cvalue) || DB_IS_NULL (&cvalue))
3557  {
3558  /* if not exists, set comment to null */
3559  comment = NULL;
3560  }
3561  else if (DB_VALUE_TYPE (&cvalue) == DB_TYPE_STRING)
3562  {
3563  /* strdup, caller shall free it */
3564  const char *cvalue_string = db_get_string (&cvalue);
3565  comment = strdup (cvalue_string);
3566  }
3567  else
3568  {
3569  goto error_exit;
3570  }
3571  break;
3572  }
3573  }
3574 end:
3575  set_free (setref);
3576  return comment;
3577 
3578 error_exit:
3579  assert (false);
3580  goto end;
3581 }
3582 
3583 #if defined (ENABLE_UNUSED_FUNCTION)
3584 /*
3585  * or_classrep_needs_indexes () -
3586  * return:
3587  * rep(in):
3588  */
3589 int
3590 or_classrep_needs_indexes (OR_CLASSREP * rep)
3591 {
3592  return rep->needs_indexes;
3593 }
3594 #endif /* ENABLE_UNUSED_FUNCTION */
3595 
3596 /*
3597  * or_free_classrep () - Frees an OR_CLASSREP structure returned by
3598  * or_get_classrep
3599  * return: void
3600  * rep(in): representation structure
3601  */
3602 void
3604 {
3605  int i;
3606  OR_ATTRIBUTE *att;
3607  OR_INDEX *index;
3608  OR_FOREIGN_KEY *fk, *fk_next;
3609 
3610  if (rep == NULL)
3611  {
3612  return;
3613  }
3614 
3615  if (rep->attributes != NULL)
3616  {
3617  for (i = 0, att = rep->attributes; i < rep->n_attributes; i++, att++)
3618  {
3619  if (att->default_value.value != NULL)
3620  {
3622  }
3623 
3625  {
3627  }
3628 
3629  if (att->current_default_value.value != NULL)
3630  {
3632  }
3633 
3635  {
3637  }
3638 
3639  if (att->btids != NULL && att->btids != att->btid_pack)
3640  {
3641  free_and_init (att->btids);
3642  }
3643  }
3644  free_and_init (rep->attributes);
3645  }
3646 
3647  if (rep->shared_attrs != NULL)
3648  {
3649  for (i = 0, att = rep->shared_attrs; i < rep->n_shared_attrs; i++, att++)
3650  {
3651  if (att->default_value.value != NULL)
3652  {
3654  }
3655 
3657  {
3659  }
3660 
3661  if (att->current_default_value.value != NULL)
3662  {
3664  }
3665 
3667  {
3669  }
3670 
3671  if (att->btids != NULL && att->btids != att->btid_pack)
3672  {
3673  free_and_init (att->btids);
3674  }
3675  }
3676  free_and_init (rep->shared_attrs);
3677  }
3678 
3679  if (rep->class_attrs != NULL)
3680  {
3681  for (i = 0, att = rep->class_attrs; i < rep->n_class_attrs; i++, att++)
3682  {
3683  if (att->default_value.value != NULL)
3684  {
3686  }
3687 
3688  if (att->current_default_value.value != NULL)
3689  {
3691  }
3692 
3693  if (att->btids != NULL && att->btids != att->btid_pack)
3694  {
3695  free_and_init (att->btids);
3696  }
3697  }
3698  free_and_init (rep->class_attrs);
3699  }
3700 
3701  if (rep->indexes != NULL)
3702  {
3703  for (i = 0, index = rep->indexes; i < rep->n_indexes; i++, index++)
3704  {
3705  if (index->atts != NULL)
3706  {
3707  free_and_init (index->atts);
3708  }
3709 
3710  if (index->btname != NULL)
3711  {
3712  free_and_init (index->btname);
3713  }
3714 
3715  if (index->filter_predicate)
3716  {
3717  if (index->filter_predicate->pred_string)
3718  {
3720  }
3721 
3722  if (index->filter_predicate->pred_stream)
3723  {
3725  }
3726 
3728  }
3729 
3730  if (index->asc_desc != NULL)
3731  {
3732  free_and_init (index->asc_desc);
3733  }
3734 
3735  if (index->attrs_prefix_length != NULL)
3736  {
3738  }
3739 
3740  if (index->fk)
3741  {
3742  for (fk = index->fk; fk; fk = fk_next)
3743  {
3744  fk_next = fk->next;
3745  if (fk->fkname)
3746  {
3747  free_and_init (fk->fkname);
3748  }
3749  free_and_init (fk);
3750  }
3751  }
3752  if (index->func_index_info)
3753  {
3754  if (index->func_index_info->expr_string)
3755  {
3757  }
3758  if (index->func_index_info->expr_stream)
3759  {
3761  }
3762  free_and_init (index->func_index_info);
3763  }
3764  }
3765 
3766  free_and_init (rep->indexes);
3767  }
3768 
3769  free_and_init (rep);
3770 }
3771 
3772 /*
3773  * or_find_diskattr () - Find disk attribute in record by attr_id
3774  * return: a pointer to a disk attribute
3775  * record(in): disk record
3776  * attr_id(in): desired attribute id
3777  *
3778  * If the given attribute identifier does not exist for current
3779  * representation, NULL is returned.
3780  */
3781 static const char *
3782 or_find_diskattr (RECDES * record, int attr_id)
3783 {
3784  int n_fixed, n_variable, n_shared, n_class;
3785  int n_attrs;
3786  int type_attr, i, id;
3787  bool found;
3788  char *start, *ptr, *attset, *diskatt = NULL;
3789 
3790  start = record->data;
3791 
3793 
3794  ptr = start + OR_FIXED_ATTRIBUTES_OFFSET (record->data, ORC_CLASS_VAR_ATT_COUNT);
3795 
3796  n_fixed = OR_GET_INT (ptr + ORC_FIXED_COUNT_OFFSET);
3797  n_variable = OR_GET_INT (ptr + ORC_VARIABLE_COUNT_OFFSET);
3798  n_shared = OR_GET_INT (ptr + ORC_SHARED_COUNT_OFFSET);
3799  n_class = OR_GET_INT (ptr + ORC_CLASS_ATTR_COUNT_OFFSET);
3800 
3801  for (type_attr = 0, found = false; type_attr < 3 && found == false; type_attr++)
3802  {
3803  if (type_attr == 0)
3804  {
3805  /*
3806  * INSTANCE ATTRIBUTES
3807  *
3808  * find the start of the "set_of(attribute)" fix/variable attribute
3809  * list inside the class
3810  */
3811  attset = start + OR_VAR_OFFSET (start, ORC_ATTRIBUTES_INDEX);
3812  n_attrs = n_fixed + n_variable;
3813  }
3814  else if (type_attr == 1)
3815  {
3816  /*
3817  * SHARED ATTRIBUTES
3818  *
3819  * find the start of the "set_of(shared attributes)" attribute
3820  * list inside the class
3821  */
3822  attset = start + OR_VAR_OFFSET (start, ORC_SHARED_ATTRS_INDEX);
3823  n_attrs = n_shared;
3824  }
3825  else
3826  {
3827  /*
3828  * CLASS ATTRIBUTES
3829  *
3830  * find the start of the "set_of(class attributes)" attribute
3831  * list inside the class
3832  */
3833  attset = start + OR_VAR_OFFSET (start, ORC_CLASS_ATTRS_INDEX);
3834  n_attrs = n_class;
3835  }
3836 
3837  for (i = 0, found = false; i < n_attrs && found == false; i++)
3838  {
3839  /*
3840  * diskatt will now be pointing at the offset table for this attribute.
3841  * this is logically the "start" of this nested object.
3842  *
3843  * set ptr to the beginning of the fixed attributes
3844  */
3845  diskatt = attset + OR_SET_ELEMENT_OFFSET (attset, i);
3846  ptr = diskatt + OR_VAR_TABLE_SIZE (ORC_ATT_VAR_ATT_COUNT);
3847  id = OR_GET_INT (ptr + ORC_ATT_ID_OFFSET);
3848  if (id == attr_id)
3849  {
3850  found = true;
3851  }
3852  }
3853  }
3854 
3855  return found ? diskatt : NULL;
3856 }
3857 
3858 /*
3859  * or_get_attr_string () - Get the string of the given attribute (id,index)
3860  * return: NO_ERROR or error code.
3861  * record(in): disk record
3862  * attr_id(in): desired attribute id
3863  * attr_index(in): index to a string among the attribute
3864  * string(out) : The pointer towards the desire attribute.
3865  * alloced_string(out) : States whether the returned string was alloc'ed due do decompression,
3866  * or is just a pointer from the record.
3867  *
3868  * If the given attribute identifier does not exist for current
3869  * representation, NULL is returned.
3870  */
3871 int
3872 or_get_attr_string (RECDES * record, int attr_id, int attr_index, char **string, int *alloced_string)
3873 {
3874  char *diskatt, *attr = NULL;
3875  int offset = 0, offset_next = 0;
3876  unsigned char len = 0;
3877  OR_BUF buffer;
3878  int compressed_length = 0, decompressed_length = 0, rc = NO_ERROR;
3879 
3880  assert (*alloced_string == 0);
3881 
3882  assert (attr_index < ORC_ATT_LAST_INDEX);
3883 
3884  diskatt = (char *) or_find_diskattr (record, attr_id);
3885  if (diskatt != NULL)
3886  {
3887  /*
3888  * diskatt now points to the attribute that we are interested in.
3889  * Get the attribute name.
3890  */
3891  offset = OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, attr_index);
3892  attr = diskatt + offset;
3893 
3894  /*
3895  * Get boundary of the attribute, that is, the offset of next attribute.
3896  * Regardless the next attribute exists or not,
3897  * the "offset_next" is always retrievable.
3898  * There is a last offset to denote the end of object. See attribute_to_disk.
3899  */
3900  offset_next = OR_VAR_TABLE_ELEMENT_OFFSET (diskatt, attr_index + 1);
3901 
3902  /*
3903  * kludge kludge kludge
3904  * This is now an encoded "varchar" string, we need to skip over the
3905  * length before returning it. Note that this also depends on the
3906  * stored string being NULL terminated.
3907  */
3908  assert (attr != NULL);
3909  if (attr != NULL)
3910  {
3911  len = *((unsigned char *) attr);
3912  }
3913 
3914  if (offset == offset_next)
3915  {
3916  attr = NULL;
3917  *string = NULL;
3918  }
3919  else if (len < 0xFFU)
3920  {
3921  assert (len != 0);
3922  attr += 1;
3923  *string = attr;
3924  }
3925  else
3926  {
3927  OR_BUF_INIT (buffer, attr, -1);
3928 
3929  rc = or_get_varchar_compression_lengths (&buffer, &compressed_length, &decompressed_length);
3930  if (rc != NO_ERROR)
3931  {
3932  ASSERT_ERROR ();
3933  *string = NULL;
3934  return rc;
3935  }
3936 
3937  assert (*string == NULL);
3938  *string = (char *) db_private_alloc (NULL, decompressed_length + 1);
3939  if (*string == NULL)
3940  {
3941  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, decompressed_length + 1);
3942  return ER_OUT_OF_VIRTUAL_MEMORY;
3943  }
3944  *alloced_string = 1;
3945 
3946  rc = pr_get_compressed_data_from_buffer (&buffer, *string, compressed_length, decompressed_length);
3947  if (rc != NO_ERROR)
3948  {
3949  ASSERT_ERROR ();
3950  db_private_free (NULL, *string);
3951  *alloced_string = 0;
3952  *string = NULL;
3953  return rc;
3954  }
3955  }
3956  }
3957 
3958  return rc;
3959 }
3960 
3961 /*
3962  * or_get_attrname () - Find the name of the given attribute
3963  * return: the name of the attribute
3964  * record(in): disk record
3965  * attrid(in): desired attribute
3966  * string(out): Desired attribute name
3967  * alloced_string(out) : States whether the attribute name was alloc'ed or it is just a pointer.
3968  *
3969  * The name returned is the name of the actual representation.
3970  * If the given attribute identifier does not exist for current
3971  * representation, NULL is returned.
3972  */
3973 int
3974 or_get_attrname (RECDES * record, int attrid, char **string, int *alloced_string)
3975 {
3976  return or_get_attr_string (record, attrid, ORC_ATT_NAME_INDEX, string, alloced_string);
3977 }
3978 
3979 /*
3980  * or_get_attrcomment () - Find the comment of the given attribute
3981  * return: NO_ERROR or error code
3982  * record(in): disk record
3983  * attrid(in): desired attribute
3984  * string(out): Desired string
3985  * alloced_string(out) : States whether the string was alloc'ed due to decompression or it is just a pointer.
3986  *
3987  * Note: The comment returned is an actual pointer to the record structure
3988  * If the record is changed, the pointer may be trashed.
3989  * If the given attribute identifier does not exist for current
3990  * representation, NULL is returned.
3991  */
3992 int
3993 or_get_attrcomment (RECDES * record, int attrid, char **string, int *alloced_string)
3994 {
3995  return or_get_attr_string (record, attrid, ORC_ATT_COMMENT_INDEX, string, alloced_string);
3996 }
3997 
3998 /*
3999  * or_install_btids_function_info () - Install (add) function index
4000  * information to the index structure
4001  * of the class representation
4002  * return: void
4003  * index(in): index structure
4004  * fi_seq(in): Set which contains the function index information
4005  */
4006 static void
4008 {
4009  OR_FUNCTION_INDEX *fi_info = NULL;
4010  DB_VALUE val, val1;
4011  const char *buffer;
4012 
4013  index->func_index_info = NULL;
4014  if (fi_seq == NULL)
4015  {
4016  return;
4017  }
4018 
4019  if (set_get_element_nocopy (fi_seq, 0, &val1) != NO_ERROR)
4020  {
4022  goto error;
4023  }
4024 
4025  switch (DB_VALUE_TYPE (&val1))
4026  {
4027  case DB_TYPE_NULL:
4028  return;
4029 
4030  case DB_TYPE_STRING:
4031  /* continue */
4032  break;
4033 
4034  default:
4036  return;
4037  }
4038 
4039  if (set_get_element_nocopy (fi_seq, 1, &val) != NO_ERROR)
4040  {
4042  goto error;
4043  }
4044 
4045  switch (DB_VALUE_TYPE (&val))
4046  {
4047  case DB_TYPE_NULL:
4048  return;
4049 
4050  case DB_TYPE_CHAR:
4051  /* continue */
4052  break;
4053 
4054  default:
4056  return;
4057  }
4058 
4059 
4060  fi_info = (OR_FUNCTION_INDEX *) malloc (sizeof (OR_FUNCTION_INDEX));
4061  if (fi_info == NULL)
4062  {
4064  goto error;
4065  }
4066 
4067  fi_info->expr_string = strdup (db_get_string (&val1));
4068  if (fi_info->expr_string == NULL)
4069  {
4071  strlen (db_get_string (&val1)) * sizeof (char));
4072  goto error;
4073  }
4074 
4075  buffer = db_get_string (&val);
4076  fi_info->expr_stream_size = db_get_string_size (&val);
4077  fi_info->expr_stream = (char *) malloc (fi_info->expr_stream_size);
4078  if (fi_info->expr_stream == NULL)
4079  {
4081  goto error;
4082  }
4083  memcpy (fi_info->expr_stream, buffer, fi_info->expr_stream_size);
4084 
4085  if (set_get_element_nocopy (fi_seq, 2, &val) != NO_ERROR)
4086  {
4088  goto error;
4089  }
4090  fi_info->col_id = db_get_int (&val);
4091 
4092  if (set_get_element_nocopy (fi_seq, 3, &val) != NO_ERROR)
4093  {
4095  goto error;
4096  }
4097  fi_info->attr_index_start = db_get_int (&val);
4098 
4099  index->func_index_info = fi_info;
4100  return;
4101 
4102 error:
4103  if (fi_info)
4104  {
4105  if (fi_info->expr_string)
4106  {
4107  free_and_init (fi_info->expr_string);
4108  }
4109 
4110  if (fi_info->expr_stream)
4111  {
4112  free_and_init (fi_info->expr_stream);
4113  }
4114 
4115  free_and_init (fi_info);
4116  }
4117 
4118  return;
4119 }
4120 
4121 /*
4122  * or_replace_rep_id () - replace representation id for record
4123  * return : error code or NO_ERROR
4124  * record (in/out): record
4125  * repid (in) : new representation
4126  *
4127  * NOTE: This function is similar to or_set_rep_id but it determines
4128  * the type of record based on MVCC flag and sets rep_id accordingly.
4129  */
4130 int
4131 or_replace_rep_id (RECDES * record, int repid)
4132 {
4133  OR_BUF orep, *buf;
4134  unsigned int new_bits = 0;
4135  int offset_size = 0;
4136  char mvcc_flag;
4137  bool is_bound_bit = false;
4138 
4139  OR_BUF_INIT (orep, record->data, record->area_size);
4140  buf = &orep;
4141 
4142  mvcc_flag = or_mvcc_get_flag (record);
4143  if (mvcc_flag == 0)
4144  {
4145  /* non-MVCC record */
4146  /* read REPR_ID flags */
4147  if (OR_GET_BOUND_BIT_FLAG (record->data))
4148  {
4149  is_bound_bit = true;
4150  }
4151  offset_size = OR_GET_OFFSET_SIZE (record->data);
4152 
4153  /* construct new REPR_ID element */
4154  new_bits = repid;
4155  if (is_bound_bit)
4156  {
4157  new_bits |= OR_BOUND_BIT_FLAG;
4158  }
4159  OR_SET_VAR_OFFSET_SIZE (new_bits, offset_size);
4160  buf->ptr = buf->buffer + OR_REP_OFFSET;
4161  }
4162  else
4163  {
4164  /* MVCC record */
4165  new_bits = OR_GET_MVCC_REPID_AND_FLAG (record->data);
4166 
4167  /* Remove old repid */
4168  new_bits &= ~OR_MVCC_REPID_MASK;
4169 
4170  /* Add new repid */
4171  new_bits |= (repid & OR_MVCC_REPID_MASK);
4172 
4173  /* Set buffer pointer to the right position */
4174  buf->ptr = buf->buffer + OR_REP_OFFSET;
4175  }
4176 
4177  /* write new REPR_ID to the record */
4178  or_put_int (buf, new_bits);
4179 
4180  return NO_ERROR;
4181 }
4182 
4183 /*
4184  * or_mvcc_get_header () - Get mvcc record header from record data.
4185  *
4186  * return : Void.
4187  * record (in) : Record descriptor.
4188  * mvcc_header (out) : MVCC Record header.
4189  */
4190 int
4191 or_mvcc_get_header (RECDES * record, MVCC_REC_HEADER * mvcc_header)
4192 {
4193  OR_BUF buf;
4194  int rc = NO_ERROR;
4195  int repid_and_flag_bits;
4196 
4197  assert (record != NULL && record->data != NULL && record->length >= OR_MVCC_REP_SIZE && mvcc_header != NULL);
4198 
4199  or_init (&buf, record->data, record->length);
4200 
4201  repid_and_flag_bits = or_mvcc_get_repid_and_flags (&buf, &rc);
4202  if (rc != NO_ERROR)
4203  {
4204  goto exit_on_error;
4205  }
4206  mvcc_header->repid = repid_and_flag_bits & OR_MVCC_REPID_MASK;
4207  mvcc_header->mvcc_flag = (char) ((repid_and_flag_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
4208 
4209  mvcc_header->chn = or_mvcc_get_chn (&buf, &rc);
4210  if (rc != NO_ERROR)
4211  {
4212  goto exit_on_error;
4213  }
4214 
4215  mvcc_header->mvcc_ins_id = or_mvcc_get_insid (&buf, mvcc_header->mvcc_flag, &rc);
4216  if (rc != NO_ERROR)
4217  {
4218  goto exit_on_error;
4219  }
4220 
4221  mvcc_header->mvcc_del_id = or_mvcc_get_delid (&buf, mvcc_header->mvcc_flag, &rc);
4222  if (rc != NO_ERROR)
4223  {
4224  goto exit_on_error;
4225  }
4226 
4227  rc = or_mvcc_get_prev_version_lsa (&buf, mvcc_header->mvcc_flag, &(mvcc_header->prev_version_lsa));
4228  if (rc != NO_ERROR)
4229  {
4230  goto exit_on_error;
4231  }
4232 
4233  return NO_ERROR;
4234 
4235 exit_on_error:
4236  return (rc == NO_ERROR && (rc = er_errid ()) == NO_ERROR) ? ER_FAILED : rc;
4237 }
4238 
4239 /*
4240  * or_mvcc_set_header () - Updates record header
4241  *
4242  * return : Void.
4243  * record (in/out) : Record descriptor.
4244  * mvcc_rec_header (in) : MVCC Record header.
4245  *
4246  * Note: This function assume that record area size is sufficiently large
4247  * to include additional MVCC data that may come from mvcc_rec_header.
4248  */
4249 int
4251 {
4252  OR_BUF orep, *buf;
4253  int error = NO_ERROR;
4254  int mvcc_old_flag = 0;
4255  int repid_and_flag_bits = 0;
4256  int old_mvcc_size = 0, new_mvcc_size = 0;
4257 
4258  assert (record != NULL && record->data != NULL && record->length != 0 && record->length >= OR_MVCC_MIN_HEADER_SIZE);
4259 
4260  repid_and_flag_bits = OR_GET_MVCC_REPID_AND_FLAG (record->data);
4261 
4262  mvcc_old_flag = (char) ((repid_and_flag_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
4263 
4264  old_mvcc_size = mvcc_header_size_lookup[mvcc_old_flag];
4265  new_mvcc_size = mvcc_header_size_lookup[mvcc_rec_header->mvcc_flag];
4266  if (old_mvcc_size != new_mvcc_size)
4267  {
4268  /* resize MVCC info inside recdes */
4269  if (record->area_size < (record->length + new_mvcc_size - old_mvcc_size))
4270  {
4271  /* TO DO - er_set */
4272  assert (false);
4273  goto exit_on_error;
4274  }
4275 
4276  HEAP_MOVE_INSIDE_RECORD (record, new_mvcc_size, old_mvcc_size);
4277  }
4278 
4279  OR_BUF_INIT (orep, record->data, record->area_size);
4280  buf = &orep;
4281 
4282  error =
4283  or_mvcc_set_repid_and_flags (buf, mvcc_rec_header->mvcc_flag, mvcc_rec_header->repid,
4284  repid_and_flag_bits & OR_BOUND_BIT_FLAG, OR_GET_OFFSET_SIZE (record->data));
4285  if (error != NO_ERROR)
4286  {
4287  goto exit_on_error;
4288  }
4289 
4290  error = or_mvcc_set_chn (buf, mvcc_rec_header);
4291  if (error != NO_ERROR)
4292  {
4293  goto exit_on_error;
4294  }
4295 
4296  error = or_mvcc_set_insid (buf, mvcc_rec_header);
4297  if (error != NO_ERROR)
4298  {
4299  goto exit_on_error;
4300  }
4301 
4302  error = or_mvcc_set_delid (buf, mvcc_rec_header);
4303  if (error != NO_ERROR)
4304  {
4305  goto exit_on_error;
4306  }
4307 
4308  error = or_mvcc_set_prev_version_lsa (buf, mvcc_rec_header);
4309  if (error != NO_ERROR)
4310  {
4311  goto exit_on_error;
4312  }
4313 
4314  return NO_ERROR;
4315 
4316 exit_on_error:
4317  return (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
4318 }
4319 
4320 /*
4321  * or_mvcc_add_header () - Add header in record
4322  *
4323  * return : Void.
4324  * record (in/out) : Record descriptor.
4325  * mvcc_rec_header (in) : MVCC Record header.
4326  *
4327  * Note: This function must be called when the record is build by adding
4328  * header and then data. This function will add record header only.
4329  * Later, record data must be added. Obvious, the caller must be sure that
4330  * the record area size is sufficiently large to include header and data.
4331  * When called, record->length must be 0. When return, record->length
4332  * will contain the header size.
4333  */
4334 int
4335 or_mvcc_add_header (RECDES * record, MVCC_REC_HEADER * mvcc_rec_header, int bound_bit, int variable_offset_size)
4336 {
4337  OR_BUF orep, *buf;
4338  int error = NO_ERROR;
4339 
4340  assert (record != NULL && record->data != NULL && record->length == 0);
4341 
4342  OR_BUF_INIT (orep, record->data, record->area_size);
4343  buf = &orep;
4344 
4345  error =
4346  or_mvcc_set_repid_and_flags (buf, mvcc_rec_header->mvcc_flag, mvcc_rec_header->repid, bound_bit,
4347  variable_offset_size);
4348  if (error != NO_ERROR)
4349  {
4350  goto exit_on_error;
4351  }
4352 
4353  error = or_mvcc_set_chn (buf, mvcc_rec_header);
4354  if (error != NO_ERROR)
4355  {
4356  goto exit_on_error;
4357  }
4358 
4359  error = or_mvcc_set_insid (buf, mvcc_rec_header);
4360  if (error != NO_ERROR)
4361  {
4362  goto exit_on_error;
4363  }
4364 
4365  error = or_mvcc_set_delid (buf, mvcc_rec_header);
4366  if (error != NO_ERROR)
4367  {
4368  goto exit_on_error;
4369  }
4370 
4371  error = or_mvcc_set_prev_version_lsa (buf, mvcc_rec_header);
4372  if (error != NO_ERROR)
4373  {
4374  goto exit_on_error;
4375  }
4376 
4377  record->length = CAST_BUFLEN (buf->ptr - buf->buffer);
4378 
4379  return NO_ERROR;
4380 
4381 exit_on_error:
4382  return (error == NO_ERROR && (error = er_errid ()) == NO_ERROR) ? ER_FAILED : error;
4383 }
4384 
4385 /*
4386  * or_mvcc_set_log_lsa_to_record () - Sets the previus version LSA in record header.
4387  * Assumes the previous version lsa is allocated in header
4388  *
4389  * return : error_code
4390  * record (in/out) : record
4391  * lsa (in) : lsa to be set
4392  */
4393 int
4395 {
4396  int mvcc_flags = or_mvcc_get_flag (record);
4397  int lsa_offset = -1;
4398 
4399  if (!(mvcc_flags & OR_MVCC_FLAG_VALID_PREV_VERSION))
4400  {
4401  assert (false);
4402  return ER_FAILED;
4403  }
4404 
4405  if (record == NULL || lsa == NULL)
4406  {
4407  assert (false);
4408  return ER_FAILED;
4409  }
4410 
4411  lsa_offset = (OR_REP_OFFSET + OR_MVCC_REP_SIZE + OR_INT_SIZE
4412  + (((mvcc_flags) & OR_MVCC_FLAG_VALID_INSID) ? OR_MVCCID_SIZE : 0)
4413  + (((mvcc_flags) & OR_MVCC_FLAG_VALID_DELID) ? OR_MVCCID_SIZE : 0));
4414 
4415  memcpy (record->data + lsa_offset, lsa, OR_MVCC_PREV_VERSION_LSA_SIZE);
4416 
4417  return NO_ERROR;
4418 }
4419 
4420 /*
4421  * or_mvcc_get_flag () - Gets MVCC flags.
4422  *
4423  * return : MVCC flags.
4424  * record (in) : Record descriptor.
4425  */
4426 static char
4428 {
4429  assert (record != NULL && record->data != NULL && record->length >= OR_HEADER_SIZE (record->data));
4430 
4431  return (char) (OR_GET_MVCC_FLAG (record->data));
4432 }
4433 
4434 /*
4435  * or_mvcc_set_flag () - Set mvcc flags to record header.
4436  *
4437  * return : Void.
4438  * record (in) : Record descriptor.
4439  * flags (in) : MVCC flags to set.
4440  */
4441 static void
4442 or_mvcc_set_flag (RECDES * record, char flags)
4443 {
4444  OR_BUF orep, *buf;
4445  int repid_and_flag = 0;
4446 
4447  assert (record != NULL && record->data != NULL && record->length >= OR_MVCC_REP_SIZE);
4448 
4449  repid_and_flag = OR_GET_INT (record->data + OR_REP_OFFSET);
4450 
4451  /* Remove old mvcc flags */
4452  repid_and_flag &= ~OR_MVCC_FLAG_MASK;
4453  /* Set new mvcc flags */
4454  repid_and_flag += ((flags & OR_MVCC_FLAG_MASK) << OR_MVCC_FLAG_SHIFT_BITS);
4455 
4456  OR_BUF_INIT (orep, record->data, record->area_size);
4457  buf = &orep;
4458  buf->ptr = buf->buffer + OR_REP_OFFSET;
4459  or_put_int (buf, repid_and_flag);
4460 }
4461 
4462 /*
4463  * or_mvcc_get_insid () - Get insert MVCCID from record data.
4464  *
4465  * return : Insert MVCCID.
4466  * buf (in/out) : or buffer
4467  * mvcc_falgs(in) : MVCC flags
4468  * error(out): NO_ERROR or error code
4469  */
4471 or_mvcc_get_insid (OR_BUF * buf, int mvcc_flags, int *error)
4472 {
4473  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4474 
4475  if (!(mvcc_flags & OR_MVCC_FLAG_VALID_INSID))
4476  {
4477  return MVCCID_ALL_VISIBLE;
4478  }
4479  else if ((buf->ptr + OR_MVCCID_SIZE) > buf->endptr)
4480  {
4481  *error = or_underflow (buf);
4482  return 0;
4483  }
4484  else
4485  {
4486  MVCCID insert_id = 0;
4487  OR_GET_BIGINT (buf->ptr, &insert_id);
4488  buf->ptr += OR_MVCCID_SIZE;
4489  *error = NO_ERROR;
4490  return insert_id;
4491  }
4492 }
4493 
4494 /*
4495  * or_mvcc_set_insid () - Set insert MVCCID into record data
4496  *
4497  * return : Insert MVCCID.
4498  * buf (in/out) : or buffer
4499  * mvcc_rec_header(in) : MVCC record header
4500  */
4501 STATIC_INLINE int
4503 {
4504  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4505  if (!(mvcc_rec_header->mvcc_flag & OR_MVCC_FLAG_VALID_INSID))
4506  {
4507  return NO_ERROR;
4508  }
4509 
4510  return or_put_bigint (buf, mvcc_rec_header->mvcc_ins_id);
4511 }
4512 
4513 /*
4514  * or_mvcc_get_delid () - Get MVCC delid
4515  *
4516  * return : MVCC delid
4517  * buf (in/out) : or buffer
4518  * mvcc_falgs(in) : MVCC flags
4519  * error(out): NO_ERROR or error code
4520  */
4522 or_mvcc_get_delid (OR_BUF * buf, int mvcc_flags, int *error)
4523 {
4524  MVCCID delid = MVCCID_NULL;
4525 
4526  assert (buf != NULL && error != NULL);
4527 
4528  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4529 
4530  *error = NO_ERROR;
4531  if (mvcc_flags & OR_MVCC_FLAG_VALID_DELID)
4532  {
4533  /* MVCC DELID is active */
4534  if ((buf->ptr + OR_MVCCID_SIZE) > buf->endptr)
4535  {
4536  *error = or_underflow (buf);
4537  delid = MVCCID_NULL;
4538  }
4539  else
4540  {
4541  OR_GET_BIGINT (buf->ptr, &(delid));
4542  buf->ptr += OR_MVCCID_SIZE;
4543  }
4544  }
4545  return delid;
4546 }
4547 
4548 /*
4549  * or_mvcc_get_chn () - Get MVCC chn
4550  *
4551  * return : MVCC chn
4552  * buf (in/out) : or buffer
4553  * mvcc_falgs(in) : MVCC flags
4554  * error(out): NO_ERROR or error code
4555  */
4556 STATIC_INLINE int
4558 {
4559  int chn = NULL_CHN;
4560 
4561  assert (buf != NULL && error != NULL);
4562 
4563  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4564 
4565  *error = NO_ERROR;
4566 
4567  if ((buf->ptr + OR_INT_SIZE) > buf->endptr)
4568  {
4569  *error = or_underflow (buf);
4570  }
4571  else
4572  {
4573  chn = OR_GET_INT (buf->ptr);
4574  buf->ptr += OR_INT_SIZE;
4575  }
4576 
4577  return chn;
4578 }
4579 
4580 /*
4581  * or_mvcc_set_delid () - Set MVCC delete id
4582  *
4583  * return : error code
4584  * buf (in/out) : or buffer
4585  * mvcc_rec_header(in): MVCC record header
4586  */
4587 STATIC_INLINE int
4589 {
4590  assert (buf != NULL);
4591  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4592 
4593  if (!(mvcc_rec_header->mvcc_flag & OR_MVCC_FLAG_VALID_DELID))
4594  {
4595  return NO_ERROR;
4596  }
4597 
4598  return or_put_bigint (buf, mvcc_rec_header->mvcc_del_id);
4599 }
4600 
4601 /*
4602  * or_mvcc_set_chn () - Set MVCC chn
4603  *
4604  * return : error code
4605  * buf (in/out) : or buffer
4606  * mvcc_rec_header(in): MVCC record header
4607  */
4608 STATIC_INLINE int
4610 {
4611  assert (buf != NULL);
4612  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4613 
4614  return or_put_int (buf, mvcc_rec_header->chn);
4615 }
4616 
4617 /*
4618  * or_mvcc_set_prev_version_lsa () - Set MVCC prev version LSA
4619  *
4620  * return : error code
4621  * buf (in/out) : or buffer
4622  * mvcc_rec_header(in): MVCC record header
4623  */
4624 STATIC_INLINE int
4626 {
4627  assert (buf != NULL);
4628 
4629  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4630  if (!(mvcc_rec_header->mvcc_flag & OR_MVCC_FLAG_VALID_PREV_VERSION))
4631  {
4632  return NO_ERROR;
4633  }
4634 
4635  if ((buf->ptr + OR_MVCC_PREV_VERSION_LSA_SIZE) > buf->endptr)
4636  {
4637  return (or_overflow (buf));
4638  }
4639 
4640  memcpy (buf->ptr, &mvcc_rec_header->prev_version_lsa, OR_MVCC_PREV_VERSION_LSA_SIZE);
4642 
4643  return NO_ERROR;
4644 }
4645 
4646 /*
4647  * or_mvcc_get_prev_version_lsa () - Get MVCC prev version LSA from buffer
4648  *
4649  * return : error code
4650  * buf (in) : or buffer
4651  * mvcc_flags(in) : header mvcc flags
4652  * prev_version_lsa(out): the LSA to previous version
4653  * mvcc_rec_header(in) : MVCC record header
4654  */
4655 STATIC_INLINE int
4656 or_mvcc_get_prev_version_lsa (OR_BUF * buf, int mvcc_flags, LOG_LSA * prev_version_lsa)
4657 {
4658  assert (buf != NULL);
4659 
4660  ASSERT_ALIGN (buf->ptr, INT_ALIGNMENT);
4661  if (!(mvcc_flags & OR_MVCC_FLAG_VALID_PREV_VERSION))
4662  {
4663  LSA_SET_NULL (prev_version_lsa);
4664  return NO_ERROR;
4665  }
4666 
4667  if ((buf->ptr + OR_MVCC_PREV_VERSION_LSA_SIZE) > buf->endptr)
4668  {
4669  return (or_underflow (buf));
4670  }
4671 
4672  *prev_version_lsa = *(LOG_LSA *) buf->ptr;
4674 
4675  return NO_ERROR;
4676 }
char * PAGE_PTR
#define OR_SET_VAR_OFFSET_SIZE(val, offset_size)
OR_ATTRIBUTE * shared_attrs
int tp_domain_disk_size(TP_DOMAIN *domain)
int ci_tot_pages
static int or_get_default_value(OR_ATTRIBUTE *attr, char *ptr, int length)
#define NO_ERROR
Definition: error_code.h:46
int set_get_element_nocopy(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2616
int area_size
int or_get_enumeration(OR_BUF *buf, DB_ENUMERATION *e)
int or_rep_id(RECDES *record)
#define __attribute__(X)
Definition: porting.h:36
DB_COLLECTION * db_get_set(const DB_VALUE *value)
INT32 mvcc_flag
Definition: mvcc.h:40
static int or_cl_get_prop_nocopy(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
#define BTREE_STATS_RESERVED_NUM
Definition: statistics.h:42
STATIC_INLINE int or_get_varchar_compression_lengths(OR_BUF *buf, int *compressed_size, int *decompressed_size) __attribute__((ALWAYS_INLINE))
static void or_install_btids(OR_CLASSREP *rep, DB_SEQ *props)
MVCCID mvcc_ins_id
Definition: mvcc.h:43
OR_FUNCTION_INDEX * func_index_info
BTID * sys_btid
Definition: btree.h:121
#define ASSERT_ERROR()
void or_class_tde_algorithm(RECDES *record, TDE_ALGORITHM *tde_algo)
int or_mvcc_set_repid_and_flags(OR_BUF *buf, int mvcc_flag, int repid, int bound_bit, int variable_offset_size)
unsigned char codeset
Definition: object_domain.h:91
PAGEID FILEID
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
int db_get_int(const DB_VALUE *value)
int or_replace_rep_id(RECDES *record, int repid)
#define OR_VAR_TABLE_ELEMENT_LENGTH(table, index)
DB_TYPE
Definition: dbtype_def.h:670
#define ER_FAILED
Definition: error_code.h:47
BTREE_ROOT_HEADER * btree_get_root_header(THREAD_ENTRY *thread_p, PAGE_PTR page_ptr)
Definition: btree_load.c:309
#define OR_SET_ELEMENT_COUNT(setptr)
OR_ATTRIBUTE * class_attrs
int pr_get_compressed_data_from_buffer(struct or_buf *buf, char *data, int compressed_size, int expected_decompressed_size)
#define ALWAYS_INLINE
#define OR_MVCC_REPID_MASK
BTREE_TYPE
struct tp_domain * setdomain
Definition: object_domain.h:82
#define SM_FILTER_INDEX_ID
#define HEAP_MOVE_INSIDE_RECORD(rec, dest_offset, src_offset)
int classobj_get_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
#define OR_BUF_INIT(buf, data, size)
#define ER_CT_UNKNOWN_REPRID
Definition: error_code.h:493
void orc_free_diskrep(DISK_REPR *rep)
#define OR_MVCC_FLAG_VALID_INSID
int btree_glean_root_header_info(THREAD_ENTRY *thread_p, BTREE_ROOT_HEADER *root_header, BTID_INT *btid)
Definition: btree.c:5797
unsigned int ci_time_stamp
int or_mvcc_get_header(RECDES *record, MVCC_REC_HEADER *mvcc_header)
int pkeys_size
Definition: statistics.h:66
INT16 VOLID
INT32 repid
Definition: mvcc.h:41
#define MVCCID_NULL
#define OR_GET_BOUND_BIT_FLAG(ptr)
static void or_install_btids_foreign_key_ref(DB_SEQ *fk_container, OR_INDEX *index)
int heap_scancache_quick_start_root_hfid(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:19255
#define OR_MVCC_FLAG_VALID_DELID
#define OR_MVCCID_SIZE
TP_DOMAIN * key_type
Definition: statistics.h:65
#define OID_SET_NULL(oidp)
Definition: oid.h:85
OR_CLASSREP * or_classrep_load_indexes(OR_CLASSREP *rep, RECDES *record)
#define OR_ATT_BTID_PREALLOC
#define OR_MVCC_FLAG_SHIFT_BITS
char * data
#define OR_FIXED_ATTRIBUTES_OFFSET(ptr, nvars)
int32_t pageid
Definition: dbtype_def.h:879
void or_free_classrep(OR_CLASSREP *rep)
INT32 root_pageid
int or_mvcc_add_header(RECDES *record, MVCC_REC_HEADER *mvcc_rec_header, int bound_bit, int variable_offset_size)
static void or_get_att_index(char *ptr, BTID *btid)
INT32 hpgid
#define BTID_IS_EQUAL(b1, b2)
int er_errid(void)
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
void or_class_hfid(RECDES *record, HFID *hfid)
#define SM_PROPERTY_NUM_INDEX_FAMILY
int heap_scancache_end(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:7195
#define OR_VAR_OFFSET(obj, index)
#define COPY_OID(dest_oid_ptr, src_oid_ptr)
Definition: oid.h:63
OR_CLASSREP * or_get_classrep_noindex(RECDES *record, int repid)
int mvcc_header_size_lookup[8]
static int or_install_btids_filter_pred(DB_SEQ *pred_seq, OR_INDEX *index)
int ci_tot_objects
void THREAD_ENTRY
#define MVCCID_ALL_VISIBLE
#define pgbuf_unfix_and_init(thread_p, pgptr)
Definition: page_buffer.h:63
#define OR_VAR_IS_NULL(obj, index)
or_auto_increment auto_increment
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
OR_FOREIGN_KEY * fk
#define OR_VAR_TABLE_SIZE(vars)
void or_class_rep_dir(RECDES *record, OID *rep_dir_p)
static INLINE int or_mvcc_set_chn(OR_BUF *buf, MVCC_REC_HEADER *mvcc_rec_header) __attribute__((ALWAYS_INLINE))
DB_DEFAULT_EXPR_TYPE on_update_expr
static INLINE int or_mvcc_set_insid(OR_BUF *buf, MVCC_REC_HEADER *mvcc_rec_header) __attribute__((ALWAYS_INLINE))
#define RECDES_INITIALIZER
static OR_CLASSREP * or_get_old_representation(RECDES *record, int repid, int do_indexes)
int or_get_unique_hierarchy(THREAD_ENTRY *thread_p, RECDES *record, int attrid, BTID *btid, OID **class_oids, HFID **hfids, int *num_classes, int *partition_local_index)
int classobj_decompose_property_oid(const char *buffer, int *volid, int *fileid, int *pageid)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
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 or_mvcc_set_log_lsa_to_record(RECDES *record, LOG_LSA *lsa)
Definition: db_set.h:35
#define OR_MVCC_FLAG_VALID_PREV_VERSION
static TP_DOMAIN * or_get_domain_internal(char *ptr)
const char * or_get_constraint_comment(RECDES *record, const char *constraint_name)
#define assert(x)
BTID btid_pack[OR_ATT_BTID_PREALLOC]
int * pkeys
Definition: statistics.h:67
TDE_ALGORITHM
Definition: tde.h:71
BTREE_STATS * bt_stats
#define OR_MVCC_FLAG_MASK
int32_t fileid
Definition: dbtype_def.h:886
bool pgbuf_check_page_ptype(THREAD_ENTRY *thread_p, PAGE_PTR pgptr, PAGE_TYPE ptype)
#define ASSERT_ALIGN(ptr, alignment)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
#define STATIC_INLINE
OR_DEFAULT_VALUE default_value
std::atomic< or_aligned_oid > serial_obj
int or_mvcc_get_repid_and_flags(OR_BUF *buf, int *error)
DB_IDENTIFIER OID
Definition: dbtype_def.h:967
#define OR_SET_HEADER_SIZE
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
int or_get_attrcomment(RECDES *record, int attrid, char **string, int *alloced_string)
DB_TYPE db_value_type(const DB_VALUE *value)
int orc_superclasses_from_record(RECDES *record, int *array_size, OID **array_ptr)
#define DOM_GET_ENUMERATION(dom)
Definition: object_domain.h:38
int tp_domain_size(const TP_DOMAIN *domain)
#define OR_GET_OID(ptr, oid)
DB_SEQ * db_seq_copy(DB_SEQ *source)
Definition: db_set.c:428
int or_put_int(OR_BUF *buf, int num)
#define BTREE_STATS_PKEYS_NUM
Definition: statistics.h:41
static int or_install_btids_attribute(OR_CLASSREP *rep, int att_id, BTID *id)
int or_mvcc_set_header(RECDES *record, MVCC_REC_HEADER *mvcc_rec_header)
#define OR_HEADER_SIZE(ptr)
int or_put_bigint(OR_BUF *buf, DB_BIGINT num)
int or_overflow(OR_BUF *buf)
static INLINE MVCCID or_mvcc_get_insid(OR_BUF *buf, int mvcc_flags, int *error) __attribute__((ALWAYS_INLINE))
OR_PREDICATE * filter_predicate
short volid
Definition: dbtype_def.h:880
void orc_free_class_info(CLS_INFO *info)
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
#define OR_MVCC_PREV_VERSION_LSA_SIZE
DISK_REPR * orc_diskrep_from_record(THREAD_ENTRY *thread_p, RECDES *record)
VFID vfid
#define TP_DOMAIN_TYPE(dom)
#define NULL
Definition: freelistheap.h:34
static TP_DOMAIN * or_get_domain_and_cache(char *ptr)
UINT64 MVCCID
struct disk_attribute * variable
static void or_install_btids_function_info(DB_SEQ *fi_seq, OR_INDEX *index)
OR_CLASSREP ** or_get_all_representation(RECDES *record, bool do_indexes, int *count)
#define DB_ATT_ALIGN(offset)
Definition: memory_alloc.h:93
VFID vfid
int or_class_get_partition_info(RECDES *record, OR_PARTITION *partition_info, REPR_ID *repr_id, int *has_partition_info)
#define SM_PROPERTY_UNIQUE
static int success()
#define OR_GET_BIGINT(ptr, val)
#define BTID_SET_NULL(btid)
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
#define err(fd,...)
Definition: porting.h:431
#define pgbuf_fix(thread_p, vpid, fetch_mode, requestmode, condition)
Definition: page_buffer.h:255
int db_set_free(DB_SET *set)
Definition: db_set.c:306
#define OR_REP_OFFSET
static void or_install_btids_class(OR_CLASSREP *rep, BTID *id, DB_SEQ *constraint_seq, int seq_size, BTREE_TYPE type, const char *cons_name)
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
void or_init(OR_BUF *buf, char *data, int length)
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
const OID oid_Null_oid
Definition: oid.c:68
struct disk_attribute * fixed
#define BIG_VAR_OFFSET_SIZE
static INLINE int or_mvcc_get_prev_version_lsa(OR_BUF *buf, int mvcc_flags, LOG_LSA *prev_version_lsa) __attribute__((ALWAYS_INLINE))
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)
#define OR_SET_ELEMENT_OFFSET(setptr, element)
#define OR_MVCC_MIN_HEADER_SIZE
#define max(a, b)
#define NULL_REPRID
static INLINE MVCCID or_mvcc_get_delid(OR_BUF *buf, int mvcc_flags, int *error) __attribute__((ALWAYS_INLINE))
static void or_install_btids_prefix_length(DB_SEQ *prefix_seq, OR_INDEX *index, int num_attrs)
OR_CLASSREP * or_get_classrep(RECDES *record, int repid)
#define CAST_BUFLEN
Definition: porting.h:471
DB_ENUMERATION enumeration
Definition: object_domain.h:84
static const char * or_find_diskattr(RECDES *record, int attr_id)
#define TP_IS_CHAR_TYPE(typeid)
static void error(const char *msg)
Definition: gencat.c:331
#define VPID_ISNULL(vpid_ptr)
Definition: dbtype_def.h:925
static int or_get_hierarchy_helper(THREAD_ENTRY *thread_p, OID *source_class, OID *class_, BTID *btid, OID **class_oids, HFID **hfids, int *num_classes, int *max_classes, int *partition_local_index)
static int or_get_current_default_value(OR_ATTRIBUTE *attr, char *ptr, int length)
static int rc
Definition: serial.c:50
#define HFID_IS_NULL(hfid)
bool db_value_is_null(const DB_VALUE *value)
static void or_install_btids_constraint(OR_CLASSREP *rep, DB_SEQ *constraint_seq, BTREE_TYPE type, const char *cons_name)
char * or_unpack_setref(char *ptr, DB_SET **ref)
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define SM_PROPERTY_INDEX
static const bool COPY
const char * default_expr_format
Definition: dbtype_def.h:1206
#define SM_PROPERTY_PRIMARY_KEY
LOG_LSA prev_version_lsa
Definition: mvcc.h:45
#define OR_GET_INT(ptr)
static INLINE int or_mvcc_get_chn(OR_BUF *buf, int *error) __attribute__((ALWAYS_INLINE))
INT16 PGSLOTID
int or_underflow(OR_BUF *buf)
static OR_CLASSREP * or_get_current_representation(RECDES *record, int do_indexes)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
int or_get_attrname(RECDES *record, int attrid, char **string, int *alloced_string)
#define OR_GET_MVCC_FLAG(ptr)
void LSA_SET_NULL(log_lsa *lsa_ptr)
Definition: log_lsa.hpp:146
#define OR_ARRAY_EXTENT
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
#define OR_MVCC_REP_SIZE
int orc_subclasses_from_record(RECDES *record, int *array_size, OID **array_ptr)
JSON_VALIDATOR * json_validator
int db_get_string_size(const DB_VALUE *value)
static void or_mvcc_set_flag(RECDES *record, char flags)
static INLINE int or_mvcc_set_delid(OR_BUF *buf, MVCC_REC_HEADER *mvcc_rec_header) __attribute__((ALWAYS_INLINE))
#define OR_GET_MVCC_REPID_AND_FLAG(ptr)
int REPR_ID
OR_DEFAULT_VALUE current_default_value
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int has_function
Definition: statistics.h:64
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
#define OR_GET_OFFSET_SIZE(ptr)
struct tp_domain * next
Definition: object_domain.h:74
#define INLINE
static INLINE int or_mvcc_set_prev_version_lsa(OR_BUF *buf, MVCC_REC_HEADER *mvcc_rec_header) __attribute__((ALWAYS_INLINE))
static char or_mvcc_get_flag(RECDES *record)
static int or_get_attr_string(RECDES *record, int attr_id, int attr_index, char **string, int *alloced_string)
char * strdup(const char *str)
Definition: porting.c:901
CLS_INFO * orc_class_info_from_record(RECDES *record)
OR_INDEX_STATUS index_status
struct db_object * class_mop
Definition: object_domain.h:81
short volid
Definition: dbtype_def.h:887
#define OR_BOUND_BIT_FLAG
INT32 PAGEID
#define OID_ISNULL(oidp)
Definition: oid.h:81
#define SM_PREFIX_INDEX_ID
#define SM_PROPERTY_REVERSE_INDEX
int collation_id
Definition: object_domain.h:92
int or_get_value(OR_BUF *buf, DB_VALUE *value, struct tp_domain *domain, int expected, bool copy)
static void or_install_btids_foreign_key(const char *fkname, DB_SEQ *fk_seq, OR_INDEX *index)
OR_ATTRIBUTE * attributes
TP_DOMAIN * key_type
Definition: btree.h:124
char * or_unpack_domain(char *ptr, struct tp_domain **domain_ptr, int *is_null)
#define DOM_SET_ENUM(dom, elems, cnt)
Definition: object_domain.h:51
#define SM_PROPERTY_REVERSE_UNIQUE
TP_DOMAIN * tp_domain_new(DB_TYPE type)
MVCCID mvcc_del_id
Definition: mvcc.h:44
DB_DEFAULT_EXPR default_expr
OR_ATTRIBUTE ** atts
HFID ci_hfid
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)
DB_DEFAULT_EXPR_TYPE
Definition: dbtype_def.h:1181
int or_get_json_validator(OR_BUF *buf, REFPTR(JSON_VALIDATOR, validator))
#define OR_VAR_TABLE_ELEMENT_OFFSET(table, index)
#define ER_SM_INVALID_PROPERTY
Definition: error_code.h:368
SCAN_CODE heap_get_class_record(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *recdes_p, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:24780