CUBRID Engine  latest
transform_cl.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  * transform_cl.c: Functions related to the storage of instances and classes.
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "porting.h"
32 #include "memory_alloc.h"
33 #include "error_manager.h"
34 #include "work_space.h"
35 #include "oid.h"
36 #include "object_representation.h"
37 #include "object_domain.h"
38 #include "object_primitive.h"
39 #include "class_object.h"
40 #include "set_object.h"
41 #include "transform.h"
42 #include "transform_cl.h"
43 #include "schema_manager.h"
44 #include "locator_cl.h"
45 #include "object_accessor.h"
46 #include "trigger_manager.h"
47 #include "locator.h"
48 #include "server_interface.h"
49 #include "execute_statement.h"
50 #include "db_json.hpp"
51 
52 #include "dbtype.h"
53 
54 #if defined (SUPPRESS_STRLEN_WARNING)
55 #define strlen(s1) ((int) strlen(s1))
56 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
57 
58 /*
59  * tf_Allow_fixups
60  *
61  * Integration kludge.
62  * The changes for initialization of the OR_BUF were rather widespread
63  * and could not all be done at the same time.
64  * This will be OFF until we're sure all the OR_BUF usages are initialized.
65  *
66  * Note, after this gets checked in, and is shown to work well enough, this
67  * variable can be removed, it is only retained to allow for a quick disable
68  * in the event that something ugly happens.
69  */
71 
72 
73 /*
74  * OR_TEMPOID
75  * Information about a temporary OID encountered during a transformation.
76  * These will get stuck onto the LC_OIDMAP structures as they are created
77  * for the LC_OIDSET being maintained inside the OR_FIXUP structure, whew.
78  * LC_OIDSET is a structure that gets sent accross the client/server
79  * boundary so it contains only server safe things. Unfortuantely, we
80  * need to map entries in the LC_OIDSET universe back into the DB_OBJECT*
81  * and transformation buffer locations that need to get fixed once the
82  * permanent OID is known. Rather than keep parallel structures for this,
83  * we're allowed to stick a client/side structure on each LC_OIDMAP
84  * entry, this is it.
85  * When the LC_OIDMAP is returned by the server with permanent OIDs, it
86  * will be unpacked INTO an EXISTING LC_OIDMAP structure rather than
87  * creating a new one. This existing structure will still have pointers
88  * to this structure so once the server has filled in the permanent OIDs
89  * we can simply walk over the LC_OIDMAP, get into the OR_TEMPOID and make
90  * the appropriate modifications.
91  */
92 typedef struct or_tempoid
93 {
94 
95  int refsize; /* number of elements in array */
96  int refcount; /* our fill pointer */
97  void **references; /* references, NULL terminated */
98 
99 } OR_TEMPOID;
100 
101 /*
102  * OR_FIXUP
103  * State structure maintained in an OR_BUF that encapuslates a history
104  * of temporary OIDs that we encounter during transformation.
105  * Now that the LC_OIDSET is sufficiently complex, we could just replace
106  * OR_FIXUP with that, but lets keep the encapsulation for awhile in case
107  * we need to add somethign else here.
108  */
109 typedef struct or_fixup
110 {
112 } OR_FIXUP;
113 
114 /*
115  * Set functions
116  * These are shorthand macros for functions that are required as
117  * arguments to the variable set functions below.
118  *
119  */
120 typedef int (*LSIZER) (void *);
121 typedef void (*LWRITER) (void *, void *);
122 typedef DB_LIST *(*LREADER) (void *);
123 typedef void (*VREADER) (void *, void *);
124 
125 /*
126  * Forward declaration of local functions
127  */
128 static int optimize_sets (SM_CLASS * class_, MOBJ volatile obj);
129 static OR_FIXUP *tf_make_fixup (void);
130 static void tf_free_fixup (OR_FIXUP * fix);
131 static void fixup_callback (LC_OIDMAP * oidmap);
132 static int tf_do_fixup (OR_FIXUP * fix);
133 static int put_varinfo (OR_BUF * buf, char *obj, SM_CLASS * class_, int offset_size);
134 static int object_size (SM_CLASS * class_, MOBJ obj, int *offset_size_ptr);
135 static int put_attributes (OR_BUF * buf, char *obj, SM_CLASS * class_);
136 static char *get_current (OR_BUF * buf, SM_CLASS * class_, MOBJ * obj_ptr, int bound_bit_flag, int offset_size);
137 static SM_ATTRIBUTE *find_current_attribute (SM_CLASS * class_, int id);
138 static void clear_new_unbound (char *obj, SM_CLASS * class_, SM_REPRESENTATION * oldrep);
139 static char *get_old (OR_BUF * buf, SM_CLASS * class_, MOBJ * obj_ptr, int repid, int bound_bit_flag, int offset_size);
140 static char *unpack_allocator (int size);
141 static OR_VARINFO *read_var_table (OR_BUF * buf, int nvars);
142 static OR_VARINFO *read_var_table_internal (OR_BUF * buf, int nvars, int offset_size);
143 static void free_var_table (OR_VARINFO * vars);
144 static int string_disk_size (const char *string);
145 static char *get_string (OR_BUF * buf, int length);
146 static void put_string (OR_BUF * buf, const char *string);
147 static int object_set_size (DB_OBJLIST * list);
148 static int put_object_set (OR_BUF * buf, DB_OBJLIST * list);
149 static DB_OBJLIST *get_object_set (OR_BUF * buf, int expected);
150 static int substructure_set_size (DB_LIST * list, LSIZER function);
151 static void put_substructure_set (OR_BUF * buf, DB_LIST * list, LWRITER writer, OID * class_, int repid);
152 static DB_LIST *get_substructure_set (OR_BUF * buf, LREADER reader, int expected);
153 static void install_substructure_set (OR_BUF * buf, DB_LIST * list, VREADER reader, int expected);
154 static int property_list_size (DB_SEQ * properties);
155 static void put_property_list (OR_BUF * buf, DB_SEQ * properties);
156 static DB_SEQ *get_property_list (OR_BUF * buf, int expected_size);
157 static int domain_size (TP_DOMAIN * domain);
158 static void domain_to_disk (OR_BUF * buf, TP_DOMAIN * domain);
159 static TP_DOMAIN *disk_to_domain2 (OR_BUF * buf);
160 static TP_DOMAIN *disk_to_domain (OR_BUF * buf);
161 static void metharg_to_disk (OR_BUF * buf, SM_METHOD_ARGUMENT * arg);
162 static int metharg_size (SM_METHOD_ARGUMENT * arg);
164 static int methsig_to_disk (OR_BUF * buf, SM_METHOD_SIGNATURE * sig);
165 static inline void methsig_to_disk_lwriter (void *buf, void *sig);
166 static int methsig_size (SM_METHOD_SIGNATURE * sig);
168 static int method_to_disk (OR_BUF * buf, SM_METHOD * method);
169 static inline void method_to_disk_lwriter (void *buf, void *method);
170 static int method_size (SM_METHOD * method);
171 static void disk_to_method (OR_BUF * buf, SM_METHOD * method);
172 static int methfile_to_disk (OR_BUF * buf, SM_METHOD_FILE * file);
173 static inline void methfile_to_disk_lwriter (void *buf, void *file);
174 static int methfile_size (SM_METHOD_FILE * file);
175 static SM_METHOD_FILE *disk_to_methfile (OR_BUF * buf);
176 static int query_spec_to_disk (OR_BUF * buf, SM_QUERY_SPEC * query_spec);
177 static inline void query_spec_to_disk_lwriter (void *buf, void *query_spec);
178 static int query_spec_size (SM_QUERY_SPEC * statement);
179 static SM_QUERY_SPEC *disk_to_query_spec (OR_BUF * buf);
180 static int attribute_to_disk (OR_BUF * buf, SM_ATTRIBUTE * att);
181 static inline void attribute_to_disk_lwriter (void *buf, void *att);
182 static int attribute_size (SM_ATTRIBUTE * att);
183 static void disk_to_attribute (OR_BUF * buf, SM_ATTRIBUTE * att);
184 static int resolution_to_disk (OR_BUF * buf, SM_RESOLUTION * res);
185 static inline void resolution_to_disk_lwriter (void *buf, void *res);
186 static int resolution_size (SM_RESOLUTION * res);
187 static SM_RESOLUTION *disk_to_resolution (OR_BUF * buf);
188 static int repattribute_to_disk (OR_BUF * buf, SM_REPR_ATTRIBUTE * rat);
189 static inline void repattribute_to_disk_lwriter (void *buf, void *rat);
190 static int repattribute_size (SM_REPR_ATTRIBUTE * rat);
192 static int representation_size (SM_REPRESENTATION * rep);
193 static int representation_to_disk (OR_BUF * buf, SM_REPRESENTATION * rep);
194 static inline void representation_to_disk_lwriter (void *buf, void *rep);
196 static int check_class_structure (SM_CLASS * class_);
197 static int put_class_varinfo (OR_BUF * buf, SM_CLASS * class_);
198 static void put_class_attributes (OR_BUF * buf, SM_CLASS * class_);
199 static void class_to_disk (OR_BUF * buf, SM_CLASS * class_);
200 static void tag_component_namespace (SM_COMPONENT * components, SM_NAME_SPACE name_space);
201 static SM_CLASS *disk_to_class (OR_BUF * buf, SM_CLASS ** class_ptr);
202 static void root_to_disk (OR_BUF * buf, ROOT_CLASS * root);
203 static int root_size (MOBJ rootobj);
204 static int tf_class_size (MOBJ classobj);
205 static ROOT_CLASS *disk_to_root (OR_BUF * buf);
206 
207 static int enumeration_size (const DB_ENUMERATION * enumeration);
208 static void put_enumeration (OR_BUF * buf, const DB_ENUMERATION * e);
209 static int get_enumeration (OR_BUF * buf, DB_ENUMERATION * enumeration, int expected);
210 static int tf_attribute_default_expr_to_property (SM_ATTRIBUTE * attr_list);
211 
212 static int partition_info_to_disk (OR_BUF * buf, SM_PARTITION * partition_info);
213 static inline void partition_info_to_disk_lwriter (void *buf, void *partition_info);
215 static int partition_info_size (SM_PARTITION * partition_info);
216 static void or_pack_mop (OR_BUF * buf, MOP mop);
217 
218 #if defined(ENABLE_UNUSED_FUNCTION)
219 /*
220  * tf_find_temporary_oids - walks over the memory representation of an
221  * instance and finds all the temporary OIDs within it and adds them to the
222  * oidset.
223  * return: NO_ERROR if successful, error code otherwise
224  * oidset(out): oidset to populate
225  * classobj(in): object to examine
226  */
227 int
228 tf_find_temporary_oids (LC_OIDSET * oidset, MOBJ classobj, MOBJ obj)
229 {
230  int error = NO_ERROR;
231  SM_CLASS *class_;
232  SM_ATTRIBUTE *att;
233  DB_TYPE type;
234  SETOBJ *col;
235 
236  /*
237  * Do this only for instance objects. This means that class objects
238  * with temporary oids in, say, class variables won't get flushed at
239  * this time, but that's probably ok. They'll get flushed as part of
240  * the ordinary class object packing business, and since they ought to
241  * be few in number, that shouldn't have much of an impact.
242  */
243  if ((classobj != (MOBJ) (&sm_Root_class)) && (obj != NULL))
244  {
245 
246  class_ = (SM_CLASS *) classobj;
247 
248  for (att = class_->attributes; att != NULL && error == NO_ERROR; att = (SM_ATTRIBUTE *) att->header.next)
249  {
250 
251  type = TP_DOMAIN_TYPE (att->domain);
252  if (type == DB_TYPE_OBJECT)
253  {
254  WS_MEMOID *mem;
255  OID *oid;
256  mem = (WS_MEMOID *) (obj + att->offset);
257  oid = &mem->oid;
258 
259  if (OID_ISTEMP (oid) && mem->pointer != NULL && !WS_IS_DELETED (mem->pointer))
260  {
261 
262  /* Make sure the ws_memoid mop is temporary. */
263  if (OID_ISTEMP (WS_OID (mem->pointer)))
264  {
265 
266  /* its an undeleted temporary object, promote */
267  if (locator_add_oidset_object (oidset, mem->pointer) == NULL)
268  {
269  assert (er_errid () != NO_ERROR);
270  error = er_errid ();
271  }
272  }
273  }
274  }
275  else if (TP_IS_SET_TYPE (type))
276  {
277  col = *(SETOBJ **) (obj + att->offset);
278 
279  error = setobj_find_temporary_oids (col, oidset);
280  }
281  }
282  }
283 
284  return error;
285 }
286 #endif /* ENABLE_UNUSED_FUNCTION */
287 
288 /*
289  * optimize_sets - Called before the transformation begins to ensure that
290  * any sets this object contains are sorted before sending them to disk.
291  * return: NO_ERROR if successful, error code otherwise
292  * class(in): class structure
293  * obj(in/out): object attributes
294  * Note:
295  * In practice, sets will be unsorted only if they contained temporary
296  * OIDs at one time in their lives. This will have the side effect
297  * of doing a bulk OID assignment for each set that is unsorted and then
298  * sorting the set. This may add some time to the flush process but
299  * the sort will not allocate very much memory so it should be safe in low
300  * memory situations.
301  *
302  * This would be more effecient if we split this into two opeations,
303  * the first would walk over the entire object upgrading all temporary
304  * OIDs to permanent ones. The second sorted the sets.
305  * This would result in one batch OID assignment calls rather than
306  * one for each set. Unfortuantely, that's a little more complicated as
307  * it requires some new traversal code. Someday . . .
308  */
309 static int
310 optimize_sets (SM_CLASS * class_, MOBJ volatile obj)
311 {
312  int error = NO_ERROR;
313  SM_ATTRIBUTE *att;
314  SETOBJ *col;
315 
316  for (att = class_->attributes; att != NULL && error == NO_ERROR; att = (SM_ATTRIBUTE *) att->header.next)
317  {
318  if (TP_IS_SET_TYPE (TP_DOMAIN_TYPE (att->domain)))
319  {
320  col = *((SETOBJ **) (obj + att->offset));
321 
322  if (col)
323  {
324  /*
325  * col now has the collection pointer.
326  * sort it before we flush. The sort operation will produce
327  * batched permanent oid's on demand if needed.
328  */
329  error = setobj_sort (col);
330  }
331  }
332  }
333  return error;
334 }
335 
336 
337 /*
338  * tf_make_fixup - This initializes a new transformer fixup structure for use.
339  * return: fixup structure
340  * Note:
341  * It doesn't actually allocate the LC_OIDSET until we find that
342  * we have references.
343  */
344 static OR_FIXUP *
346 {
347  OR_FIXUP *fix;
348 
349  fix = (OR_FIXUP *) malloc (sizeof (OR_FIXUP));
350  if (fix != NULL)
351  {
352  fix->oidset = NULL;
353  }
354  return fix;
355 }
356 
357 
358 /*
359  * tf_free_fixup - frees a fixup structure create by tf_make_fixup.
360  * return: none
361  * fix(out): fixup structure
362  * Note:
363  * This now consists of a single LC_OIDSET structure with
364  * OR_TEMPOID structure embedded within it.
365  * Since locator_free_oid_set doesn't know anything about our appendages,
366  * we have to walk the LC_OIDSET and free them first.
367  *
368  */
369 static void
371 {
372  LC_CLASS_OIDSET *class_;
373  LC_OIDMAP *oid;
374  OR_TEMPOID *temp;
375 
376  if (fix == NULL)
377  {
378  return;
379  }
380 
381  if (fix->oidset == NULL)
382  {
383  free_and_init (fix);
384  return;
385  }
386  /* free our OR_TEMPOID warts */
387  for (class_ = fix->oidset->classes; class_ != NULL; class_ = class_->next)
388  {
389  for (oid = class_->oids; oid != NULL; oid = oid->next)
390  {
391  if (oid->client_data)
392  {
393  temp = (OR_TEMPOID *) oid->client_data;
394  free_and_init (temp->references);
395  free_and_init (temp);
396  oid->client_data = NULL;
397  }
398  }
399  }
400 
401  /* now free the LC_OIDSET hierarchy */
403  free_and_init (fix);
404 }
405 
406 
407 
408 #define TF_FIXUP_REFERENCE_QUANT 32
409 /*
410  * tf_add_fixup - This adds a fixup "relocation" entry for a temporary OID
411  * that's been encountered.
412  * return: error
413  * fix(in/out): fixup state
414  * obj(in): object with temporary OID
415  * ref(in): address of packed reference
416  */
417 static int
418 tf_add_fixup (OR_FIXUP * fix, DB_OBJECT * obj, void *ref)
419 {
420  LC_OIDMAP *o;
421  OR_TEMPOID *t;
422  size_t buf_size;
423 
424  /* get the oidset we're building */
425  if (fix->oidset == NULL)
426  {
427  fix->oidset = locator_make_oid_set ();
428  if (fix->oidset == NULL)
429  {
430  assert (er_errid () != NO_ERROR);
431  return er_errid ();
432  }
433  }
434 
435  o = locator_add_oidset_object (fix->oidset, obj);
436  if (o == NULL)
437  {
438  assert (er_errid () != NO_ERROR);
439  return er_errid ();
440  }
441 
442  /* check our references list */
443  t = (OR_TEMPOID *) o->client_data;
444  if (t == NULL)
445  {
446  /* this is a new OID, add our reference wart */
447  t = (OR_TEMPOID *) malloc (sizeof (OR_TEMPOID));
448  if (t == NULL)
449  {
452  }
453 
454  buf_size = sizeof (void *) * TF_FIXUP_REFERENCE_QUANT;
455  t->references = (void **) malloc (buf_size);
456  if (t->references == NULL)
457  {
458  free_and_init (t);
459 
462  }
464  t->references[0] = ref;
465  t->refcount = 1;
466  o->client_data = (void *) t;
467  }
468  else
469  {
470  /* we've already had at least one reference, add another one */
471  if (t->refcount >= t->refsize)
472  {
473  /* its time to grow */
475  buf_size = t->refsize * sizeof (void *);
476  t->references = (void **) realloc (t->references, buf_size);
477  if (t->references == NULL)
478  {
481  }
482  }
483  t->references[t->refcount] = ref;
484  t->refcount++;
485  }
486 
487  return NO_ERROR;
488 }
489 
490 
491 /*
492  * tf_need_permanent_oid - called when a temporary OID is encountered during
493  * various packing places to ensure permanent oid assignment
494  * return: oid to store
495  * buf(in/out): packing buffer
496  * obj(in): object to examine
497  * Note:
498  * This is called by the various packing functions when they encounter
499  * a temporary OID that needs to be packed. If this is an INSTANCE OID,
500  * and we're maintaining a deferred "fixup" buffer, then we return a NULL
501  * oid and add an entry to the fixup state.
502  *
503  * If this is a CLASS OID, or if we're not maintaining a fixup buffer,
504  * then we simply call locator_assign_permanent_oid to immeidately get a
505  * permanent OID.
506  *
507  * The oid returned by this function does not need to be freed but it
508  * must be used or copied immediately.
509  *
510  * NULL is returned on error.
511  */
512 OID *
514 {
515  OID *oidp;
516 
517  oidp = NULL;
518 
519  /*
520  * if we have a fixup buffer, and this is NOT a class object, then make
521  * an entry for it.
522  */
523  if (tf_Allow_fixups && buf->fixups != NULL && obj->class_mop != NULL && obj->class_mop != sm_Root_class_mop)
524  {
525 
526  if (tf_add_fixup (buf->fixups, obj, buf->ptr) != NO_ERROR)
527  {
528  or_abort (buf);
529  }
530  else
531  {
532  /* leave the NULL oid in the buffer until we can fix it */
533  oidp = (OID *) (&oid_Null_oid);
534  }
535  }
536  else
537  {
538  /*
539  * couldn't make a fixup buffer entry, go to the server and assign
540  * it in the usual way.
541  */
542  if (locator_assign_permanent_oid (obj) == NULL)
543  {
544  if (er_errid () == NO_ERROR)
545  {
547  }
548 
549  /* this is serious */
550  or_abort (buf);
551  }
552  else
553  {
554  oidp = WS_OID (obj);
555  }
556  }
557  return oidp;
558 }
559 
560 
561 /*
562  * fixup_callback - LC_OIDMAP_CALLBACK function passed to locator_assign_oidset
563  * by tf_do_fixup function.
564  * return: none
565  * oidmap(in): oidmap being processed
566  * Note:
567  * This function gets called for each oid that has been made permanent,
568  * here we get our client appendage out of the client_data field, then
569  * whip through the references list so that they can be properly updated.
570  */
571 static void
573 {
574  OR_TEMPOID *t;
575  int i;
576 
577  t = (OR_TEMPOID *) oidmap->client_data;
578  if (t != NULL)
579  {
580  /* fix the packed references */
581  for (i = 0; i < t->refcount; i++)
582  {
583  OR_PUT_OID (t->references[i], &(oidmap->oid));
584  }
585  }
586 }
587 
588 
589 /*
590  * tf_do_fixup - Process the fixup operations left over after a transformation.
591  * return: error code
592  * fix(): fixup state
593  */
594 static int
596 {
597  int error = NO_ERROR;
598 
599  if (fix != NULL && fix->oidset != NULL)
600  {
602  }
603 
604  return error;
605 }
606 
607 
608 /*
609  * put_varinfo - Write the variable attribute offset table for an instance.
610  * return: NO_ERROR
611  * buf(in/out): translation buffer
612  * obj(in): instance memory
613  * class(in): class of instance
614  */
615 static int
616 put_varinfo (OR_BUF * buf, char *obj, SM_CLASS * class_, int offset_size)
617 {
618  SM_ATTRIBUTE *att;
619  char *mem;
620  int a, offset, len;
621  int rc = NO_ERROR;
622 
623  if (class_->variable_count)
624  {
625  /* compute the variable offsets relative to the end of the header (beginning of variable table) */
626  offset =
628  offset_size) + class_->fixed_size + OR_BOUND_BIT_BYTES (class_->fixed_count);
629 
630  for (a = class_->fixed_count; a < class_->att_count; a++)
631  {
632  att = &class_->attributes[a];
633  mem = obj + att->offset;
634 
635  len = att->domain->type->get_disk_size_of_mem (mem, att->domain);
636 
637  or_put_offset_internal (buf, offset, offset_size);
638  offset += len;
639  }
640 
641  or_put_offset_internal (buf, offset, offset_size);
642  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
643  }
644  return rc;
645 }
646 
647 
648 /*
649  * object_size - Calculates the amount of disk storage required for an instance.
650  * return: bytes of disk storage required
651  * class(in): class structure
652  * obj(in): instance to examine
653  */
654 static int
655 object_size (SM_CLASS * class_, MOBJ obj, int *offset_size_ptr)
656 {
657  SM_ATTRIBUTE *att;
658  char *mem;
659  int a, size;
660 
661  *offset_size_ptr = OR_BYTE_SIZE;
662 
663 re_check:
664 
666 
667  if (class_->variable_count)
668  {
669  size += OR_VAR_TABLE_SIZE_INTERNAL (class_->variable_count, *offset_size_ptr);
670  for (a = class_->fixed_count; a < class_->att_count; a++)
671  {
672  att = &class_->attributes[a];
673  mem = obj + att->offset;
674 
675  size += att->domain->type->get_disk_size_of_mem (mem, att->domain);
676  }
677  }
678 
679  if (*offset_size_ptr == OR_BYTE_SIZE && size > OR_MAX_BYTE)
680  {
681  *offset_size_ptr = OR_SHORT_SIZE; /* 2byte */
682  goto re_check;
683  }
684  if (*offset_size_ptr == OR_SHORT_SIZE && size > OR_MAX_SHORT)
685  {
686  *offset_size_ptr = BIG_VAR_OFFSET_SIZE; /* 4byte */
687  goto re_check;
688  }
689  return (size);
690 }
691 
692 
693 /*
694  * put_attributes - Write the fixed and variable attribute values.
695  * return: on overflow, or_overflow will call longjmp and jump to the
696  * outer caller
697  * buf(in/out): translation buffer
698  * obj(in): instance memory
699  * class(in): class structure
700  * Note:
701  * The object header and offset table will already have been written.
702  * Assumes that the schema manager is smart enough to keep the
703  * attributes in their appropriate disk ordering.
704  */
705 static int
706 put_attributes (OR_BUF * buf, char *obj, SM_CLASS * class_)
707 {
708  SM_ATTRIBUTE *att;
709  char *start;
710  int pad;
711 
712  /*
713  * write fixed attribute values, if unbound, leave zero or garbage
714  * it doesn't really matter.
715  */
716  start = buf->ptr;
717  for (att = class_->attributes; att != NULL && !att->type->variable_p; att = (SM_ATTRIBUTE *) att->header.next)
718  {
719  att->type->data_writemem (buf, obj + att->offset, att->domain);
720  }
721 
722  /* bring the end of the fixed width block up to proper alignment */
723  pad = (int) (buf->ptr - start);
724  if (pad < class_->fixed_size)
725  {
726  or_pad (buf, class_->fixed_size - pad);
727  }
728  else if (pad > class_->fixed_size)
729  { /* mismatched fixed block calculations */
731  or_abort (buf);
732  }
733 
734  /* write the bound bits */
735  if (class_->fixed_count)
736  {
738  }
739  /* write the variable attributes */
740 
741  for (; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
742  {
743  att->type->data_writemem (buf, obj + att->offset, att->domain);
744  }
745  return NO_ERROR;
746 }
747 
748 
749 /*
750  * tf_mem_to_disk - Translate an instance from its memory format into the
751  * disk format.
752  * return: zero on success, non-zero on error
753  * classmop(in): class of this instance
754  * classobj(in): class structure
755  * obj(in/out): instance memory to translate
756  * record(out): destination disk record
757  * index_flag(out): set if there are indexes on any attributes
758  * Note:
759  * If there was an overflow error on the given record, we determine
760  * the required size and return this size as a negative number, otherwise
761  * a zero is returned to indicate successful translation.
762  * Note that volatile is used here to prevent the compiler from
763  * optimizing variables into registers that aren't preserved by
764  * setjmp/longjmp.
765  */
766 TF_STATUS
767 tf_mem_to_disk (MOP classmop, MOBJ classobj, MOBJ volatile obj, RECDES * record, bool * index_flag)
768 {
769  OR_BUF orep, *buf;
770  SM_CLASS *volatile class_; /* prevent register optimization */
771  int chn;
772  bool has_index = false;
773  unsigned int repid_bits;
774  TF_STATUS status;
775  volatile int expected_size;
776  volatile int offset_size;
777 
778  buf = &orep;
779  or_init (buf, record->data, record->area_size);
780  buf->error_abort = 1;
781 
782  if (tf_Allow_fixups)
783  {
784  buf->fixups = tf_make_fixup ();
785  if (buf->fixups == NULL)
786  {
787  return TF_ERROR;
788  }
789  }
790 
791  class_ = (SM_CLASS *) classobj;
792 
793  if (optimize_sets (class_, obj) != NO_ERROR)
794  {
795  if (tf_Allow_fixups)
796  {
797  tf_free_fixup (buf->fixups);
798  }
799  return TF_ERROR;
800  }
801 
802  expected_size = object_size (class_, obj, (int *) &offset_size);
803  if ((expected_size + OR_MVCC_MAX_HEADER_SIZE - OR_MVCC_INSERT_HEADER_SIZE) > record->area_size)
804  {
805  record->length = -expected_size;
806 
807  /* make sure we free this */
808  if (tf_Allow_fixups)
809  {
810  tf_free_fixup (buf->fixups);
811  }
812 
813  *index_flag = false;
814  return (TF_OUT_OF_SPACE);
815  }
816 
817  switch (_setjmp (buf->env))
818  {
819  case 0:
820  status = TF_SUCCESS;
821 
822  if (OID_ISTEMP (WS_OID (classmop)))
823  {
824  /*
825  * since this isn't a mem_oid, can't rely on write_oid to do this,
826  * don't bother making this part of the deferred fixup stuff yet.
827  */
828  if (locator_assign_permanent_oid (classmop) == NULL)
829  {
830  if (er_errid () == NO_ERROR)
831  {
833  }
834 
835  or_abort (buf);
836  }
837  }
838 
839  /* header */
840 
841  repid_bits = class_->repid;
842  if (class_->fixed_count)
843  {
844  repid_bits |= OR_BOUND_BIT_FLAG;
845  }
846  /* offset size */
847  OR_SET_VAR_OFFSET_SIZE (repid_bits, offset_size);
848 
849  chn = WS_CHN (obj) + 1;
850 
851  /* in most of the cases, we expect the MVCC header of a new object to have OR_MVCC_FLAG_VALID_INSID flag,
852  * repid_bits, MVCC insert id and chn. This header may be changed later, at insert/update. So, we must be sure
853  * that the record has enough free space. */
854 
856  or_put_int (buf, repid_bits);
857  or_put_int (buf, chn); /* CHN, short size */
858  or_put_bigint (buf, MVCCID_NULL); /* MVCC insert id */
859 
860  /* variable info block */
861  put_varinfo (buf, obj, class_, offset_size);
862 
863  /* attributes, fixed followed by variable */
864  put_attributes (buf, obj, class_);
865 
866  record->length = (int) (buf->ptr - buf->buffer);
867 
868  /* see if there are any indexes */
869  has_index = classobj_class_has_indexes (class_);
870 
871  /*
872  * assign permanent OID's and make the necessary adjustments in
873  * the packed buffer.
874  */
875  if (tf_do_fixup (buf->fixups) != NO_ERROR)
876  {
877  status = TF_ERROR;
878  }
879 
880  /*
881  * Now that we know the object has been packed up safely, it's safe
882  * to update the coherency number of the in-memory image.
883  */
884  WS_CHN (obj) = chn;
885 
886  break;
887 
888  /* if the longjmp status was anything other than ER_TF_BUFFER_OVERFLOW, it represents an error condition and
889  * er_set will have been called */
891  status = TF_OUT_OF_SPACE;
892  record->length = -expected_size;
893  has_index = false;
894  break;
895 
896  default:
897  status = TF_ERROR;
898  has_index = false;
899  break;
900  }
901 
902  /* make sure we free this */
903  if (tf_Allow_fixups)
904  {
905  tf_free_fixup (buf->fixups);
906  }
907 
908  *index_flag = has_index;
909 
910  buf->error_abort = 0;
911  return (status);
912 }
913 
914 
915 /*
916  * get_current - Loads an instance from disk using the latest class
917  * representation.
918  * return: new instance memory
919  * buf(in/out): translation buffer
920  * class(): class of this instance
921  * obj_ptr(out): loaded object (same as return value)
922  * bound_bit_flag(in): initial status of bound bits
923  */
924 static char *
925 get_current (OR_BUF * buf, SM_CLASS * class_, MOBJ * obj_ptr, int bound_bit_flag, int offset_size)
926 {
927  SM_ATTRIBUTE *att;
928  char *obj, *mem, *start;
929  int *vars, rc = NO_ERROR;
930  int i, j, offset, offset2, pad;
931 
932  obj = NULL;
933  /* need nicer way to store these */
934  vars = NULL;
935  if (class_->variable_count)
936  {
937  vars = (int *) db_ws_alloc (sizeof (int) * class_->variable_count);
938  if (vars == NULL)
939  {
940  or_abort (buf);
941  }
942  else
943  {
944  /* get the offsets relative to the end of the header (beginning of variable table) */
945  offset = or_get_offset_internal (buf, &rc, offset_size);
946  for (i = 0; i < class_->variable_count; i++)
947  {
948  offset2 = or_get_offset_internal (buf, &rc, offset_size);
949  vars[i] = offset2 - offset;
950  offset = offset2;
951  }
952  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
953  }
954  }
955 
956  /*
957  * if there are no bound bits on disk, allocate the instance block
958  * with all the bits turned on, we have to assume that the values
959  * are non-null
960  */
961  obj = *obj_ptr = obj_alloc (class_, (bound_bit_flag) ? 0 : 1);
962 
963  if (obj == NULL)
964  {
965  if (vars != NULL)
966  {
967  db_ws_free (vars);
968  }
969  or_abort (buf);
970  }
971  else
972  {
973  /* fixed */
974  start = buf->ptr;
975  for (i = 0; i < class_->fixed_count; i++)
976  {
977  att = &(class_->attributes[i]);
978  mem = obj + att->offset;
979  att->type->data_readmem (buf, mem, att->domain, -1);
980  }
981 
982  /* round up to a to the end of the fixed block */
983  pad = (int) (buf->ptr - start);
984  if (pad < class_->fixed_size)
985  {
986  or_advance (buf, class_->fixed_size - pad);
987  }
988  /* bound bits, if not present, we have to assume everything is bound */
989  if (bound_bit_flag && class_->fixed_count)
990  {
992  }
993 
994  /* variable */
995  if (vars != NULL)
996  {
997  for (i = class_->fixed_count, j = 0; i < class_->att_count && j < class_->variable_count; i++, j++)
998  {
999  att = &(class_->attributes[i]);
1000  mem = obj + att->offset;
1001  att->type->data_readmem (buf, mem, att->domain, vars[j]);
1002  }
1003  }
1004  }
1005 
1006  if (vars != NULL)
1007  {
1008  db_ws_free (vars);
1009  }
1010 
1011  return (obj);
1012 }
1013 
1014 
1015 /*
1016  * find_current_attribute - Given an instance attribute id, find the
1017  * corresponding attribute in the latest representation.
1018  * return: pointer to current attribute. NULL if not found
1019  * class(in): class structure
1020  * id(in): attribute id
1021  */
1022 static SM_ATTRIBUTE *
1024 {
1025  SM_ATTRIBUTE *found, *att;
1026 
1027  found = NULL;
1028  for (att = class_->attributes; att != NULL && found == NULL; att = (SM_ATTRIBUTE *) att->header.next)
1029  {
1030  if (att->id == id)
1031  {
1032  found = att;
1033  }
1034  }
1035  return (found);
1036 }
1037 
1038 
1039 /*
1040  * clear_new_unbound - This initializes the space created for instance
1041  * attributes that had no saved values on disk.
1042  * return: void
1043  * obj(in/out): instance memory
1044  * class(in): class of this instance
1045  * oldrep(in): old representation (of instance on disk)
1046  * Note:
1047  * This happens when an object is converted to a new representation
1048  * that had one or more attributes added.
1049  * It might be more efficient to do this for all fields when the instance
1050  * memory is first allocated ?
1051  * The original_value is used if it has a value.
1052  */
1053 static void
1054 clear_new_unbound (char *obj, SM_CLASS * class_, SM_REPRESENTATION * oldrep)
1055 {
1056  SM_ATTRIBUTE *att;
1057  SM_REPR_ATTRIBUTE *rat, *found;
1058  char *mem;
1059 
1060  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
1061  {
1062  found = NULL;
1063  for (rat = oldrep->attributes; rat != NULL && found == NULL; rat = rat->next)
1064  {
1065  if (rat->attid == att->id)
1066  {
1067  found = rat;
1068  }
1069  }
1070  if (found == NULL)
1071  {
1072  mem = obj + att->offset;
1073  /* initialize in case there isn't an initial value */
1074  att->type->initmem (mem, att->domain);
1076  {
1077  /* assign the initial value, should check for non-existance ? */
1078  att->type->setmem (mem, att->domain, &att->default_value.original_value);
1079  if (!att->type->variable_p)
1080  {
1081  OBJ_SET_BOUND_BIT (obj, att->storage_order);
1082  }
1083  }
1084  }
1085  }
1086 }
1087 
1088 
1089 /*
1090  * get_old - This creates an instance from an obsolete disk representation.
1091  * return: new instance memory
1092  * buf(in/out): translation buffer
1093  * class(in): class of this instance
1094  * obj_ptr(out): return value
1095  * repid(in): old representation id
1096  * bound_bit_flag(in): initial status of bound bits
1097  * Note:
1098  * Any new attributes that had no values on disk are given a starting
1099  * value from the "original_value" field in the class.
1100  * Values for deleted attributes are discarded.
1101  */
1102 static char *
1103 get_old (OR_BUF * buf, SM_CLASS * class_, MOBJ * obj_ptr, int repid, int bound_bit_flag, int offset_size)
1104 {
1105  SM_REPRESENTATION *oldrep;
1106  SM_REPR_ATTRIBUTE *rat;
1107  SM_ATTRIBUTE **attmap;
1108  PR_TYPE *type;
1109  char *obj, *bits, *start;
1110  int *vars = NULL, rc = NO_ERROR;
1111  int i, total, offset, offset2, bytes, att_index, padded_size, fixed_size;
1112 
1113  obj = NULL;
1114  oldrep = classobj_find_representation (class_, repid);
1115 
1116  if (oldrep == NULL)
1117  {
1119  }
1120  else
1121  {
1122  /*
1123  * if there are no bound bits on disk, allocate the instance block
1124  * with all the bits turned on, we have to assume that the values
1125  * are non-null
1126  */
1127  obj = *obj_ptr = obj_alloc (class_, (bound_bit_flag) ? 0 : 1);
1128 
1129  if (obj == NULL)
1130  {
1131  or_abort (buf);
1132  }
1133  else
1134  {
1135  /*
1136  * read the variable offset table, can't we just leave this on
1137  * disk ?
1138  */
1139  vars = NULL;
1140  if (oldrep->variable_count)
1141  {
1142  vars = (int *) db_ws_alloc (sizeof (int) * oldrep->variable_count);
1143  if (vars == NULL)
1144  {
1145  or_abort (buf);
1146  return NULL;
1147  }
1148  else
1149  {
1150  /* get the offsets relative to the end of the header (beginning of variable table) */
1151  offset = or_get_offset_internal (buf, &rc, offset_size);
1152  for (i = 0; i < oldrep->variable_count; i++)
1153  {
1154  offset2 = or_get_offset_internal (buf, &rc, offset_size);
1155  vars[i] = offset2 - offset;
1156  offset = offset2;
1157  }
1158  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
1159  }
1160  }
1161 
1162  /* calculate an attribute map */
1163  total = oldrep->fixed_count + oldrep->variable_count;
1164  attmap = NULL;
1165  if (total > 0)
1166  {
1167  attmap = (SM_ATTRIBUTE **) db_ws_alloc (sizeof (SM_ATTRIBUTE *) * total);
1168  if (attmap == NULL)
1169  {
1170  if (vars != NULL)
1171  {
1172  db_ws_free (vars);
1173  }
1174  or_abort (buf);
1175  return NULL;
1176  }
1177  else
1178  {
1179  for (rat = oldrep->attributes, i = 0; rat != NULL; rat = rat->next, i++)
1180  {
1181  attmap[i] = find_current_attribute (class_, rat->attid);
1182  }
1183  }
1184  }
1185 
1186  /* read the fixed attributes */
1187  rat = oldrep->attributes;
1188  start = buf->ptr;
1189  for (i = 0; i < oldrep->fixed_count && rat != NULL && attmap != NULL; i++, rat = rat->next)
1190  {
1191  type = pr_type_from_id (rat->typeid_);
1192  if (type == NULL)
1193  {
1195  sm_ch_name ((MOBJ) class_));
1196 
1197  db_ws_free (attmap);
1198  if (vars != NULL)
1199  {
1200  db_ws_free (vars);
1201  }
1202 
1203  or_abort (buf);
1204  return NULL;
1205  }
1206 
1207  if (attmap[i] == NULL)
1208  {
1209  type->data_readmem (buf, NULL, rat->domain, -1);
1210  }
1211  else
1212  {
1213  type->data_readmem (buf, obj + attmap[i]->offset, rat->domain, -1);
1214  }
1215  }
1216 
1217  fixed_size = (int) (buf->ptr - start);
1218  padded_size = DB_ATT_ALIGN (fixed_size);
1219  or_advance (buf, (padded_size - fixed_size));
1220 
1221 
1222  /*
1223  * sigh, we now have to process the bound bits in much the same way
1224  * as the attributes above, it would be nice if these could be done
1225  * in parallel but we don't have the fixed size of the old
1226  * representation so we can't easily sneak the buffer pointer
1227  * forward, work on this someday
1228  */
1229 
1230  if (bound_bit_flag && oldrep->fixed_count)
1231  {
1232  bits = buf->ptr;
1233  bytes = OR_BOUND_BIT_BYTES (oldrep->fixed_count);
1234  if ((buf->ptr + bytes) > buf->endptr)
1235  {
1236  or_overflow (buf);
1237  }
1238 
1239  rat = oldrep->attributes;
1240  for (i = 0; i < oldrep->fixed_count && rat != NULL && attmap != NULL; i++, rat = rat->next)
1241  {
1242  if (attmap[i] != NULL)
1243  {
1244  if (OR_GET_BOUND_BIT (bits, i))
1245  {
1246  OBJ_SET_BOUND_BIT (obj, attmap[i]->storage_order);
1247  }
1248  }
1249  }
1250  or_advance (buf, bytes);
1251  }
1252 
1253  /* variable */
1254  if (vars != NULL)
1255  {
1256  for (i = 0; i < oldrep->variable_count && rat != NULL && attmap != NULL; i++, rat = rat->next)
1257  {
1258  type = pr_type_from_id (rat->typeid_);
1259  if (type == NULL)
1260  {
1262  sm_ch_name ((MOBJ) class_));
1263 
1264  db_ws_free (attmap);
1265  db_ws_free (vars);
1266 
1267  or_abort (buf);
1268  return NULL;
1269  }
1270 
1271  att_index = oldrep->fixed_count + i;
1272  if (attmap[att_index] == NULL)
1273  {
1274  type->data_readmem (buf, NULL, rat->domain, vars[i]);
1275  }
1276  else
1277  {
1278  type->data_readmem (buf, obj + attmap[att_index]->offset, rat->domain, vars[i]);
1279  }
1280  }
1281  }
1282 
1283  /* should be optimizing this operation ! */
1284  clear_new_unbound (obj, class_, oldrep);
1285 
1286  if (attmap != NULL)
1287  {
1288  db_ws_free (attmap);
1289  }
1290  if (vars != NULL)
1291  {
1292  db_ws_free (vars);
1293  }
1294  }
1295  }
1296 
1297  return (obj);
1298 }
1299 
1300 
1301 /*
1302  * tf_disk_to_mem - Interface function for transforming the disk
1303  * representation of an instance into the memory representation.
1304  * return: MOBJ
1305  * classobj(in): class structure
1306  * record(in): disk record
1307  * convertp(in): set to non-zero if the object had to be converted from
1308  * an obsolete disk representation.
1309  * Note:
1310  * It is imperitive that garbage collection be disabled during this
1311  * operation.
1312  * This is because the structure being built may contain pointers
1313  * to MOPs but it has not itself been attached to its own MOP yet so it
1314  * doesn't serve as a gc root. Make sure the caller
1315  * calls ws_cache() immediately after we return so the new object
1316  * gets attached as soon as possible. We must also have already
1317  * allocated the MOP in the caller so that we don't get one of the
1318  * periodic gc's when we attempt to allocate a new MOP.
1319  * This dependency should be isolated in a ws_ function called by
1320  * the locator.
1321  */
1322 MOBJ
1323 tf_disk_to_mem (MOBJ classobj, RECDES * record, int *convertp)
1324 {
1325  OR_BUF orep, *buf;
1326  SM_CLASS *class_ = NULL;
1327  char *obj = NULL;
1328  unsigned int repid_bits;
1329  int repid, convert, chn, bound_bit_flag;
1330  int rc = NO_ERROR;
1331  int offset_size;
1332  char mvcc_flags;
1333 
1334  buf = &orep;
1335  or_init (buf, record->data, record->length);
1336  buf->error_abort = 1;
1337 
1338  switch (_setjmp (buf->env))
1339  {
1340  case 0:
1341  class_ = (SM_CLASS *) classobj;
1342  obj = NULL;
1343  convert = 0;
1344  /* offset size */
1345  offset_size = OR_GET_OFFSET_SIZE (buf->ptr);
1346 
1347  /* in case of MVCC, repid_bits contains MVCC flags */
1348  repid_bits = or_mvcc_get_repid_and_flags (buf, &rc);
1349  repid = repid_bits & OR_MVCC_REPID_MASK;
1350 
1351  mvcc_flags = (char) ((repid_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
1352 
1353  chn = or_get_int (buf, &rc);
1354 
1355  if (mvcc_flags & OR_MVCC_FLAG_VALID_INSID)
1356  {
1357  /* skip insert id */
1358  or_advance (buf, OR_MVCCID_SIZE);
1359  }
1360 
1361  if (mvcc_flags & OR_MVCC_FLAG_VALID_DELID)
1362  {
1363  /* skip delete id */
1364  or_advance (buf, OR_MVCCID_SIZE);
1365  }
1366 
1367  if (mvcc_flags & OR_MVCC_FLAG_VALID_PREV_VERSION)
1368  {
1369  /* skip prev version lsa */
1371  }
1372 
1373  bound_bit_flag = repid_bits & OR_BOUND_BIT_FLAG;
1374 
1375  if (repid == class_->repid)
1376  {
1377  obj = get_current (buf, class_, &obj, bound_bit_flag, offset_size);
1378  }
1379  else
1380  {
1381  obj = get_old (buf, class_, &obj, repid, bound_bit_flag, offset_size);
1382  convert = 1;
1383  }
1384 
1385  /* set the chn of the object */
1386  if (obj != NULL)
1387  {
1388  WS_CHN (obj) = chn;
1389  }
1390 
1391  *convertp = convert;
1392  break;
1393 
1394  default:
1395  /* make sure to clear the object that was being created, an appropriate error will have been set */
1396  if (obj != NULL)
1397  {
1398  obj_free_memory (class_, obj);
1399  obj = NULL;
1400  }
1401  break;
1402  }
1403 
1404  buf->error_abort = 0;
1405  return (obj);
1406 }
1407 
1408 /*
1409  * unpack_allocator - memory allocator
1410  * return: memory allocated
1411  * size(in): size to allocate
1412  * Note:
1413  * Used in cases where an allocatino function needs to be passed
1414  * to one of the transformation routines.
1415  */
1416 static char *
1418 {
1419  return ((char *) malloc (size));
1420 }
1421 
1422 
1423 /*
1424  * read_var_table - extracts the variable offset table from the disk
1425  * representation and build a more convenient memory representation.
1426  * return: array of OR_VARINFO structures
1427  * buf(in/out): translation buffr
1428  * nvars(in): expected number of variables
1429  */
1430 static OR_VARINFO *
1431 read_var_table (OR_BUF * buf, int nvars)
1432 {
1433  return (read_var_table_internal (buf, nvars, BIG_VAR_OFFSET_SIZE));
1434 }
1435 
1436 /*
1437  * read_var_table_internal - extracts the variable offset table from the disk
1438  * representation and build a more convenient memory representation.
1439  * return: array of OR_VARINFO structures
1440  * buf(in/out): translation buffr
1441  * nvars(in): expected number of variables
1442  */
1443 static OR_VARINFO *
1444 read_var_table_internal (OR_BUF * buf, int nvars, int offset_size)
1445 {
1446  return (or_get_var_table_internal (buf, nvars, unpack_allocator, offset_size));
1447 }
1448 
1449 
1450 /*
1451  * free_var_table - frees a table allocated by read_var_table
1452  * return: void
1453  * vars(out): variable table
1454  */
1455 static void
1457 {
1458  if (vars != NULL)
1459  {
1460  free_and_init (vars);
1461  }
1462 }
1463 
1464 
1465 /*
1466  * string_disk_size - calculate the disk size of a NULL terminated ASCII
1467  * string that is supposed to be stored as a VARNCHAR attribute in one of
1468  * the various class objects.
1469  * return: byte size for packed "varchar" string
1470  * string(in):
1471  */
1472 static int
1473 string_disk_size (const char *string)
1474 {
1475  DB_VALUE value;
1476  int str_length = 0;
1477  int length = 0;
1478 
1479  if (string)
1480  {
1481  str_length = strlen (string);
1482  }
1483  else
1484  {
1485  str_length = 0;
1486  }
1487 
1489  length = tp_VarNChar.get_disk_size_of_value (&value);
1490 
1491  /* Clear the compressed_string of DB_VALUE */
1492  pr_clear_compressed_string (&value);
1493 
1494  return length;
1495 }
1496 
1497 
1498 /*
1499  * get_string - read a string out of the OR_BUF and return it as a NULL
1500  * terminated ASCII string
1501  * return: string from value or NULL
1502  * buf(in/out): translation buffer
1503  * length(in): length of string or -1 if read variable length
1504  * Note:
1505  * Shorthand macro to read a string out of the OR_BUF and return it
1506  * as a NULL terminated ASCII string which everything stored as part
1507  * of the class definition is.
1508  *
1509  * A jmp_buf has previously been established.
1510  */
1511 static char *
1512 get_string (OR_BUF * buf, int length)
1513 {
1514  DB_VALUE value;
1515  DB_DOMAIN my_domain;
1516  char *string = NULL;
1517 
1518  /*
1519  * Make sure this starts off initialized so "readval" won't try to free
1520  * any existing contents.
1521  */
1522  db_make_null (&value);
1523 
1524  /*
1525  * The domain here is always a server side VARNCHAR. Set a temporary
1526  * domain to reflect this.
1527  */
1529 
1530  my_domain.codeset = lang_charset ();
1531  my_domain.collation_id = LANG_SYS_COLLATION;
1533 
1534  tp_VarNChar.data_readval (buf, &value, &my_domain, length, false, NULL, 0);
1535 
1536  if (DB_VALUE_TYPE (&value) == DB_TYPE_VARNCHAR)
1537  {
1538  string = ws_copy_string (db_get_string (&value));
1539  }
1540 
1541  db_value_clear (&value);
1542 
1543  return string;
1544 }
1545 
1546 
1547 /*
1548  * put_string - Put a NULL terminated ASCII string into the disk buffer in the
1549  * usual way.
1550  * return: void
1551  * buf(in/out): translation buffer
1552  * string(in): string to store
1553  * Note:
1554  * See get_string & string_disk_size for the related functions.
1555  */
1556 static void
1557 put_string (OR_BUF * buf, const char *string)
1558 {
1559  DB_VALUE value;
1560  int str_length = 0;
1561 
1562  if (string)
1563  {
1564  str_length = strlen (string);
1565  }
1566  else
1567  {
1568  str_length = 0;
1569  }
1570 
1572  tp_VarNChar.data_writeval (buf, &value);
1573  pr_clear_value (&value);
1574 }
1575 
1576 /*
1577  * SET SUPPORT FUNCTIONS
1578  *
1579  * These make it easier to read and write object and substructure sets
1580  * which are used often in a class's disk representation.
1581  *
1582  * SUBSTRUCTURE SET RULES
1583  *
1584  * The set header containing type and count is always present.
1585  * The variable offset table is present only if there are elements.
1586  * The substructure tag is present only if there are elements.
1587  *
1588  */
1589 
1590 /*
1591  * object_set_size - Calculates the disk storage required for a set of object
1592  * pointers.
1593  * return: byte size for a set of OIDs
1594  * list(in): object list
1595  */
1596 static int
1598 {
1599  DB_OBJLIST *l;
1600  int count, size;
1601 
1602  /* store NULL for empty set */
1603  if (list == NULL)
1604  {
1605  return 0;
1606  }
1607 
1608  size = 0;
1609  for (count = 0, l = list; l != NULL; l = l->next)
1610  {
1611  if (WS_IS_DELETED (l->op))
1612  {
1613  continue;
1614  }
1615  count++;
1616  }
1617 
1618  if (count == 0)
1619  {
1620  return 0;
1621  }
1622 
1623  size += OR_SET_HEADER_SIZE;
1624  size += OR_INT_SIZE; /* size of domain word */
1625  size += OR_INT_SIZE; /* size of the built-in object domain */
1626  size += (count * tp_Object.disksize);
1627 
1628  return (size);
1629 }
1630 
1631 /*
1632  * or_pack_mop - write an OID to a disk representation buffer given a MOP
1633  * instead of a WS_MEMOID.
1634  * return:
1635  * buf(): transformer buffer
1636  * mop(): mop to transform
1637  * Note:
1638  * mr_write_object can't be used because it takes a WS_MEMOID as is the
1639  * case for object references in instances.
1640  * This must stay in sync with mr_write_object above !
1641  */
1642 static void
1643 or_pack_mop (OR_BUF * buf, MOP mop)
1644 {
1645  DB_VALUE value;
1646 
1647  tp_Object.initval (&value, 0, 0);
1648  db_make_object (&value, mop);
1649  tp_Object.data_writeval (buf, &value);
1650  tp_Object.setval (&value, NULL, false);
1651 }
1652 
1653 /*
1654  * put_object_set - Translates a list objects into the disk representation of a
1655  * sequence of objects
1656  * return: on overflow, or_overflow will call longjmp and jump to the outer
1657  * caller
1658  * buf(in/out): translation buffer
1659  * list(in): object list
1660  */
1661 static int
1663 {
1664  DB_OBJLIST *l;
1665  int count;
1666 
1667  /* store NULL for empty set */
1668  if (list == NULL)
1669  return ER_FAILED;
1670 
1671  for (count = 0, l = list; l != NULL; l = l->next)
1672  {
1673  if (WS_IS_DELETED (l->op))
1674  {
1675  continue;
1676  }
1677  count++;
1678  }
1679 
1680  if (count == 0)
1681  {
1682  return NO_ERROR;
1683  }
1684 
1685  /* w/ domain, no bound bits, no offsets, no tags, no substructure header */
1686  or_put_set_header (buf, DB_TYPE_SEQUENCE, count, 1, 0, 0, 0, 0);
1687 
1688  /* use the generic "object" domain */
1689  or_put_int (buf, OR_INT_SIZE); /* size of the domain */
1690  or_put_domain (buf, &tp_Object_domain, 0, 0); /* actual domain */
1691 
1692  /* should be using something other than or_pack_mop here ! */
1693  for (l = list; l != NULL; l = l->next)
1694  {
1695  if (WS_IS_DELETED (l->op))
1696  {
1697  continue;
1698  }
1699  or_pack_mop (buf, l->op);
1700  }
1701 
1702  return NO_ERROR;
1703 }
1704 
1705 /*
1706  * get_object_set - Extracts a sequence of objects in a disk representation
1707  * and converts it into an object list in memory.
1708  * return: object list NOTE: a jmp_buf has previously been established.
1709  * buf(in/out): translation buffer
1710  * expected(in): expected length
1711  */
1712 static DB_OBJLIST *
1713 get_object_set (OR_BUF * buf, int expected)
1714 {
1715  DB_OBJLIST *list;
1716  MOP op;
1717  DB_VALUE value;
1718  int count, i;
1719 
1720  /* handle NULL case, variable width will be zero */
1721  if (expected == 0)
1722  {
1723  return NULL;
1724  }
1725 
1726  list = NULL;
1727  count = or_skip_set_header (buf);
1728  for (i = 0; i < count; i++)
1729  {
1730  /*
1731  * Get a MOP, could assume classes mops here and make sure the resulting
1732  * MOP is stamped with the sm_Root_class_mop class ?
1733  */
1734  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
1735  op = db_get_object (&value);
1736  if (op != NULL)
1737  {
1738  if (ml_append (&list, op, NULL))
1739  {
1740  /* memory error */
1741  or_abort (buf);
1742  }
1743  }
1744  }
1745 
1746  return (list);
1747 }
1748 
1749 /*
1750  * substructure_set_size - Calculates the disk storage for a set created from
1751  * a list of memory elements.
1752  * return: byte of disk storage required
1753  * list(in): list of elements
1754  * function(in): function to calculate element sizes
1755  * Note:
1756  * The supplied function is used to find the size of the list elements.
1757  * Even if the list is empty, there will always be at least a set header
1758  * written to disk.
1759  */
1760 static int
1762 {
1763  DB_LIST *l;
1764  int size, count;
1765 
1766  /* store NULL for empty list */
1767  if (list == NULL)
1768  {
1769  return 0;
1770  }
1771 
1772  /* header + domain length word + domain */
1774 
1775  count = 0;
1776  for (l = list; l != NULL; l = l->next, count++)
1777  {
1778  size += (*function) (l);
1779  }
1780 
1781  if (count)
1782  {
1783  /*
1784  * we have elements to store, in that case we need to add the
1785  * common substructure header at the front and an offset table
1786  */
1787  size += OR_VAR_TABLE_SIZE (count);
1788  size += OR_SUB_HEADER_SIZE;
1789  }
1790 
1791  return (size);
1792 }
1793 
1794 /*
1795  * put_substructure_set - Write the disk representation of a substructure
1796  * set from a linked list of structures.
1797  * return: void
1798  * buf(in/out): translation buffer
1799  * list(in): substructure list
1800  * writer(in): translation function
1801  * class(in): OID of meta class for this substructure
1802  * repid(in): repid for the meta class
1803  * Note:
1804  * The supplied functions calculate the size and write the elements.
1805  * The OID/repid for the metaclass will be one of the meta classes
1806  * defined in the catalog.
1807  */
1808 static void
1809 put_substructure_set (OR_BUF * buf, DB_LIST * list, LWRITER writer, OID * class_, int repid)
1810 {
1811  DB_LIST *l;
1812  char *start;
1813  int count;
1814  char *offset_ptr;
1815 
1816  /* store NULL for empty list */
1817  if (list == NULL)
1818  {
1819  return;
1820  }
1821 
1822  count = 0;
1823  for (l = list; l != NULL; l = l->next, count++);
1824 
1825  /* with domain, no bound bits, with offsets, no tags, common sub header */
1826  start = buf->ptr;
1827  or_put_set_header (buf, DB_TYPE_SEQUENCE, count, 1, 0, 1, 0, 1);
1828 
1829  if (!count)
1830  {
1831  /* we must at least store the domain even though there will be no elements */
1833  or_put_sub_domain (buf);
1834  }
1835  else
1836  {
1837  /* begin an offset table */
1838  offset_ptr = buf->ptr;
1839  or_advance (buf, OR_VAR_TABLE_SIZE (count));
1840 
1841  /* write the domain */
1843  or_put_sub_domain (buf);
1844 
1845  /* write the common substructure header */
1846  or_put_oid (buf, class_);
1847  or_put_int (buf, repid);
1848  or_put_int (buf, 0); /* flags */
1849 
1850  /* write each substructure */
1851  for (l = list; l != NULL; l = l->next)
1852  {
1853  /* determine the offset to the this element and put it in the table */
1854  OR_PUT_OFFSET (offset_ptr, (buf->ptr - start));
1855  offset_ptr += BIG_VAR_OFFSET_SIZE;
1856  /* write the substructure */
1857  (*writer) (buf, l);
1858  }
1859  /* write the final offset */
1860  OR_PUT_OFFSET (offset_ptr, (buf->ptr - start));
1861  }
1862 }
1863 
1864 /*
1865  * get_substructure_set - extracts a substructure set on disk and create a
1866  * list of memory structures.
1867  * return: list of structures
1868  * buf(in/out): translation buffer
1869  * reader(in): function to read the elements
1870  * expected(in): expected size
1871  * Note:
1872  * It is important that the elements be APPENDED here.
1873  */
1874 static DB_LIST *
1875 get_substructure_set (OR_BUF * buf, LREADER reader, int expected)
1876 {
1877  DB_LIST *list, *obj;
1878  int count, i;
1879 
1880  /* handle NULL case, variable width will be zero */
1881  if (expected == 0)
1882  {
1883  return NULL;
1884  }
1885 
1886  list = NULL;
1887  count = or_skip_set_header (buf);
1888  for (i = 0; i < count; i++)
1889  {
1890  obj = (*reader) (buf);
1891  if (obj != NULL)
1892  {
1893  WS_LIST_APPEND (&list, obj);
1894  }
1895  else
1896  {
1897  or_abort (buf);
1898  }
1899  }
1900  return (list);
1901 }
1902 
1903 /*
1904  * install_substructure_set - loads a substructure set from disk into a list
1905  * of memory structures.
1906  * return: void
1907  * buf(in/out): translation buffer
1908  * list(in): threaded array of structures
1909  * reader(in): function to read elements
1910  * expected(in): expected size;
1911  * Note:
1912  * The difference is this function does not allocate storage for the
1913  * elements, these have been previously allocated and are simply filled in
1914  * by the reader.
1915  */
1916 static void
1917 install_substructure_set (OR_BUF * buf, DB_LIST * list, VREADER reader, int expected)
1918 {
1919  DB_LIST *p;
1920  int count, i;
1921 
1922  if (expected)
1923  {
1924  count = or_skip_set_header (buf);
1925  for (i = 0, p = list; i < count && p != NULL; i++, p = p->next)
1926  {
1927  (*reader) (buf, p);
1928  }
1929  }
1930 }
1931 
1932 /*
1933  * property_list_size - Calculate the disk storage requirements for a
1934  * property list.
1935  * return: byte size of property list
1936  * properties(in): property list
1937  */
1938 static int
1940 {
1941  DB_VALUE value;
1942  int size, max;
1943 
1944  size = 0;
1945  if (properties != NULL)
1946  {
1947  /* collapse empty property sequences to NULL values on disk */
1948  max = set_size (properties);
1949  if (max)
1950  {
1951  db_make_sequence (&value, properties);
1952  size = tp_Sequence.get_disk_size_of_value (&value);
1953  }
1954  }
1955  return size;
1956 }
1957 
1958 /*
1959  * put_property_list - Write the disk representation of a property list.
1960  * return: void
1961  * buf(in/out): translation buffer
1962  * properties(in): property list
1963  */
1964 static void
1965 put_property_list (OR_BUF * buf, DB_SEQ * properties)
1966 {
1967  DB_VALUE value;
1968  int max;
1969 
1970  if (properties == NULL)
1971  {
1972  return;
1973  }
1974  /* collapse empty property sequences to NULL values on disk */
1975  max = set_size (properties);
1976  if (max)
1977  {
1978  db_make_sequence (&value, properties);
1979  tp_Sequence.data_writeval (buf, &value);
1980  }
1981 }
1982 
1983 /*
1984  * get_property_list - This reads a property list from disk.
1985  * return: a new property list
1986  * buf(in/out): translation buffer
1987  * expected_size(in): number of bytes on disk
1988  * Note:
1989  * This reads a property list from disk.
1990  * If either the expected size is zero, NULL is returned.
1991  * If a sequence was stored on disk but it had no elements, NULL is
1992  * returned and the empty sequence is freed. This is to handle the
1993  * case where old style class objects had an empty substructure set
1994  * stored at this position. Since these will be converted to property
1995  * lists, we can just ignore them.
1996  *
1997  * A jmp_buf has previously been established.
1998  */
1999 static DB_SEQ *
2000 get_property_list (OR_BUF * buf, int expected_size)
2001 {
2002  DB_VALUE value;
2003  DB_SEQ *properties;
2004  int max;
2005 
2006  properties = NULL;
2007  if (expected_size)
2008  {
2009  tp_Sequence.data_readval (buf, &value, NULL, expected_size, true, NULL, 0);
2010  properties = db_get_set (&value);
2011  if (properties == NULL)
2012  or_abort (buf); /* trouble allocating a handle */
2013  else
2014  {
2015  max = set_size (properties);
2016  if (!max)
2017  {
2018  /*
2019  * there is an empty sequence here, get rid of it so we don't
2020  * have to carry it around
2021  */
2022  set_free (properties);
2023  properties = NULL;
2024  }
2025  }
2026  }
2027  return (properties);
2028 }
2029 
2030 /*
2031  * domain_size - Calculates the number of bytes required to store a domain
2032  * list on disk.
2033  * return: disk size of domain
2034  * domain(in): domain list
2035  */
2036 static int
2038 {
2039  int size;
2040 
2042 
2043  size += enumeration_size (&DOM_GET_ENUMERATION (domain));
2044 
2045  size += substructure_set_size ((DB_LIST *) domain->setdomain, (LSIZER) domain_size);
2046 
2047  size += (domain->json_validator == NULL
2049 
2050  return (size);
2051 }
2052 
2053 
2054 /*
2055  * domain_to_disk - Translates a domain list to its disk representation.
2056  * return: void
2057  * buf(in/out): translation buffer
2058  * domain(in): domain list
2059  * Note:
2060  * Translates a domain list to its disk representation.
2061  */
2062 static void
2064 {
2065  char *start;
2066  int offset;
2067  DB_VALUE schema_value;
2068 
2069  /* safe-guard : domain collation flags should only be used for execution */
2071  {
2072  assert (false);
2074  }
2075 
2076  /* VARIABLE OFFSET TABLE */
2077  start = buf->ptr;
2079 
2080  or_put_offset (buf, offset);
2081  offset += substructure_set_size ((DB_LIST *) domain->setdomain, (LSIZER) domain_size);
2082 
2083  or_put_offset (buf, offset);
2084  offset += enumeration_size (&DOM_GET_ENUMERATION (domain));
2085 
2086  or_put_offset (buf, offset);
2087  offset += (domain->json_validator == NULL
2089 
2090  or_put_offset (buf, offset);
2091  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2092 
2093  /* ATTRIBUTES */
2094  or_put_int (buf, (int) TP_DOMAIN_TYPE (domain));
2095  or_put_int (buf, domain->precision);
2096  or_put_int (buf, domain->scale);
2097  or_put_int (buf, domain->codeset);
2098  or_put_int (buf, domain->collation_id);
2099  or_pack_mop (buf, domain->class_mop);
2100 
2103 
2104  put_enumeration (buf, &DOM_GET_ENUMERATION (domain));
2105 
2106  if (domain->json_validator)
2107  {
2109  tp_String.data_writeval (buf, &schema_value);
2110  pr_clear_value (&schema_value);
2111  }
2112  if (start + offset != buf->ptr)
2113  {
2115  }
2116 }
2117 
2118 /*
2119  * disk_to_domain2 - Create the memory representation for a domain list from
2120  * the disk representation.
2121  * return: domain structure
2122  * buf(in/out): translation buffer
2123  * Note:
2124  * This builds a transient domain, it is called by disk_to_domain which
2125  * just turns around and caches it.
2126  *
2127  * A jmp_buf has previously been established.
2128  */
2129 static TP_DOMAIN *
2131 {
2132  OR_VARINFO *vars;
2133  TP_DOMAIN *domain;
2134  DB_TYPE typeid_;
2135  OID oid;
2136  int rc = NO_ERROR;
2137 
2139  if (vars == NULL)
2140  {
2141  or_abort (buf);
2142  return NULL;
2143  }
2144 
2145  typeid_ = (DB_TYPE) or_get_int (buf, &rc);
2146 
2147  domain = tp_domain_new (typeid_);
2148  if (domain == NULL)
2149  {
2150  free_var_table (vars);
2151  or_abort (buf);
2152  return NULL;
2153  }
2154 
2155  domain->precision = or_get_int (buf, &rc);
2156  domain->scale = or_get_int (buf, &rc);
2157  domain->codeset = or_get_int (buf, &rc);
2158  domain->collation_id = or_get_int (buf, &rc);
2159  if (typeid_ == DB_TYPE_ENUMERATION && domain->codeset == 0)
2160  {
2162  domain->codeset = INTL_CODESET_ISO88591;
2163  }
2164  /*
2165  * Read the domain class OID without promoting it to a MOP.
2166  * Could use readval, and extract the OID out of the already swizzled
2167  * MOP too.
2168  */
2169  tp_Oid.data_readmem (buf, &oid, NULL, -1);
2170  domain->class_oid = oid;
2171 
2172  /* swizzle the pointer, we know we're on the client here */
2173  if (!OID_ISNULL (&domain->class_oid))
2174  {
2175  domain->class_mop = ws_mop (&domain->class_oid, NULL);
2176  if (domain->class_mop == NULL)
2177  {
2178  free_var_table (vars);
2179  or_abort (buf);
2180  }
2181  }
2184  domain->enumeration.collation_id = domain->collation_id;
2185 
2186  if (get_enumeration (buf, &DOM_GET_ENUMERATION (domain), vars[ORC_DOMAIN_ENUMERATION_INDEX].length) != NO_ERROR)
2187  {
2188  free_var_table (vars);
2189  tp_domain_free (domain);
2190  or_abort (buf);
2191  return NULL;
2192  }
2193 
2194  if (vars[ORC_DOMAIN_SCHEMA_JSON_OFFSET].length > 0)
2195  {
2196  char *schema_raw;
2197  int error_code;
2198 
2199  or_get_json_schema (buf, schema_raw);
2200  if (schema_raw == NULL)
2201  {
2203  vars[ORC_DOMAIN_SCHEMA_JSON_OFFSET].length + 1);
2204  tp_domain_free (domain);
2205  free_var_table (vars);
2206  return NULL;
2207  }
2208 
2209  error_code = db_json_load_validator (schema_raw, domain->json_validator);
2210  if (error_code != NO_ERROR)
2211  {
2212  assert_release (false);
2213  tp_domain_free (domain);
2214  free_var_table (vars);
2215  db_private_free_and_init (NULL, schema_raw);
2216  return NULL;
2217  }
2218  db_private_free_and_init (NULL, schema_raw);
2219  }
2220 
2221  free_var_table (vars);
2222 
2223  return (domain);
2224 }
2225 
2226 /*
2227  * disk_to_domain - Create the memory representation for a domain list from
2228  * the disk representation.
2229  * return: domain structure
2230  * buf(in/out): translation buffer
2231  * Note:
2232  * Calls disk_to_domain2 which builds the transient domain which we
2233  * then cache when we're done.
2234  * We need to separate the two operations because disk_to_domain2 is
2235  * called recursively for nested domains and we don't want to
2236  * cache each of those.
2237  */
2238 static TP_DOMAIN *
2240 {
2241  TP_DOMAIN *domain;
2242 
2243  domain = disk_to_domain2 (buf);
2244 
2245  if (domain != NULL)
2246  {
2247  domain = tp_domain_cache (domain);
2248  }
2249  return domain;
2250 }
2251 
2252 
2253 /*
2254  * metharg_to_disk - Write the memory representation of a method argument to
2255  * disk.
2256  * return: void
2257  * buf(in/out): translation buffer
2258  * arg(in): method argument
2259  * Note:
2260  * Write the memory representation of a method argument to disk.
2261  * On overflow, or_overflow will call longjmp and jump to the outer caller
2262  */
2263 static void
2265 {
2266  char *start;
2267  int offset;
2268 
2269  /* VARIABLE OFFSET TABLE */
2270  start = buf->ptr;
2272  or_put_offset (buf, offset);
2273  offset += substructure_set_size ((DB_LIST *) arg->domain, (LSIZER) domain_size);
2274  or_put_offset (buf, offset);
2275  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2276 
2277  /* ATTRIBUTES */
2278  /* note that arguments can be empty, in which case they are untyped */
2279  if (arg->type == NULL)
2280  {
2281  or_put_int (buf, (int) DB_TYPE_NULL);
2282  }
2283  else
2284  {
2285  or_put_int (buf, (int) arg->type->id);
2286  }
2287 
2288  or_put_int (buf, arg->index);
2289 
2292 
2293  if (start + offset != buf->ptr)
2294  {
2296  }
2297 }
2298 
2299 /*
2300  * metharg_size - Calculate the byte size for the disk representation of a
2301  * method arg.
2302  * return: disk size of method argument
2303  * arg(in): argument
2304  */
2305 static int
2307 {
2308  int size;
2309 
2311  size += substructure_set_size ((DB_LIST *) arg->domain, (LSIZER) domain_size);
2312 
2313  return (size);
2314 }
2315 
2316 /*
2317  * disk_to_metharg - Read the disk represenation of a method argument and
2318  * build the memory representation.
2319  * return: new method argument
2320  * buf(in/out): translation buffer
2321  */
2322 static SM_METHOD_ARGUMENT *
2324 {
2325  OR_VARINFO *vars;
2326  SM_METHOD_ARGUMENT *arg;
2327  DB_TYPE argtype;
2328  int rc = NO_ERROR;
2329 
2331  if (vars == NULL)
2332  {
2333  or_abort (buf);
2334  return NULL;
2335  }
2336 
2337  arg = classobj_make_method_arg (0);
2338  if (arg == NULL)
2339  {
2340  or_abort (buf);
2341  }
2342  else
2343  {
2344  argtype = (DB_TYPE) or_get_int (buf, &rc);
2345  if (argtype == DB_TYPE_NULL)
2346  {
2347  arg->type = NULL;
2348  }
2349  else
2350  {
2351  arg->type = pr_type_from_id (argtype);
2352  }
2353  arg->index = or_get_int (buf, &rc);
2354  arg->domain =
2356  }
2357  free_var_table (vars);
2358 
2359  return (arg);
2360 }
2361 
2362 /*
2363  * methsig_to_disk - Write the disk representation of a method signature.
2364  * return: void
2365  * buf(in/out): translation buffer
2366  * sig(in): signature
2367  * Note:
2368  * On overflow, or_overflow will call longjmp and jump to the outer caller
2369  *
2370  */
2371 static int
2373 {
2374  char *start;
2375  int offset;
2376 
2377  start = buf->ptr;
2378  /* VARIABLE OFFSET TABLE */
2380 
2381  or_put_offset (buf, offset);
2382  offset += string_disk_size (sig->function_name);
2383 
2384  or_put_offset (buf, offset);
2385  offset += string_disk_size (sig->sql_definition);
2386 
2387  or_put_offset (buf, offset);
2388  offset += substructure_set_size ((DB_LIST *) sig->value, (LSIZER) metharg_size);
2389 
2390  or_put_offset (buf, offset);
2391  offset += substructure_set_size ((DB_LIST *) sig->args, (LSIZER) metharg_size);
2392 
2393  or_put_offset (buf, offset);
2394  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2395 
2396 
2397  /* ATTRIBUTES */
2398  or_put_int (buf, sig->num_args);
2399  put_string (buf, sig->function_name);
2400  put_string (buf, sig->sql_definition);
2401 
2404 
2405  put_substructure_set (buf, (DB_LIST *) sig->args, (LWRITER) metharg_to_disk, &tf_Metaclass_metharg.mc_classoid,
2407 
2408  if (start + offset != buf->ptr)
2409  {
2411  }
2412 
2413  return NO_ERROR;
2414 }
2415 
2416 static inline void
2417 methsig_to_disk_lwriter (void *buf, void *sig)
2418 {
2420 }
2421 
2422 /*
2423  * methsig_size - Calculate the disk size of a method signature.
2424  * return: disk size of signature
2425  * sig(in): signature
2426  */
2427 static int
2429 {
2430  int size;
2431 
2433  size += string_disk_size (sig->function_name);
2434  size += string_disk_size (sig->sql_definition);
2435  size += substructure_set_size ((DB_LIST *) sig->value, (LSIZER) metharg_size);
2436  size += substructure_set_size ((DB_LIST *) sig->args, (LSIZER) metharg_size);
2437 
2438  return (size);
2439 }
2440 
2441 /*
2442  * disk_to_methsig - Read the disk represenation of a method signature and
2443  * create the memory represenatation.
2444  * return: new method signature
2445  * buf(in/out): translation buffer
2446  */
2447 static SM_METHOD_SIGNATURE *
2449 {
2450  OR_VARINFO *vars;
2451  SM_METHOD_SIGNATURE *sig;
2452  int nargs, rc = NO_ERROR;
2453  const char *fname, *fix;
2454 
2455  sig = NULL;
2457  if (vars == NULL)
2458  {
2459  or_abort (buf);
2460  }
2461  else
2462  {
2463  nargs = or_get_int (buf, &rc);
2465  if (sig == NULL)
2466  {
2467  or_abort (buf);
2468  }
2469  else
2470  {
2471  fname = get_string (buf, vars[ORC_METHSIG_FUNCTION_NAME_INDEX].length);
2472  sig->sql_definition = get_string (buf, vars[ORC_METHSIG_SQL_DEF_INDEX].length);
2473 
2474  /*
2475  * KLUDGE: older databases have the function name string stored with
2476  * a prepended '_' character for the sun. Now, since we don't do this
2477  * until we actually have to dynamic link the function, we have to
2478  * strip it off if it was stored in the old form
2479  */
2480  if (fname != NULL && fname[0] == '_')
2481  {
2482  fix = ws_copy_string (fname + 1);
2483  if (fix == NULL)
2484  {
2485  or_abort (buf);
2486  }
2487  else
2488  {
2489  ws_free_string (fname);
2490  fname = fix;
2491  }
2492  }
2493  sig->function_name = fname;
2494 
2495  sig->num_args = nargs;
2496  sig->value =
2499  sig->args =
2502  }
2503  free_var_table (vars);
2504  }
2505 
2506  return (sig);
2507 }
2508 
2509 /*
2510  * method_to_disk - Write the disk representation of a method.
2511  * return:
2512  * buf(in/out): translation buffer
2513  * method(in): method structure
2514  * Note:
2515  * On overflow, or_overflow will call longjmp and jump to the outer caller
2516  */
2517 static int
2519 {
2520  char *start;
2521  int offset;
2522 
2523  start = buf->ptr;
2524  /* VARIABLE OFFSET TABLE */
2525  /* name */
2527 
2528  or_put_offset (buf, offset);
2529  offset += string_disk_size (method->header.name);
2530 
2531  /* signature set */
2532  or_put_offset (buf, offset);
2533  offset += substructure_set_size ((DB_LIST *) method->signatures, (LSIZER) methsig_size);
2534 
2535  /* property list */
2536 
2537  or_put_offset (buf, offset);
2538  offset += property_list_size (method->properties);
2539 
2540  /* end of variables */
2541  or_put_offset (buf, offset);
2542  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2543 
2544  /* ATTRIBUTES */
2545  /* source class oid */
2546  or_pack_mop (buf, method->class_mop);
2547  or_put_int (buf, method->id);
2548 
2549  /* name */
2550  put_string (buf, method->header.name);
2551 
2552  /* signatures */
2555 
2556  put_property_list (buf, method->properties);
2557 
2558  if (start + offset != buf->ptr)
2559  {
2561  }
2562 
2563  return NO_ERROR;
2564 }
2565 
2566 static inline void
2567 method_to_disk_lwriter (void *buf, void *method)
2568 {
2569  (void) method_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_METHOD *, method));
2570 }
2571 
2572 /*
2573  * method_size - Calculates the disk size of a method.
2574  * return: disk size of method
2575  * method(in): method structure
2576  */
2577 static int
2579 {
2580  int size;
2581 
2583  size += string_disk_size (method->header.name);
2584  size += substructure_set_size ((DB_LIST *) method->signatures, (LSIZER) methsig_size);
2585  size += property_list_size (method->properties);
2586 
2587  return (size);
2588 }
2589 
2590 /*
2591  * disk_to_method - Reads the disk representation of a method and fills in
2592  * the supplied method structure.
2593  * return: void
2594  * buf(in/out): translation buffer
2595  * method(out): method structure
2596  * Note:
2597  * A jmp_buf has previously been established.
2598  */
2599 static void
2601 {
2602  OR_VARINFO *vars;
2603  DB_VALUE value;
2604  int rc = NO_ERROR;
2605 
2607  if (vars == NULL)
2608  {
2609  or_abort (buf);
2610  }
2611  else
2612  {
2613  /* this must be set later */
2614  method->header.name_space = ID_NULL;
2615 
2616  /* CLASS */
2617  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
2618  method->class_mop = db_get_object (&value);
2619  method->id = or_get_int (buf, &rc);
2620  method->function = NULL;
2621 
2622  /* variable attrubute 0 : name */
2623  method->header.name = get_string (buf, vars[ORC_METHOD_NAME_INDEX].length);
2624 
2625  /* variable attribute 1 : signatures */
2626  method->signatures =
2629 
2630  /* variable attribute 2 : property list */
2631  method->properties = get_property_list (buf, vars[ORC_METHOD_PROPERTIES_INDEX].length);
2632 
2633  free_var_table (vars);
2634  }
2635 }
2636 
2637 /*
2638  * methfile_to_disk - Write the disk representation of a method file.
2639  * return: NO_ERROR, or error code
2640  * buf(in/out): translation buffer
2641  * file(in): method file
2642  * Note:
2643  * on overflow, or_overflow will call longjmp and jump to the outer caller
2644  */
2645 static int
2647 {
2648  char *start;
2649  int offset;
2650 
2651  start = buf->ptr;
2652  /* VARIABLE OFFSET TABLE */
2654 
2655  /* name */
2656  or_put_offset (buf, offset);
2657  offset += string_disk_size (file->name);
2658 
2659  /* property list */
2660  or_put_offset (buf, offset);
2661  /* currently no properties */
2662  offset += property_list_size (NULL);
2663 
2664  /* end of object */
2665  or_put_offset (buf, offset);
2666  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2667 
2668  /* ATTRIBUTES */
2669 
2670  /* class */
2671  or_pack_mop (buf, file->class_mop);
2672 
2673  /* name */
2674  put_string (buf, file->name);
2675 
2676  /* property list */
2677  put_property_list (buf, NULL);
2678 
2679  if (start + offset != buf->ptr)
2680  {
2682  }
2683 
2684  return NO_ERROR;
2685 }
2686 
2687 static inline void
2688 methfile_to_disk_lwriter (void *buf, void *file)
2689 {
2690  (void) methfile_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_METHOD_FILE *, file));
2691 }
2692 
2693 /*
2694  * methfile_size - Calculate the disk size of a method file.
2695  * return: disk size of the method file
2696  * file(in): method file
2697  */
2698 static int
2700 {
2701  int size;
2702 
2704  size += string_disk_size (file->name);
2705  size += property_list_size (NULL);
2706 
2707  return (size);
2708 }
2709 
2710 /*
2711  * disk_to_methfile - Read the disk representation of a method file and
2712  * create a new method file structure.
2713  * return: new method file structure
2714  * buf(in/out): translation buffer
2715  * Note:
2716  * A jmp_buf has previously been established.
2717  */
2718 static SM_METHOD_FILE *
2720 {
2721  SM_METHOD_FILE *file;
2722  OR_VARINFO *vars;
2723  DB_SET *props;
2724  DB_VALUE value;
2725 
2726  file = NULL;
2728  if (vars == NULL)
2729  {
2730  or_abort (buf);
2731  }
2732  else
2733  {
2735  if (file == NULL)
2736  {
2737  or_abort (buf);
2738  }
2739  else
2740  {
2741  /* class */
2742  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
2743  file->class_mop = db_get_object (&value);
2744 
2745  /* name */
2746  file->name = get_string (buf, vars[ORC_METHFILE_NAME_INDEX].length);
2747 
2748  /* properties */
2749  props = get_property_list (buf, vars[ORC_METHFILE_PROPERTIES_INDEX].length);
2750  /* shouldn't have any of these yet */
2751  if (props != NULL)
2752  {
2753  set_free (props);
2754  }
2755  }
2756 
2757  free_var_table (vars);
2758  }
2759  return (file);
2760 }
2761 
2762 /*
2763  * query_spec_to_disk - Write the disk representation of a virtual class
2764  * query_spec statement.
2765  * return: NO_ERROR or error code
2766  * buf(in/out): translation buffer
2767  * statement(in): query_spec statement
2768  */
2769 static int
2771 {
2772  char *start;
2773  int offset;
2774 
2775  start = buf->ptr;
2776  /* VARIABLE OFFSET TABLE */
2778 
2779  or_put_offset (buf, offset);
2780  offset += string_disk_size (query_spec->specification);
2781 
2782  or_put_offset (buf, offset);
2783  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2784 
2785  /* ATTRIBUTES */
2786  put_string (buf, query_spec->specification);
2787 
2788  if (start + offset != buf->ptr)
2789  {
2791  }
2792 
2793  return NO_ERROR;
2794 }
2795 
2796 static inline void
2797 query_spec_to_disk_lwriter (void *buf, void *query_spec)
2798 {
2799  (void) query_spec_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_QUERY_SPEC *, query_spec));
2800 }
2801 
2802 /*
2803  * query_spec_size - Calculates the disk size of a query_spec statement.
2804  * return: disk size of query_spec statement
2805  * statement(in): query_spec statement
2806  */
2807 static int
2809 {
2810  int size;
2811 
2813  size += string_disk_size (statement->specification);
2814 
2815  return (size);
2816 }
2817 
2818 
2819 /*
2820  * disk_to_query_spec - Reads the disk representation of a query_spec
2821  * statement and creates the memory representation.
2822  * return: new query_spec structure
2823  * buf(in/out): translation buffer
2824  */
2825 static SM_QUERY_SPEC *
2827 {
2828  SM_QUERY_SPEC *statement;
2829  OR_VARINFO *vars;
2830 
2831  statement = NULL;
2833  if (vars == NULL)
2834  {
2835  or_abort (buf);
2836  }
2837  else
2838  {
2839  statement = classobj_make_query_spec (NULL);
2840  if (statement == NULL)
2841  {
2842  or_abort (buf);
2843  }
2844  else
2845  {
2846  statement->specification = get_string (buf, vars[ORC_QUERY_SPEC_SPEC_INDEX].length);
2847  }
2848 
2849  free_var_table (vars);
2850  }
2851  return (statement);
2852 }
2853 
2854 /*
2855  * attribute_to_disk - Write the disk representation of an attribute.
2856  * return: on overflow, or_overflow will call longjmp and jump to the outer caller
2857  * buf(in/out): translation buffer
2858  * att(in): attribute
2859  * Note:
2860  * On overflow, or_overflow will call longjmp and jump to the outer caller
2861  */
2862 static int
2864 {
2865  char *start;
2866  int offset;
2867  DB_OBJLIST *triggers;
2868 
2869  start = buf->ptr;
2870  /* VARIABLE OFFSET TABLE */
2871  /* name */
2873  or_put_offset (buf, offset);
2874 
2875  offset += string_disk_size (att->header.name);
2876 
2877  /* initial value variable */
2878  or_put_offset (buf, offset);
2879  /* could avoid domain tag here ? */
2880  offset += or_packed_value_size (&att->default_value.value, 1, 1, 0);
2881 
2882  /* original value */
2883  or_put_offset (buf, offset);
2884  /* could avoid domain tag here ? */
2885  offset += or_packed_value_size (&att->default_value.original_value, 1, 1, 0);
2886 
2887  /* domain list */
2888  or_put_offset (buf, offset);
2889  offset += substructure_set_size ((DB_LIST *) att->domain, (LSIZER) domain_size);
2890 
2891  /* trigger list */
2892  or_put_offset (buf, offset);
2893  (void) tr_get_cache_objects (att->triggers, &triggers);
2894  offset += object_set_size (triggers);
2895 
2896  /* property list */
2897  or_put_offset (buf, offset);
2898  offset += property_list_size (att->properties);
2899 
2900  /* comment */
2901  or_put_offset (buf, offset);
2902  offset += string_disk_size (att->comment);
2903 
2904  /* end of object */
2905  or_put_offset (buf, offset);
2906  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
2907 
2908  /* ATTRIBUTES */
2909  or_put_int (buf, att->id);
2910  or_put_int (buf, (int) att->type->id);
2911  or_put_int (buf, 0); /* memory offsets are now calculated after loading */
2912  or_put_int (buf, att->order);
2913  or_pack_mop (buf, att->class_mop);
2914  or_put_int (buf, att->flags);
2915 
2916  /* index BTID */
2917  /*
2918  * The index member of the attribute structure has been removed. Indexes
2919  * are now stored on the class property list. We still need to store
2920  * something out to disk since the disk representation has not changed.
2921  * For now, store a NULL BTID on disk. - JB
2922  */
2923  or_put_int (buf, NULL_FILEID);
2924  or_put_int (buf, NULL_PAGEID);
2925  or_put_int (buf, 0);
2926 
2927  /* name */
2928  put_string (buf, att->header.name);
2929 
2930  /* value/original value, make sure the flags match the calls to or_packed_value_size above ! */
2931  or_put_value (buf, &att->default_value.value, 1, 1, 0);
2932  or_put_value (buf, &att->default_value.original_value, 1, 1, 0);
2933 
2934  /* domain */
2937 
2938  /* triggers */
2939  put_object_set (buf, triggers);
2940 
2941  /* formerly att_extension_to_disk(buf, att) */
2942  put_property_list (buf, att->properties);
2943 
2944  /* comment */
2945  put_string (buf, att->comment);
2946 
2947  if (start + offset != buf->ptr)
2948  {
2950  }
2951 
2952  return NO_ERROR;
2953 }
2954 
2955 static inline void
2956 attribute_to_disk_lwriter (void *buf, void *att)
2957 {
2958  (void) attribute_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_ATTRIBUTE *, att));
2959 }
2960 
2961 /*
2962  * attribute_size - Calculates the disk size of an attribute.
2963  * return: disk size of attribute
2964  * att(in): attribute
2965  */
2966 static int
2968 {
2969  DB_OBJLIST *triggers;
2970  int size;
2971 
2973 
2974  size += string_disk_size (att->header.name);
2975  size += or_packed_value_size (&att->default_value.value, 1, 1, 0);
2976  size += or_packed_value_size (&att->default_value.original_value, 1, 1, 0);
2977  size += substructure_set_size ((DB_LIST *) att->domain, (LSIZER) domain_size);
2978 
2979  (void) tr_get_cache_objects (att->triggers, &triggers);
2980  size += object_set_size (triggers);
2981 
2982  /* size += att_extension_size(att); */
2983  size += property_list_size (att->properties);
2984 
2985  size += string_disk_size (att->comment);
2986 
2987  return (size);
2988 }
2989 
2990 
2991 /*
2992  * disk_to_attribute - Reads the disk representation of an attribute and
2993  * fills in the supplied attribute structure.
2994  * return: void
2995  * buf(in/out): translation buffer
2996  * att(out): attribute structure
2997  * Note:
2998  * A jmp_buf has previously been established.
2999  */
3000 static void
3002 {
3003  OR_VARINFO *vars;
3004  int fileid;
3005  DB_OBJLIST *triggers;
3006  DB_VALUE value;
3007  int rc = NO_ERROR;
3008  DB_TYPE dbval_type;
3009 
3011  if (vars == NULL)
3012  {
3013  or_abort (buf);
3014  }
3015  else
3016  {
3017  /*
3018  * must be sure to initialize these, the function classobj_make_attribute
3019  * should be split into creation & initialization functions so we can
3020  * have a single function that initializes the various fields. As it
3021  * stands now, any change made to the attribute structure has to be
3022  * initialized in classobj_make_attribute and here as well
3023  */
3024  att->header.name_space = ID_NULL; /* must set this later ! */
3025  att->header.name = NULL;
3026  att->domain = NULL;
3027  att->constraints = NULL;
3028  att->properties = NULL;
3029  att->order_link = NULL;
3030  att->triggers = NULL;
3031  att->auto_increment = NULL;
3032 
3033  att->id = or_get_int (buf, &rc);
3034  dbval_type = (DB_TYPE) or_get_int (buf, &rc);
3035  att->type = pr_type_from_id (dbval_type);
3036  att->offset = or_get_int (buf, &rc);
3037  att->offset = 0; /* calculated later */
3038  att->order = or_get_int (buf, &rc);
3039 
3040  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
3041  att->class_mop = db_get_object (&value);
3042  /* prevents clear on next readval call */
3043  db_value_put_null (&value);
3044 
3045  att->flags = or_get_int (buf, &rc);
3046 
3047  fileid = or_get_int (buf, &rc);
3048 
3049  /* index BTID */
3050  /*
3051  * Read the NULL BTID from disk. There is no place to put this so
3052  * ignore it. - JB
3053  */
3054  (void) or_get_int (buf, &rc);
3055  (void) or_get_int (buf, &rc);
3056 
3057  /* variable attribute 0 : name */
3058  att->header.name = get_string (buf, vars[ORC_ATT_NAME_INDEX].length);
3059 
3060  /* variable attribute 1 : value */
3062 
3063  /* variable attribute 2 : original value */
3065 
3066  /* variable attribute 3 : domain */
3067  att->domain =
3069 
3070  if (att->domain != NULL && att->domain->type->id == DB_TYPE_ENUMERATION)
3071  {
3072  /* Fill the default values with missing data */
3075  }
3076 
3077  /* variable attribute 4: trigger list */
3078  triggers = get_object_set (buf, vars[ORC_ATT_TRIGGER_INDEX].length);
3079  if (triggers != NULL)
3080  {
3082  }
3083  /* variable attribute 5: property list */
3084  /* formerly disk_to_att_extension(buf, att, vars[5].length); */
3085  att->properties = get_property_list (buf, vars[ORC_ATT_PROPERTIES_INDEX].length);
3086 
3089  if (att->properties)
3090  {
3091  if (classobj_get_prop (att->properties, "update_default", &value) > 0)
3092  {
3094  }
3095 
3096  if (classobj_get_prop (att->properties, "default_expr", &value) > 0)
3097  {
3098  /* We have two cases: simple and complex expressions. */
3099  if (DB_VALUE_TYPE (&value) == DB_TYPE_SEQUENCE)
3100  {
3101  DB_SEQ *def_expr_seq;
3102  DB_VALUE def_expr_op, def_expr_type, def_expr_format;
3103  const char *def_expr_format_str;
3104 
3105  assert (set_size (db_get_set (&value)) == 3);
3106 
3107  def_expr_seq = db_get_set (&value);
3108 
3109  /* get default expression operator (op of expr) */
3110  if (set_get_element_nocopy (def_expr_seq, 0, &def_expr_op) != NO_ERROR)
3111  {
3112  assert (false);
3113  }
3114  assert (DB_VALUE_TYPE (&def_expr_op) == DB_TYPE_INTEGER
3115  && db_get_int (&def_expr_op) == (int) T_TO_CHAR);
3116  att->default_value.default_expr.default_expr_op = db_get_int (&def_expr_op);
3117 
3118  /* get default expression type (arg1 of expr) */
3119  if (set_get_element_nocopy (def_expr_seq, 1, &def_expr_type) != NO_ERROR)
3120  {
3121  assert (false);
3122  }
3123  assert (DB_VALUE_TYPE (&def_expr_type) == DB_TYPE_INTEGER);
3125  (DB_DEFAULT_EXPR_TYPE) db_get_int (&def_expr_type);
3126 
3127  /* get default expression format (arg2 of expr) */
3128  if (set_get_element_nocopy (def_expr_seq, 2, &def_expr_format) != NO_ERROR)
3129  {
3130  assert (false);
3131  }
3132 
3133 #if !defined (NDEBUG)
3134  {
3135  DB_TYPE db_value_type_local = db_value_type (&def_expr_format);
3136  assert (db_value_type_local == DB_TYPE_NULL || TP_IS_CHAR_TYPE (db_value_type_local));
3137  }
3138 #endif
3139  if (!db_value_is_null (&def_expr_format))
3140  {
3141  def_expr_format_str = db_get_string (&def_expr_format);
3142  att->default_value.default_expr.default_expr_format = ws_copy_string (def_expr_format_str);
3144  {
3145  assert (er_errid () != NO_ERROR);
3146  }
3147  }
3148  }
3149  else
3150  {
3152  }
3153 
3154  pr_clear_value (&value);
3155  }
3156  }
3157 
3158  /* variable attribute 6: comment */
3159  att->comment = get_string (buf, vars[ORC_ATT_COMMENT_INDEX].length);
3160 
3161  /* THIS SHOULD BE INITIALIZING THE header.name_space field !! */
3162 
3163  free_var_table (vars);
3164  }
3165 }
3166 
3167 
3168 /*
3169  * resolution_to_disk - Writes the disk representation of a resolution.
3170  * return:
3171  * buf(in/out): translation buffer
3172  * res(in): resolution
3173  */
3174 static int
3176 {
3177  char *start;
3178  int offset, name_space;
3179 
3180  start = buf->ptr;
3181  /* VARIABLE OFFSET TABLE */
3182  /* name */
3184  or_put_offset (buf, offset);
3185  offset += string_disk_size (res->name);
3186 
3187  /* new name */
3188  or_put_offset (buf, offset);
3189  offset += string_disk_size (res->alias);
3190 
3191  /* end of object */
3192  or_put_offset (buf, offset);
3193  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
3194 
3195  /* ATTRIBUTES */
3196  or_pack_mop (buf, res->class_mop);
3197  name_space = (int) res->name_space; /* kludge for ansi */
3198  or_put_int (buf, name_space);
3199  put_string (buf, res->name);
3200  put_string (buf, res->alias);
3201 
3202  if (start + offset != buf->ptr)
3203  {
3205  }
3206 
3207  return NO_ERROR;
3208 }
3209 
3210 static inline void
3211 resolution_to_disk_lwriter (void *buf, void *res)
3212 {
3213  (void) resolution_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_RESOLUTION *, res));
3214 }
3215 
3216 /*
3217  * resolution_size - Calculates the disk size of a resolution.
3218  * return: disk size of resolution
3219  * res(in): resolution
3220  */
3221 static int
3223 {
3224  int size;
3225 
3227  size += string_disk_size (res->name);
3228  size += string_disk_size (res->alias);
3229 
3230  return (size);
3231 }
3232 
3233 
3234 /*
3235  * disk_to_resolution - Reads the disk representation of a resolution and
3236  * creates a new structure in memory.
3237  * return: new resolution structure
3238  * buf(in/out): translation buffer
3239  * Note:
3240  * Handle the case where the resolution for a deleted class was
3241  * accidentally saved. When this happens, the stored OID will be the NULL
3242  * oid and ws_mop will return NULL.
3243  * Shouldn't really happen but its easier to check for it here
3244  * than having the sizer and writer functions check. Seeing this
3245  * probably indicates a bug in the subclass cleanup code after
3246  * class deletion.
3247  * This paranoia may no longer be necessary but it was put here
3248  * for a reason and we should be careful about ripping it out until
3249  * all the tests run without it.
3250  *
3251  * A jmp_buf has previously been established.
3252  */
3253 static SM_RESOLUTION *
3255 {
3256  SM_RESOLUTION *res;
3257  SM_NAME_SPACE name_space;
3258  OR_VARINFO *vars;
3259  MOP class_;
3260  DB_VALUE value;
3261  int rc;
3262 
3263  res = NULL;
3265  if (vars == NULL)
3266  {
3267  or_abort (buf);
3268  }
3269  else
3270  {
3271  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
3272  class_ = db_get_object (&value);
3273  if (class_ == NULL)
3274  {
3275  (void) or_get_int (buf, &rc);
3276  tp_VarNChar.data_readval (buf, NULL, NULL, vars[ORC_RES_NAME_INDEX].length, true, NULL, 0);
3277  tp_VarNChar.data_readval (buf, NULL, NULL, vars[ORC_RES_ALIAS_INDEX].length, true, NULL, 0);
3278  }
3279  else
3280  {
3281  name_space = (SM_NAME_SPACE) or_get_int (buf, &rc);
3282  res = classobj_make_resolution (NULL, NULL, NULL, name_space);
3283  if (res == NULL)
3284  {
3285  or_abort (buf);
3286  }
3287  else
3288  {
3289  res->class_mop = class_;
3290  res->name = get_string (buf, vars[ORC_RES_NAME_INDEX].length);
3291  res->alias = get_string (buf, vars[ORC_RES_ALIAS_INDEX].length);
3292  }
3293  }
3294 
3295  free_var_table (vars);
3296  }
3297  return (res);
3298 }
3299 
3300 /*
3301  * repattribute_to_disk - Writes the disk representation of a representation
3302  * attribute.
3303  * return: NO_ERROR or error code
3304  * buf(in): translation buffer
3305  * rat(in): attribute
3306  * Note:
3307  * On overflow, or_overflow will call longjmp and jump to the outer caller
3308  */
3309 static int
3311 {
3312  char *start;
3313  int offset;
3314 
3315  start = buf->ptr;
3316  /* VARIABLE OFFSET TABLE */
3318 
3319  /* domain list */
3320  or_put_offset (buf, offset);
3321  offset += substructure_set_size ((DB_LIST *) rat->domain, (LSIZER) domain_size);
3322 
3323  /* end of object */
3324  or_put_offset (buf, offset);
3325  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
3326  /* fixed width attributes */
3327  or_put_int (buf, rat->attid);
3328  or_put_int (buf, (int) rat->typeid_);
3329 
3330  /* domain */
3333 
3334  if (start + offset != buf->ptr)
3335  {
3337  }
3338 
3339  return NO_ERROR;
3340 }
3341 
3342 static inline void
3343 repattribute_to_disk_lwriter (void *buf, void *rat)
3344 {
3346 }
3347 
3348 /*
3349  * repattribute_size - Calculates the disk size for the REPATTRIBUTE.
3350  * return: disk size of repattribute
3351  * rat(in): memory attribute
3352  */
3353 static int
3355 {
3356  int size;
3357 
3359 
3360  size += substructure_set_size ((DB_LIST *) rat->domain, (LSIZER) domain_size);
3361 
3362  return (size);
3363 }
3364 
3365 /*
3366  * disk_to_repattribute - Reads the disk representation of a representation
3367  * attribute.
3368  * return: new repattribute
3369  * buf(in/out): translation buffer
3370  */
3371 static SM_REPR_ATTRIBUTE *
3373 {
3374  SM_REPR_ATTRIBUTE *rat;
3375  OR_VARINFO *vars;
3376  int id, tid;
3377  int rc = NO_ERROR;
3378 
3380  if (vars == NULL)
3381  {
3382  or_abort (buf);
3383  return NULL;
3384  }
3385 
3386  id = or_get_int (buf, &rc);
3387  tid = or_get_int (buf, &rc);
3388  rat = classobj_make_repattribute (id, (DB_TYPE) tid, NULL);
3389  if (rat == NULL)
3390  {
3391  free_var_table (vars);
3392  or_abort (buf);
3393  return NULL;
3394  }
3395 
3396  rat->domain =
3398 
3399  free_var_table (vars);
3400 
3401  return rat;
3402 }
3403 
3404 
3405 /*
3406  * representation_size - Calculate the disk size for a representation.
3407  * return: byte size of the representation
3408  * rep(in): representation
3409  */
3410 static int
3412 {
3413  int size;
3414 
3416 
3418 
3419  size += property_list_size (NULL);
3420 
3421  return (size);
3422 }
3423 
3424 /*
3425  * representation_to_disk - Write the disk representation of an
3426  * SM_REPRESENTATION.
3427  * return: NO_ERROR
3428  * buf(in/out): translation buffer
3429  * rep(in): representation
3430  * Note:
3431  * On overflow, or_overflow will call longjmp and jump to the outer caller
3432  */
3433 static int
3435 {
3436  char *start;
3437  int offset;
3438 
3439  start = buf->ptr;
3441 
3442  or_put_offset (buf, offset);
3444 
3445  or_put_offset (buf, offset);
3446  offset += property_list_size (NULL);
3447  /* end of object */
3448  or_put_offset (buf, offset);
3449  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
3450 
3451  or_put_int (buf, rep->id);
3452  or_put_int (buf, rep->fixed_count);
3453  or_put_int (buf, rep->variable_count);
3454 
3455  /* no longer have the fixed_size field, leave it for future expansion */
3456  or_put_int (buf, 0);
3457 
3460 
3461  put_property_list (buf, NULL);
3462 
3463  if (start + offset != buf->ptr)
3464  {
3466  }
3467 
3468  return NO_ERROR;
3469 }
3470 
3471 static inline void
3472 representation_to_disk_lwriter (void *buf, void *rep)
3473 {
3475 }
3476 
3477 /*
3478  * disk_to_representation - Read the disk representation for an
3479  * SM_REPRESENTATION structure and build the memory structure.
3480  * return: new representation structure
3481  * buf(in/out): translation buffer
3482  */
3483 static SM_REPRESENTATION *
3485 {
3486  SM_REPRESENTATION *rep;
3487  OR_VARINFO *vars;
3488  DB_SEQ *props;
3489  int rc = NO_ERROR;
3490 
3492  if (vars == NULL)
3493  {
3494  or_abort (buf);
3495  return NULL;
3496  }
3497 
3499 
3500  if (rep == NULL)
3501  {
3502  free_var_table (vars);
3503  or_abort (buf);
3504  return NULL;
3505  }
3506  else
3507  {
3508  rep->id = or_get_int (buf, &rc);
3509  rep->fixed_count = or_get_int (buf, &rc);
3510  rep->variable_count = or_get_int (buf, &rc);
3511 
3512  /* we no longer use this field, formerly fixed_size */
3513  (void) or_get_int (buf, &rc);
3514 
3515  /* variable 0 : attributes */
3516  rep->attributes =
3519 
3520  /* variable 1 : properties */
3521  props = get_property_list (buf, vars[ORC_REP_PROPERTIES_INDEX].length);
3522  /* shouldn't be any, we have no place for them */
3523  if (props != NULL)
3524  {
3525  set_free (props);
3526  }
3527  }
3528 
3529  free_var_table (vars);
3530  return (rep);
3531 }
3532 
3533 /*
3534  * check_class_structure - maps over the class prior to storage to make sure
3535  * that everything looks ok.
3536  * return: error code
3537  * class(in): class strucutre
3538  * Note:
3539  * The point is to get errors detected early on so that the lower level
3540  * translation functions don't have to worry about them.
3541  * It is MANDATORY that this be called before any size or other walk of
3542  * the class
3543  */
3544 static int
3546 {
3547  int ok = 1;
3548 
3549  /* Currently, there is nothing to decache. I expect have to populate the class property list here someting in the
3550  * near future so I'll leave the function in place. - JB */
3551 
3552 /* decache_attribute_properties(class); */
3553  return (ok);
3554 }
3555 
3556 /*
3557  * put_class_varinfo - Writes the variable offset table for a class object.
3558  * return: ending offset
3559  * buf(in/out): translation buffer
3560  * class(in): class structure
3561  * Note:
3562  * This is the only meta object that includes OR_MVCC_HEADER_SIZE
3563  * as part of the offset calculations. This is because the other
3564  * substructures are all stored in sets inside the class object.
3565  * Returns the offset within the buffer after the offset table
3566  * (offset to first fixed attribute).
3567  */
3568 static int
3570 {
3571  DB_OBJLIST *triggers;
3572  int offset;
3573 
3574  /* compute the variable offsets relative to the end of the header (beginning of variable table) */
3576  /* name */
3577  or_put_offset (buf, offset);
3578 
3579  offset += string_disk_size (sm_ch_name ((MOBJ) class_));
3580  or_put_offset (buf, offset);
3581 
3582  offset += string_disk_size (class_->loader_commands);
3583 
3584  /* representation set */
3585  or_put_offset (buf, offset);
3586 
3587  offset += substructure_set_size ((DB_LIST *) class_->representations, (LSIZER) representation_size);
3588  or_put_offset (buf, offset);
3589 
3590  offset += object_set_size (class_->users);
3591  or_put_offset (buf, offset);
3592 
3593  offset += object_set_size (class_->inheritance);
3594  or_put_offset (buf, offset);
3595 
3596  offset += substructure_set_size ((DB_LIST *) class_->attributes, (LSIZER) attribute_size);
3597  or_put_offset (buf, offset);
3598 
3599  offset += substructure_set_size ((DB_LIST *) class_->shared, (LSIZER) attribute_size);
3600  or_put_offset (buf, offset);
3601 
3602  offset += substructure_set_size ((DB_LIST *) class_->class_attributes, (LSIZER) attribute_size);
3603 
3604  or_put_offset (buf, offset);
3605 
3606  offset += substructure_set_size ((DB_LIST *) class_->methods, (LSIZER) method_size);
3607 
3608  or_put_offset (buf, offset);
3609 
3610  offset += substructure_set_size ((DB_LIST *) class_->class_methods, (LSIZER) method_size);
3611 
3612  or_put_offset (buf, offset);
3613 
3614  offset += substructure_set_size ((DB_LIST *) class_->method_files, (LSIZER) methfile_size);
3615 
3616  or_put_offset (buf, offset);
3617 
3618  offset += substructure_set_size ((DB_LIST *) class_->resolutions, (LSIZER) resolution_size);
3619 
3620  or_put_offset (buf, offset);
3621 
3622  offset += substructure_set_size ((DB_LIST *) class_->query_spec, (LSIZER) query_spec_size);
3623 
3624  or_put_offset (buf, offset);
3625 
3626  (void) tr_get_cache_objects (class_->triggers, &triggers);
3627  offset += object_set_size (triggers);
3628 
3629  /* property list */
3630  or_put_offset (buf, offset);
3631 
3632  offset += property_list_size (class_->properties);
3633 
3634  or_put_offset (buf, offset);
3635 
3636  offset += string_disk_size (class_->comment);
3637 
3638  or_put_offset (buf, offset);
3639 
3640  offset += substructure_set_size ((DB_LIST *) class_->partition, (LSIZER) partition_info_size);
3641 
3642  /* end of object */
3643  or_put_offset (buf, offset);
3644  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
3645 
3646  return (offset);
3647 }
3648 
3649 /*
3650  * put_class_attributes - Writes the fixed and variable attributes of a class.
3651  * return: void
3652  * buf(in/out): translation buffer
3653  * class(in): class structure
3654  */
3655 static void
3657 {
3658  DB_OBJLIST *triggers;
3659 
3660 #if !defined(NDEBUG)
3661  if (!HFID_IS_NULL (sm_ch_heap ((MOBJ) class_)))
3662  {
3663  assert (!OID_ISNULL (sm_ch_rep_dir ((MOBJ) class_)));
3664  }
3665 #endif
3666 
3667  /* attribute id counters */
3668 
3669  /* doesn't exist yet */
3670  or_put_int (buf, class_->att_ids);
3671  or_put_int (buf, class_->method_ids);
3672 
3673  or_put_oid (buf, &(class_->header.ch_rep_dir));
3674 
3675  or_put_int (buf, class_->header.ch_heap.vfid.fileid);
3676  or_put_int (buf, class_->header.ch_heap.vfid.volid);
3677  or_put_int (buf, class_->header.ch_heap.hpgid);
3678 
3679  or_put_int (buf, class_->fixed_count);
3680  or_put_int (buf, class_->variable_count);
3681  or_put_int (buf, class_->fixed_size);
3682  or_put_int (buf, class_->att_count);
3683  /* object size is now calculated after loading */
3684  or_put_int (buf, 0);
3685  or_put_int (buf, class_->shared_count);
3686  or_put_int (buf, class_->method_count);
3687  or_put_int (buf, class_->class_method_count);
3688  or_put_int (buf, class_->class_attribute_count);
3689  or_put_int (buf, class_->flags);
3690  or_put_int (buf, (int) class_->class_type);
3691 
3692  /* owner object */
3693  or_pack_mop (buf, class_->owner);
3694  or_put_int (buf, (int) class_->collation_id);
3695 
3696  or_put_int (buf, class_->tde_algorithm);
3697 
3698 
3699  /* 0: NAME */
3700  put_string (buf, sm_ch_name ((MOBJ) class_));
3701  put_string (buf, class_->loader_commands);
3702 
3703  put_substructure_set (buf, (DB_LIST *) class_->representations, representation_to_disk_lwriter,
3705 
3706  put_object_set (buf, class_->users);
3707 
3708  put_object_set (buf, class_->inheritance);
3709 
3710  put_substructure_set (buf, (DB_LIST *) class_->attributes, attribute_to_disk_lwriter,
3712 
3713  put_substructure_set (buf, (DB_LIST *) class_->shared, attribute_to_disk_lwriter,
3715 
3716  put_substructure_set (buf, (DB_LIST *) class_->class_attributes, attribute_to_disk_lwriter,
3718 
3721 
3722  put_substructure_set (buf, (DB_LIST *) class_->class_methods, method_to_disk_lwriter,
3724 
3725  put_substructure_set (buf, (DB_LIST *) class_->method_files, methfile_to_disk_lwriter,
3727 
3728  put_substructure_set (buf, (DB_LIST *) class_->resolutions, resolution_to_disk_lwriter,
3730 
3731  put_substructure_set (buf, (DB_LIST *) class_->query_spec, query_spec_to_disk_lwriter,
3733 
3734  /*
3735  * triggers - for simplicity, convert the cache into a flattened
3736  * list of object id's
3737  */
3738  (void) tr_get_cache_objects (class_->triggers, &triggers);
3739  put_object_set (buf, triggers);
3740 
3741  put_property_list (buf, class_->properties);
3742 
3743  put_string (buf, class_->comment);
3744 
3745  put_substructure_set (buf, (DB_LIST *) class_->partition, partition_info_to_disk_lwriter,
3747 }
3748 
3749 /*
3750  * class_to_disk - Write the disk representation of a class.
3751  * return: void
3752  * buf(in/out): translation buffer
3753  * class(in): class structure
3754  * Note:
3755  * The writing of the offset table and the attributes was split into
3756  * two pieces because it was getting too long.
3757  * Caller must have a setup a jmpbuf (called setjmp) to handle any
3758  * errors
3759  */
3760 static void
3761 class_to_disk (OR_BUF * buf, SM_CLASS * class_)
3762 {
3763  char *start;
3764  int offset;
3765 
3766  /* kludge, we may have to do some last minute adj of the class structures before saving. In particular, some of the
3767  * attribute fields need to be placed in the attribute property list because there are no corresponding fields in the
3768  * disk representation. This may result in storage allocation which because we don't have modern computers may fail.
3769  * This function does all of the various checking up front so we don't have to detect it later in the substructure
3770  * conversion routines */
3771  if (!check_class_structure (class_))
3772  {
3773  or_abort (buf);
3774  }
3775  else
3776  {
3777  start = buf->ptr - OR_NON_MVCC_HEADER_SIZE;
3778  /* header already written */
3779  offset = put_class_varinfo (buf, class_);
3780  put_class_attributes (buf, class_);
3781 
3782  if (start + offset + OR_NON_MVCC_HEADER_SIZE != buf->ptr)
3783  {
3785  or_abort (buf);
3786  }
3787  }
3788 }
3789 
3790 
3791 /*
3792  * tf_class_size - Calculates the disk size of a class.
3793  * return: disk size of class
3794  * classobj(in): pointer to class structure
3795  */
3796 static int
3798 {
3799  SM_CLASS *class_;
3800  DB_OBJLIST *triggers;
3801  int size;
3802 
3803  class_ = (SM_CLASS *) classobj;
3804 
3805  /* make sure properties are decached */
3806  if (!check_class_structure (class_))
3807  {
3808  return (-1);
3809  }
3810 
3811  size = OR_NON_MVCC_HEADER_SIZE;
3812 
3814 
3815  size += string_disk_size (sm_ch_name ((MOBJ) class_));
3816  size += string_disk_size (class_->loader_commands);
3817 
3818  size += substructure_set_size ((DB_LIST *) class_->representations, (LSIZER) representation_size);
3819 
3820  size += object_set_size (class_->users);
3821  size += object_set_size (class_->inheritance);
3822 
3823  size += substructure_set_size ((DB_LIST *) class_->attributes, (LSIZER) attribute_size);
3824  size += substructure_set_size ((DB_LIST *) class_->shared, (LSIZER) attribute_size);
3825  size += substructure_set_size ((DB_LIST *) class_->class_attributes, (LSIZER) attribute_size);
3826 
3827  size += substructure_set_size ((DB_LIST *) class_->methods, (LSIZER) method_size);
3828  size += substructure_set_size ((DB_LIST *) class_->class_methods, (LSIZER) method_size);
3829 
3830  size += substructure_set_size ((DB_LIST *) class_->method_files, (LSIZER) methfile_size);
3831 
3832  size += substructure_set_size ((DB_LIST *) class_->resolutions, (LSIZER) resolution_size);
3833 
3834  size += substructure_set_size ((DB_LIST *) class_->query_spec, (LSIZER) query_spec_size);
3835 
3836  (void) tr_get_cache_objects (class_->triggers, &triggers);
3837  size += object_set_size (triggers);
3838 
3839  size += property_list_size (class_->properties);
3840 
3841  size += string_disk_size (class_->comment);
3842 
3843  size += substructure_set_size ((DB_LIST *) class_->partition, (LSIZER) partition_info_size);
3844 
3845  return (size);
3846 }
3847 
3848 #if defined(ENABLE_UNUSED_FUNCTION)
3849 /*
3850  * tf_dump_class_size - Debugging function to display disk size information
3851  * for a class.
3852  * return: void
3853  * classobj(in): pointer to class structure
3854  */
3855 void
3856 tf_dump_class_size (MOBJ classobj)
3857 {
3858  SM_CLASS *class_;
3859  DB_OBJLIST *triggers;
3860  int size, s;
3861 
3862  class_ = (SM_CLASS *) classobj;
3863 
3864  /* make sure properties are decached */
3865  if (!check_class_structure (class_))
3866  {
3867  return;
3868  }
3869 
3870  size = OR_NON_MVCC_HEADER_SIZE; /* ? */
3872  fprintf (stdout, "Fixed size %d\n", size);
3873 
3874  s = string_disk_size (sm_ch_name ((MOBJ) class_));
3875  fprintf (stdout, "Header name %d\n", s);
3876  size += s;
3877 
3878  s = string_disk_size (class_->loader_commands);
3879  fprintf (stdout, "Loader commands %d\n", s);
3880  size += s;
3881 
3882  s = substructure_set_size ((DB_LIST *) class_->representations, (LSIZER) representation_size);
3883  fprintf (stdout, "Representations %d\n", s);
3884  size += s;
3885 
3886  s = object_set_size (class_->users);
3887  fprintf (stdout, "Users %d\n", s);
3888  size += s;
3889 
3890  s = object_set_size (class_->inheritance);
3891  fprintf (stdout, "Inheritance %d\n", s);
3892  size += s;
3893 
3894  s = substructure_set_size ((DB_LIST *) class_->attributes, (LSIZER) attribute_size);
3895  fprintf (stdout, "Attributes %d\n", s);
3896  size += s;
3897 
3898  s = substructure_set_size ((DB_LIST *) class_->shared, (LSIZER) attribute_size);
3899  fprintf (stdout, "Shared attributes %d\n", s);
3900  size += s;
3901 
3902  s = substructure_set_size ((DB_LIST *) class_->class_attributes, (LSIZER) attribute_size);
3903  fprintf (stdout, "Class attributes %d\n", s);
3904  size += s;
3905 
3906  s = substructure_set_size ((DB_LIST *) class_->methods, (LSIZER) method_size);
3907  fprintf (stdout, "Methods %d\n", s);
3908  size += s;
3909 
3910  s = substructure_set_size ((DB_LIST *) class_->class_methods, (LSIZER) method_size);
3911  fprintf (stdout, "Class methods %d\n", s);
3912  size += s;
3913 
3914  s = substructure_set_size ((DB_LIST *) class_->method_files, (LSIZER) methfile_size);
3915  fprintf (stdout, "Method files %d\n", s);
3916  size += s;
3917 
3918  s = substructure_set_size ((DB_LIST *) class_->resolutions, (LSIZER) resolution_size);
3919  fprintf (stdout, "Resolutions %d\n", s);
3920  size += s;
3921 
3922  s = substructure_set_size ((DB_LIST *) class_->query_spec, (LSIZER) query_spec_size);
3923  fprintf (stdout, "Query_Spec statements %d\n", s);
3924  size += s;
3925 
3926  (void) tr_get_cache_objects (class_->triggers, &triggers);
3927  s = object_set_size (triggers);
3928  fprintf (stdout, "Triggers %d\n", s);
3929  size += s;
3930 
3931  s = property_list_size (class_->properties);
3932  fprintf (stdout, "Properties %d\n", s);
3933  size += s;
3934 
3935  s = string_disk_size (class_->comment);
3936  fprintf (stdout, "Comment %d\n", s);
3937  size += s;
3938 
3939  fprintf (stdout, "TOTAL: %d\n", size);
3940 }
3941 #endif /* ENABLE_UNUSED_FUNCTION */
3942 
3943 /*
3944  * tag_component_namespace - restore the appropriate name_space tags for
3945  * class components.
3946  * return: void
3947  * components(in/out): component list
3948  * namespace(in):
3949  * Note:
3950  * Since the component tag is not stored with the attributes & methods
3951  * it must be restored after they have been read. We know the name_space
3952  * because they have been separated into different lists in the
3953  * class structure.
3954  */
3955 static void
3957 {
3958  SM_COMPONENT *c;
3959 
3960  for (c = components; c != NULL; c = c->next)
3961  {
3962  c->name_space = name_space;
3963  }
3964 }
3965 
3966 /*
3967  * disk_to_class - Reads the disk representation of a class and creates the
3968  * memory structure.
3969  * return: class structure
3970  * buf(in/out): translation buffer
3971  * class_ptr(out): return pointer
3972  * Note:
3973  A jmp_buf has previously been established.
3974  */
3975 static SM_CLASS *
3976 disk_to_class (OR_BUF * buf, SM_CLASS ** class_ptr)
3977 {
3978  SM_CLASS *class_;
3979  SM_ATTRIBUTE *att;
3980  OR_VARINFO *vars;
3981  DB_OBJLIST *triggers;
3982  DB_VALUE value;
3983  int rc = NO_ERROR;
3984  char auto_increment_name[AUTO_INCREMENT_SERIAL_NAME_MAX_LENGTH];
3985  MOP serial_class_mop = NULL, serial_mop;
3986  DB_IDENTIFIER serial_obj_id;
3987 
3988  class_ = NULL;
3989  /* get the variable length and offsets. The offsets are relative to the end of the header (beginning of variable
3990  * table). */
3992  if (vars == NULL)
3993  {
3994  goto on_error;
3995  }
3996 
3997  class_ = *class_ptr = classobj_make_class (NULL);
3998  if (class_ == NULL)
3999  {
4000  goto on_error;
4001  }
4002 
4003  class_->att_ids = or_get_int (buf, &rc);
4004  class_->method_ids = or_get_int (buf, &rc);
4005 
4006  or_get_oid (buf, &(class_->header.ch_rep_dir));
4007 
4008  class_->header.ch_heap.vfid.fileid = or_get_int (buf, &rc);
4009  class_->header.ch_heap.vfid.volid = or_get_int (buf, &rc);
4010  class_->header.ch_heap.hpgid = or_get_int (buf, &rc);
4011 
4012 #if !defined(NDEBUG)
4013  if (!HFID_IS_NULL (sm_ch_heap ((MOBJ) class_)))
4014  {
4015  assert (!OID_ISNULL (sm_ch_rep_dir ((MOBJ) class_)));
4016  }
4017 #endif
4018 
4019  class_->fixed_count = or_get_int (buf, &rc);
4020  class_->variable_count = or_get_int (buf, &rc);
4021  class_->fixed_size = or_get_int (buf, &rc);
4022  class_->att_count = or_get_int (buf, &rc);
4023  class_->object_size = or_get_int (buf, &rc);
4024  class_->object_size = 0; /* calculated later */
4025  class_->shared_count = or_get_int (buf, &rc);
4026  class_->method_count = or_get_int (buf, &rc);
4027  class_->class_method_count = or_get_int (buf, &rc);
4028  class_->class_attribute_count = or_get_int (buf, &rc);
4029  class_->flags = or_get_int (buf, &rc);
4030  class_->class_type = (SM_CLASS_TYPE) or_get_int (buf, &rc);
4031 
4032  /* owner object */
4033  tp_Object.data_readval (buf, &value, NULL, -1, true, NULL, 0);
4034  class_->owner = db_get_object (&value);
4035  class_->collation_id = or_get_int (buf, &rc);
4036 
4037  class_->tde_algorithm = or_get_int (buf, &rc);
4038 
4039  /* variable 0 */
4040  class_->header.ch_name = get_string (buf, vars[ORC_NAME_INDEX].length);
4041 
4042  /* variable 1 */
4043  class_->loader_commands = get_string (buf, vars[ORC_LOADER_COMMANDS_INDEX].length);
4044 
4045  /* REPRESENTATIONS */
4046  /* variable 2 */
4047  class_->representations =
4050 
4051  /* variable 3 */
4052  class_->users = get_object_set (buf, vars[ORC_SUBCLASSES_INDEX].length);
4053  /* variable 4 */
4054  class_->inheritance = get_object_set (buf, vars[ORC_SUPERCLASSES_INDEX].length);
4055 
4056  class_->attributes = (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), class_->att_count);
4057  if (class_->att_count && class_->attributes == NULL)
4058  {
4059  goto on_error;
4060  }
4061  classobj_initialize_attributes (class_->attributes);
4062 
4063  class_->shared = (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), class_->shared_count);
4064  if (class_->shared_count && class_->shared == NULL)
4065  {
4066  goto on_error;
4067  }
4068  classobj_initialize_attributes (class_->shared);
4069 
4070  class_->class_attributes =
4071  (SM_ATTRIBUTE *) classobj_alloc_threaded_array (sizeof (SM_ATTRIBUTE), class_->class_attribute_count);
4072  if (class_->class_attribute_count && class_->class_attributes == NULL)
4073  {
4074  goto on_error;
4075  }
4076  classobj_initialize_attributes (class_->class_attributes);
4077 
4078  class_->methods = (SM_METHOD *) classobj_alloc_threaded_array (sizeof (SM_METHOD), class_->method_count);
4079  if (class_->method_count && class_->methods == NULL)
4080  {
4081  goto on_error;
4082  }
4083  classobj_initialize_methods (class_->methods);
4084 
4085  class_->class_methods = (SM_METHOD *) classobj_alloc_threaded_array (sizeof (SM_METHOD), class_->class_method_count);
4086  if (class_->class_method_count && class_->class_methods == NULL)
4087  {
4088  goto on_error;
4089  }
4090  classobj_initialize_methods (class_->class_methods);
4091 
4092  /* variable 5 */
4093  install_substructure_set (buf, (DB_LIST *) class_->attributes, (VREADER) disk_to_attribute,
4095  /* variable 6 */
4096  install_substructure_set (buf, (DB_LIST *) class_->shared, (VREADER) disk_to_attribute,
4098  /* variable 7 */
4099  install_substructure_set (buf, (DB_LIST *) class_->class_attributes, (VREADER) disk_to_attribute,
4101 
4102  /* variable 8 */
4103  install_substructure_set (buf, (DB_LIST *) class_->methods, (VREADER) disk_to_method, vars[ORC_METHODS_INDEX].length);
4104  /* variable 9 */
4105  install_substructure_set (buf, (DB_LIST *) class_->class_methods, (VREADER) disk_to_method,
4107 
4108  /*
4109  * fix up the name_space tags, could do this later but easier just
4110  * to assume that they're set up correctly
4111  */
4112  tag_component_namespace ((SM_COMPONENT *) class_->attributes, ID_ATTRIBUTE);
4114  tag_component_namespace ((SM_COMPONENT *) class_->class_attributes, ID_CLASS_ATTRIBUTE);
4115  tag_component_namespace ((SM_COMPONENT *) class_->methods, ID_METHOD);
4116  tag_component_namespace ((SM_COMPONENT *) class_->class_methods, ID_CLASS_METHOD);
4117 
4118  /* variable 10 */
4119  class_->method_files =
4121 
4122  /* variable 11 */
4123  class_->resolutions =
4125 
4126  /* variable 12 */
4127  class_->query_spec =
4129 
4130  /* variable 13 */
4131  triggers = get_object_set (buf, vars[ORC_TRIGGERS_INDEX].length);
4132  if (triggers != NULL)
4133  {
4134  class_->triggers = tr_make_schema_cache (TR_CACHE_CLASS, triggers);
4135  }
4136 
4137  /* variable 14 */
4138  class_->properties = get_property_list (buf, vars[ORC_PROPERTIES_INDEX].length);
4139 
4140  /* variable 15 */
4141  class_->comment = get_string (buf, vars[ORC_COMMENT_INDEX].length);
4142 
4143  /* variable 16 */
4144  class_->partition =
4146 
4147  /* build the ordered instance/shared instance list */
4148  classobj_fixup_loaded_class (class_);
4149 
4150  /* set attribute's auto_increment object if any */
4151  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
4152  {
4153  att->auto_increment = NULL;
4154  if (att->flags & SM_ATTFLAG_AUTO_INCREMENT)
4155  {
4156  if (serial_class_mop == NULL)
4157  {
4158  serial_class_mop = sm_find_class (CT_SERIAL_NAME);
4159  if (serial_class_mop == NULL)
4160  {
4161  ASSERT_ERROR ();
4162  goto on_error;
4163  }
4164  }
4165 
4166  SET_AUTO_INCREMENT_SERIAL_NAME (auto_increment_name, sm_ch_name ((MOBJ) class_), att->header.name);
4167  serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, auto_increment_name);
4168 
4169  /* If this att is inherited from a super class, serial_mop can be NULL. In this case, att->auto_increment
4170  * will be set later. */
4171 #if 0
4172  if (serial_mop == NULL)
4173  {
4174  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ATTRIBUTE, 1, auto_increment_name);
4175  db_ws_free (class_);
4176  free_var_table (vars);
4177  or_abort (buf);
4178  return NULL;
4179  }
4180 #endif
4181  att->auto_increment = serial_mop;
4182  }
4183  }
4184 
4185  free_var_table (vars);
4186 
4187  return (class_);
4188 
4189 on_error:
4190 
4191  if (vars != NULL)
4192  {
4193  free_var_table (vars);
4194  }
4195 
4196  if (class_ != NULL)
4197  {
4198  classobj_free_class (class_);
4199  }
4200 
4201  *class_ptr = NULL;
4202 
4203  return NULL;
4204 }
4205 
4206 
4207 /*
4208  * root_to_disk - Write the disk representation of the root class.
4209  * return: void
4210  * buf(in/out): translation buffer
4211  * root(in): root class object
4212  * header_size(in): the size of header - variable in MVCC
4213  * Note:
4214  * Caller must have a setup a jmpbuf (called setjmp) to handle any errors.
4215  * Only the header part of the 'root' object is serialized. Please see comment on ROOT_CLASS definition.
4216  */
4217 static void
4219 {
4220  char *start;
4221  int offset;
4222 
4223  start = buf->ptr - OR_NON_MVCC_HEADER_SIZE; /* header already written */
4224 
4225  /* compute the variable offsets relative to the end of the header (beginning of variable table) */
4227 
4228  /* name */
4229  or_put_offset (buf, offset);
4230  offset += string_disk_size (sm_ch_name ((MOBJ) root));
4231 
4232  /* end of object */
4233  or_put_offset (buf, offset);
4234  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
4235 
4236  assert (OID_ISNULL (sm_ch_rep_dir ((MOBJ) root))); /* is dummy */
4237 
4238  /* heap file id - see assumptions in comment above */
4239  or_put_int (buf, (int) root->header.ch_heap.vfid.fileid);
4240  or_put_int (buf, (int) root->header.ch_heap.vfid.volid);
4241  or_put_int (buf, (int) root->header.ch_heap.hpgid);
4242 
4243  put_string (buf, sm_ch_name ((MOBJ) root));
4244 
4245  if (start + OR_NON_MVCC_HEADER_SIZE + offset != buf->ptr)
4246  {
4248  }
4249 }
4250 
4251 
4252 /*
4253  * root_size - Calculates the disk size of the root class.
4254  * return: disk size of root class
4255  * rootobj(in): root class object
4256  *
4257  * Note:
4258  * Only the header part of the 'root' object is serialized. Please see comment on ROOT_CLASS definition.
4259  */
4260 static int
4261 root_size (MOBJ rootobj)
4262 {
4263  ROOT_CLASS *root;
4264  int size;
4265 
4266  root = (ROOT_CLASS *) rootobj;
4267 
4268  size = OR_NON_MVCC_HEADER_SIZE;
4270 
4271  /* name */
4272  size += string_disk_size (sm_ch_name ((MOBJ) root));
4273 
4274  return (size);
4275 }
4276 
4277 
4278 /*
4279  * disk_to_root - Reads the disk representation of the root class and builds
4280  * the memory rootclass.
4281  * return: root class object
4282  * buf(in/out): translation buffer
4283  * Note:
4284  * We know there is only one static structure for the root class so we use it rather than allocating a structure.
4285  * Only the header part of the 'root' object is serialized. Please see comment on ROOT_CLASS definition.
4286  */
4287 static ROOT_CLASS *
4289 {
4290  char *start;
4291  OR_VARINFO *vars;
4292  int rc = NO_ERROR;
4293 
4294  start = buf->ptr - OR_NON_MVCC_HEADER_SIZE; /* header already read */
4295 
4296  /* get the variable length and offsets. The offsets are relative to the end of the header (beginning of variable
4297  * table). */
4299  if (vars == NULL)
4300  {
4301  or_abort (buf);
4302  }
4303  else
4304  {
4305  assert (OID_ISNULL (sm_ch_rep_dir ((MOBJ) & sm_Root_class))); /* is dummy */
4306 
4307  sm_Root_class.header.ch_heap.vfid.fileid = (FILEID) or_get_int (buf, &rc);
4308  sm_Root_class.header.ch_heap.vfid.volid = (VOLID) or_get_int (buf, &rc);
4309  sm_Root_class.header.ch_heap.hpgid = (PAGEID) or_get_int (buf, &rc);
4310 
4311  /* name - could make sure its the same as sm_Root_class_name */
4312  or_advance (buf, vars[0].length);
4313 
4314  if (start + OR_NON_MVCC_HEADER_SIZE + vars[0].offset + vars[0].length != buf->ptr)
4315  {
4317  }
4318 
4319  free_var_table (vars);
4320  }
4321  return (&sm_Root_class);
4322 }
4323 
4324 
4325 /*
4326  * tf_disk_to_class - transforming the disk representation of a class.
4327  * return: class structure
4328  * oid(in):
4329  * record(in): disk record
4330  * Note:
4331  * It is imperitive that garbage collection be disabled during this
4332  * operation.
4333  * This is because the structure being built may contain pointers
4334  * to MOPs but it has not itself been attached to its own MOP yet so it
4335  * doesn't serve as a gc root. Make sure the caller
4336  * calls ws_cache() immediately after we return so the new object
4337  * gets attached as soon as possible. We must also have already
4338  * allocated the MOP in the caller so that we don't get one of the
4339  * periodic gc's when we attempt to allocate a new MOP.
4340  * This dependency should be isolated in a ws_ function called by
4341  * the locator.
4342  */
4343 MOBJ
4344 tf_disk_to_class (OID * oid, RECDES * record)
4345 {
4346  OR_BUF orep, *buf;
4347  unsigned int repid, chn;
4348  /* declare volatile to prevent reg optimization */
4349  MOBJ volatile class_;
4350  int rc = NO_ERROR;
4351 
4352  assert (oid != NULL && !OID_ISNULL (oid));
4353 
4354  /* should we assume this ? */
4356  {
4358  }
4359 
4360  class_ = NULL;
4361 
4362  buf = &orep;
4363  or_init (buf, record->data, record->length);
4364  buf->error_abort = 1;
4365 
4366  switch (_setjmp (buf->env))
4367  {
4368  case 0:
4369  /* offset size */
4371 
4372  repid = or_get_int (buf, &rc);
4373  repid = repid & ~OR_OFFSET_SIZE_FLAG;
4374  assert (((char) (repid >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK) == 0);
4375  chn = or_get_int (buf, &rc);
4376 
4377  if (oid_is_root (oid))
4378  {
4379  class_ = (MOBJ) disk_to_root (buf);
4380  }
4381  else
4382  {
4383  class_ = (MOBJ) disk_to_class (buf, (SM_CLASS **) (&class_));
4384  if (class_ != NULL)
4385  {
4386  ((SM_CLASS *) class_)->repid = repid;
4387  }
4388  }
4389 
4390  if (class_ != NULL)
4391  {
4392  ((SM_CLASS *) class_)->header.ch_obj_header.chn = chn;
4393  }
4394  break;
4395 
4396  default:
4397  /*
4398  * make sure to clear the class that was being created,
4399  * an appropriate error will have been set
4400  */
4401  if (class_ != NULL)
4402  {
4403  classobj_free_class ((SM_CLASS *) class_);
4404  class_ = NULL;
4405  }
4406  break;
4407  }
4408 
4410 
4411  buf->error_abort = 0;
4412  return (class_);
4413 }
4414 
4415 
4416 /*
4417  * tf_class_to_disk - creates the disk representation of a class.
4418  * return: zero for success, non-zero if errors
4419  * classobj(in): pointer to class structure
4420  * record(out): disk record
4421  * Note:
4422  * If the record was not large enough for the class, resulting in
4423  * the or_overflow error, this function returns the required size of the
4424  * record as a negative number.
4425  */
4426 TF_STATUS
4427 tf_class_to_disk (MOBJ classobj, RECDES * record)
4428 {
4429  OR_BUF orep, *buf;
4430  /* prevent reg optimization which hoses longmp */
4431  SM_CLASS *volatile class_;
4432  volatile int expected_size;
4433  SM_CLASS_HEADER *header;
4434  int chn;
4435  TF_STATUS status;
4436  int rc = 0;
4437  volatile int prop_free = 0;
4438  int repid;
4439 
4440  /* should we assume this ? */
4442  {
4444  }
4445 
4446  /*
4447  * don't worry about deferred fixup for classes, we don't usually have
4448  * many temporary OIDs in classes.
4449  */
4450  buf = &orep;
4451  or_init (buf, record->data, record->area_size);
4452  buf->error_abort = 1;
4453 
4454  class_ = (SM_CLASS *) classobj;
4455 
4456  header = (SM_CLASS_HEADER *) classobj;
4457  if (header->ch_type != SM_META_ROOT)
4458  {
4459  /* put all default_expr values in attribute properties */
4461  }
4462 
4463  /*
4464  * test - this isn't necessary but we've been having a class size related
4465  * bug that I want to try to catch - take this out when we're sure
4466  */
4467  if (class_ == (SM_CLASS *) (&sm_Root_class))
4468  {
4469  expected_size = root_size (classobj);
4470  }
4471  else
4472  {
4473  expected_size = tf_class_size (classobj);
4474  }
4475 
4476  /* if anything failed this far, no need to save stack context, return code will be handled in the switch below */
4477  if (rc == NO_ERROR)
4478  {
4479  rc = _setjmp (buf->env);
4480  }
4481 
4482  switch (rc)
4483  {
4484  case 0:
4485  status = TF_SUCCESS;
4486 
4487  /* representation id, offset size */
4488  repid = class_->repid;
4489  assert (((char) (repid >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK) == 0);
4490  OR_SET_VAR_OFFSET_SIZE (repid, BIG_VAR_OFFSET_SIZE); /* 4byte */
4491 
4492  chn = class_->header.ch_obj_header.chn + 1;
4493  class_->header.ch_obj_header.chn = chn;
4494 
4495  /* The header size of a class record in the same like non-MVCC case. */
4496  or_put_int (buf, repid);
4497  or_put_int (buf, chn);
4498 
4499  if (header->ch_type == SM_META_ROOT)
4500  {
4501  root_to_disk (buf, (ROOT_CLASS *) class_);
4502  }
4503  else
4504  {
4505  assert (class_->repid == (repid & ~OR_OFFSET_SIZE_FLAG));
4506  class_to_disk (buf, (SM_CLASS *) class_);
4507  }
4508 
4509  record->length = CAST_BUFLEN (buf->ptr - buf->buffer);
4510 
4511  /* sanity test, this sets an error only so we can see it if it happens */
4512  if (record->length != expected_size)
4513  {
4514  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_TF_SIZE_MISMATCH, 2, expected_size, record->length);
4515  or_abort (buf);
4516  }
4517 
4518  /* fprintf(stdout, "Saved class in %d bytes\n", record->length); */
4519  break;
4520 
4521  /*
4522  * if the longjmp status was anything other than ER_TF_BUFFER_OVERFLOW,
4523  * it represents an error condition and er_set will have been called
4524  */
4525 
4526  case ER_TF_BUFFER_OVERFLOW:
4527  status = TF_OUT_OF_SPACE;
4528  record->length = -expected_size;
4529  break;
4530 
4531  default:
4532  status = TF_ERROR;
4533  break;
4534 
4535  }
4536 
4537  /* restore properties */
4538  if (((SM_CLASS_HEADER *) classobj)->ch_type != SM_META_ROOT && class_->partition)
4539  {
4540  if (prop_free)
4541  {
4542  classobj_free_prop (class_->properties);
4543  class_->properties = NULL;
4544  }
4545  }
4546 
4547  buf->error_abort = 0;
4548  return (status);
4549 }
4550 
4551 
4552 /*
4553  * tf_object_size - Determines the number of byte required to store an object
4554  * on disk.
4555  * return: byte size of object on disk
4556  * classobj(in): class of instance
4557  * obj(in): instance to examine
4558  * Note:
4559  * This will work for any object; classes, instances, or the rootclass.
4560  */
4561 int
4562 tf_object_size (MOBJ classobj, MOBJ obj)
4563 {
4564  int size = 0;
4565 
4566  if (classobj != (MOBJ) (&sm_Root_class))
4567  {
4568  int dummy;
4569  size = object_size ((SM_CLASS *) classobj, obj, &dummy);
4570  }
4571  else if (obj == (MOBJ) (&sm_Root_class))
4572  {
4573  size = root_size (obj);
4574  }
4575  else
4576  {
4577  size = tf_class_size (obj);
4578  }
4579 
4580  return size;
4581 }
4582 
4583 /*
4584  * enumeration_size () - calculates size of enumeration
4585  * return : size of enumeration
4586  * enumeration (in) : enumeration
4587  */
4588 static int
4589 enumeration_size (const DB_ENUMERATION * enumeration)
4590 {
4591  return or_packed_enumeration_size (enumeration);
4592 }
4593 
4594 /*
4595  * put_enumeration () - pack an enumeration
4596  * return: error code or NO_ERROR
4597  * enumeration (in): enumeration
4598  */
4599 static void
4600 put_enumeration (OR_BUF * buf, const DB_ENUMERATION * enumeration)
4601 {
4602  (void) or_put_enumeration (buf, enumeration);
4603 }
4604 
4605 /*
4606  * get_enumeration - read enumeration from input buffer
4607  * return: NO_ERROR or error code
4608  * buf(in): input buffer
4609  * enumeration(in/out): pointer to enumeration holder
4610  * expected(in): expected length
4611  */
4612 static int
4613 get_enumeration (OR_BUF * buf, DB_ENUMERATION * enumeration, int expected)
4614 {
4615  if (expected == 0)
4616  {
4617  enumeration->count = 0;
4618  enumeration->elements = NULL;
4619  return NO_ERROR;
4620  }
4621  return or_get_enumeration (buf, enumeration);
4622 }
4623 
4624 
4625 /*
4626  * tf_attribute_default_expr_to_property - transfer default_expr flag to a
4627  * disk stored property
4628  * returns: error code or NO_ERROR
4629  * attr_list(in): attribute list to process
4630  */
4631 static int
4633 {
4634  SM_ATTRIBUTE *attr = NULL;
4635  DB_DEFAULT_EXPR *default_expr;
4636  DB_VALUE default_expr_value;
4637 
4638  if (attr_list == NULL)
4639  {
4640  /* nothing to do */
4641  return NO_ERROR;
4642  }
4643 
4644  for (attr = attr_list; attr; attr = (SM_ATTRIBUTE *) attr->header.next)
4645  {
4646  default_expr = &attr->default_value.default_expr;
4647  if (default_expr->default_expr_type != DB_DEFAULT_NONE)
4648  {
4649  /* attr has default expression as default value */
4650  if (attr->properties == NULL)
4651  {
4652  /* allocate new property sequence */
4653  attr->properties = classobj_make_prop ();
4654 
4655  if (attr->properties == NULL)
4656  {
4658  return er_errid ();
4659  }
4660  }
4661 
4663  {
4664  DB_SEQ *default_expr_sequence = NULL;
4665  DB_VALUE value;
4666 
4667  default_expr_sequence = set_create_sequence (3);
4668  if (default_expr_sequence == NULL)
4669  {
4670  if (attr->properties)
4671  {
4673  attr->properties = NULL;
4674  }
4676  return er_errid ();
4677  }
4678 
4679  /* currently, only T_TO_CHAR operator is allowed */
4680  assert (default_expr->default_expr_op == T_TO_CHAR);
4681  db_make_int (&value, (int) T_TO_CHAR);
4682  set_put_element (default_expr_sequence, 0, &value);
4683 
4684  /* default expression type */
4685  db_make_int (&value, default_expr->default_expr_type);
4686  set_put_element (default_expr_sequence, 1, &value);
4687 
4688  /* default expression format */
4689  if (default_expr->default_expr_format)
4690  {
4691  db_make_string (&value, default_expr->default_expr_format);
4692  }
4693  else
4694  {
4695  db_make_null (&value);
4696  }
4697 
4698  set_put_element (default_expr_sequence, 2, &value);
4699 
4700  /* create and put sequence */
4701  db_make_sequence (&default_expr_value, default_expr_sequence);
4702  default_expr_sequence = NULL;
4703  classobj_put_prop (attr->properties, "default_expr", &default_expr_value);
4704  pr_clear_value (&default_expr_value);
4705 
4706  }
4707  else
4708  {
4709  /* add default_expr property to sequence */
4710  db_make_int (&default_expr_value, default_expr->default_expr_type);
4711  classobj_put_prop (attr->properties, "default_expr", &default_expr_value);
4712  }
4713  }
4714  else if (attr->properties != NULL)
4715  {
4716  /* make sure property is unset for existing attributes */
4717  classobj_drop_prop (attr->properties, "default_expr");
4718  }
4719 
4720  DB_DEFAULT_EXPR_TYPE update_default = attr->on_update_default_expr;
4721  if (update_default != DB_DEFAULT_NONE)
4722  {
4723  if (attr->properties == NULL)
4724  {
4725  attr->properties = classobj_make_prop ();
4726 
4727  if (attr->properties == NULL)
4728  {
4730  return er_errid ();
4731  }
4732  }
4733 
4734  db_make_int (&default_expr_value, update_default);
4735  classobj_put_prop (attr->properties, "update_default", &default_expr_value);
4736  }
4737  else if (attr->properties != NULL)
4738  {
4739  /* make sure property is unset for existing attributes */
4740  classobj_drop_prop (attr->properties, "update_default");
4741  }
4742  }
4743 
4744  /* all ok */
4745  return NO_ERROR;
4746 }
4747 
4748 
4749 #if defined(ENABLE_UNUSED_FUNCTION)
4750 /*
4751  * tf_set_size - calculates the number of bytes that are required to store
4752  * the disk representation of a set.
4753  * return: size in bytes (-1 if error)
4754  * set(in): set to examine
4755  * Note:
4756  * If -1 is returned, an error was detected while calculating the
4757  * size and er_errid() must be consulted to determine the cause.
4758  * In practice, errors should not happen since we're simply
4759  * mapping over the elements without fetching any objects.
4760  */
4761 int
4762 tf_set_size (DB_SET * set)
4763 {
4764  DB_VALUE value;
4765  int size;
4766 
4767  /* won't handle references to "attached" sets that have been swapped out */
4768  if (set == NULL || set->set == NULL)
4769  {
4770  return 0;
4771  }
4772 
4773  /*
4774  * Doesn't matter which set function we call, they all use the
4775  * Don't have to synthesize a domain, we can get the one out
4776  * of the set itself.
4777  */
4778  db_make_set (&value, set);
4779  size = (*(tp_Set.lengthval)) (&value, 1);
4780 
4781  return size;
4782 }
4783 
4784 
4785 /*
4786  * tf_pack_set - transforms a DB_SET into its disk representation.
4787  * return: error code
4788  * set(in): set to pack
4789  * buffer(out): destination buffer
4790  * buffer_size(in): maximum length of buffer
4791  * actual_bytes(out): number of bytes used or required
4792  * Note:
4793  * If the set will fit within the buffer_size, no error is returned and
4794  * actual_bytes is set to the number of bytes used.
4795  * If the set will not fit in the buffer, ER_TF_BUFFER_OVERFLOW is returned
4796  * and actual_bytes is set to the number of bytes that are required
4797  * to pack this set.
4798  * Other errors may occur as the set is examined.
4799  */
4800 int
4801 tf_pack_set (DB_SET * set, char *buffer, int buffer_size, int *actual_bytes)
4802 {
4803  OR_BUF orep, *buf;
4804  int error;
4805  DB_VALUE value;
4806 
4807  if (set == NULL || set->set == NULL)
4808  {
4809  if (actual_bytes != NULL)
4810  {
4811  *actual_bytes = 0;
4812  }
4813  return NO_ERROR;
4814  }
4815 
4816  /* set up a transformation buffer, may want to do deferred fixup here ? */
4817  buf = &orep;
4818  or_init (buf, buffer, buffer_size);
4819  buf->error_abort = 1;
4820 
4821  switch (_setjmp (buf->env))
4822  {
4823  case 0:
4824  error = NO_ERROR;
4825 
4826  /*
4827  * Doesn't matter which set function we pick, all the types are the same.
4828  * Don't have to pass in domain either since the type will be
4829  * self-describing.
4830  */
4831  db_make_set (&value, set);
4832  (*(tp_Set.writeval)) (buf, &value);
4833 
4834  if (actual_bytes != NULL)
4835  {
4836  *actual_bytes = (int) (buf->ptr - buf->buffer);
4837  }
4838  break;
4839 
4840  /*
4841  * something happened, if it was ER_TF_BUFFER_OVERFLOW, return
4842  * the desired size as a negative number
4843  */
4844 
4845  case ER_TF_BUFFER_OVERFLOW:
4846  error = ER_TF_BUFFER_OVERFLOW;
4847  if (actual_bytes != NULL)
4848  {
4849  DB_VALUE value;
4850  db_make_set (&value, set);
4851  *actual_bytes = (*(tp_Set.lengthval)) (&value, 1);
4852  }
4853  break;
4854 
4855  default:
4856  assert (er_errid () != NO_ERROR);
4857  error = er_errid ();
4858  break;
4859  }
4860  buf->error_abort = 0;
4861 
4862  return (error);
4863 }
4864 #endif /* ENABLE_UNUSED_FUNCTION */
4865 
4866 /*
4867  * partition_to_disk - Write the disk representation of partition information
4868  * return: NO_ERROR or error code
4869  * buf(in/out): translation buffer
4870  * partition_info(in):
4871  */
4872 static int
4873 partition_info_to_disk (OR_BUF * buf, SM_PARTITION * partition_info)
4874 {
4875  char *start;
4876  int offset;
4877  DB_VALUE val;
4878 
4879  start = buf->ptr;
4880  /* VARIABLE OFFSET TABLE */
4882 
4883  db_make_sequence (&val, partition_info->values);
4884 
4885  or_put_offset (buf, offset);
4886  offset += string_disk_size (partition_info->pname);
4887 
4888  or_put_offset (buf, offset);
4889  offset += string_disk_size (partition_info->expr);
4890 
4891  or_put_offset (buf, offset);
4892  offset += or_packed_value_size (&val, 1, 1, 0);
4893 
4894  or_put_offset (buf, offset);
4895  offset += string_disk_size (partition_info->comment);
4896 
4897  or_put_offset (buf, offset);
4898  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
4899 
4900  /* ATTRIBUTES */
4901  or_put_int (buf, partition_info->partition_type);
4902 
4903  put_string (buf, partition_info->pname);
4904  put_string (buf, partition_info->expr);
4905 
4906  or_put_value (buf, &val, 1, 1, 0);
4907 
4908  put_string (buf, partition_info->comment);
4909 
4910  if (start + offset != buf->ptr)
4911  {
4913  }
4914 
4915  return NO_ERROR;
4916 }
4917 
4918 static inline void
4919 partition_info_to_disk_lwriter (void *buf, void *partition_info)
4920 {
4921  (void) partition_info_to_disk (STATIC_CAST (OR_BUF *, buf), STATIC_CAST (SM_PARTITION *, partition_info));
4922 }
4923 
4924 /*
4925  * partition_info_size - Calculates the disk size of a sm_partition structure.
4926  * return: disk size
4927  * partition_info(in):
4928  */
4929 static int
4931 {
4932  int size;
4933  DB_VALUE val;
4934 
4936  size += string_disk_size (partition_info->pname);
4937  size += string_disk_size (partition_info->expr);
4938  size += string_disk_size (partition_info->comment);
4939 
4940  db_make_sequence (&val, partition_info->values);
4941  size += or_packed_value_size (&val, 1, 1, 0);
4942 
4943  return (size);
4944 }
4945 
4946 
4947 /*
4948  * disk_to_partition_info - Reads the disk representation of partition
4949  * information and creates the memory representation.
4950  * return: new sm_partition structure
4951  * buf(in/out): translation buffer
4952  */
4953 static SM_PARTITION *
4955 {
4956  SM_PARTITION *partition_info = NULL;
4957  OR_VARINFO *vars;
4958  DB_VALUE val;
4959  int error = NO_ERROR;
4960 
4962  if (vars == NULL)
4963  {
4964  or_abort (buf);
4965  return NULL;
4966  }
4967 
4968  assert (vars != NULL);
4969 
4970  partition_info = classobj_make_partition_info ();
4971  if (partition_info == NULL)
4972  {
4973  or_abort (buf);
4974  }
4975  else
4976  {
4977  partition_info->partition_type = or_get_int (buf, &error);
4978  if (error != NO_ERROR)
4979  {
4980  free_var_table (vars);
4981  classobj_free_partition_info (partition_info);
4982  return NULL;
4983  }
4984 
4985  partition_info->pname = get_string (buf, vars[ORC_PARTITION_NAME_INDEX].length);
4986  partition_info->expr = get_string (buf, vars[ORC_PARTITION_EXPR_INDEX].length);
4987 
4988  error = or_get_value (buf, &val, NULL, vars[ORC_PARTITION_VALUES_INDEX].length, true);
4989  if (error != NO_ERROR)
4990  {
4991  free_var_table (vars);
4992  classobj_free_partition_info (partition_info);
4993  return NULL;
4994  }
4995  partition_info->values = db_seq_copy (db_get_set (&val));
4996  if (partition_info->values == NULL)
4997  {
4998  free_var_table (vars);
4999  pr_clear_value (&val);
5000  classobj_free_partition_info (partition_info);
5001  return NULL;
5002  }
5003 
5004  partition_info->comment = get_string (buf, vars[ORC_PARTITION_COMMENT_INDEX].length);
5005  }
5006 
5007  pr_clear_value (&val);
5008  free_var_table (vars);
5009  return (partition_info);
5010 }
static int substructure_set_size(DB_LIST *list, LSIZER function)
struct tr_schema_cache * triggers
Definition: class_object.h:463
static int query_spec_size(SM_QUERY_SPEC *statement)
SM_REPRESENTATION * classobj_find_representation(SM_CLASS *class_, int id)
#define OR_SET_VAR_OFFSET_SIZE(val, offset_size)
const char * name
Definition: class_object.h:631
META_CLASS tf_Metaclass_methsig
Definition: transform.c:115
int data_readval(struct or_buf *buf, DB_VALUE *value, const tp_domain *domain, int size, bool copy, char *copy_buf, int copy_buf_len) const
static void attribute_to_disk_lwriter(void *buf, void *att)
#define OR_PUT_OFFSET(ptr, val)
WS_OBJECT_HEADER ch_obj_header
Definition: class_object.h:347
int ml_append(DB_OBJLIST **list, MOP mop, int *added_ptr)
Definition: work_space.c:4548
struct or_fixup * fixups
const char * expr
Definition: class_object.h:697
static int enumeration_size(const DB_ENUMERATION *enumeration)
#define OR_PUT_OID(ptr, oid)
#define WS_IS_DELETED(mop)
Definition: work_space.h:284
#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 db_value_put_null(DB_VALUE *value)
Definition: db_macro.c:122
static SM_METHOD_ARGUMENT * disk_to_metharg(OR_BUF *buf)
DB_COLLECTION * db_get_set(const DB_VALUE *value)
META_CLASS tf_Metaclass_method
Definition: transform.c:128
static void query_spec_to_disk_lwriter(void *buf, void *query_spec)
#define LANG_SYS_COLLATION
char * obj_alloc(SM_CLASS *class_, int bound_bit_status)
static int object_set_size(DB_OBJLIST *list)
int fixed_count
Definition: class_object.h:737
SM_CLASS * classobj_make_class(const char *name)
void classobj_initialize_attributes(SM_ATTRIBUTE *attributes)
static SM_ATTRIBUTE * find_current_attribute(SM_CLASS *class_, int id)
static int query_spec_to_disk(OR_BUF *buf, SM_QUERY_SPEC *query_spec)
#define ASSERT_ERROR()
META_CLASS tf_Metaclass_repattribute
Definition: transform.c:162
META_CLASS tf_Metaclass_domain
Definition: transform.c:67
static void put_substructure_set(OR_BUF *buf, DB_LIST *list, LWRITER writer, OID *class_, int repid)
int or_packed_value_size(const DB_VALUE *value, int collapse_null, int include_domain, int include_domain_classoids)
static int representation_to_disk(OR_BUF *buf, SM_REPRESENTATION *rep)
OID * tf_need_permanent_oid(or_buf *buf, DB_OBJECT *obj)
Definition: transform_cl.c:513
void sm_bump_global_schema_version(void)
int or_put_oid(OR_BUF *buf, const OID *oid)
void or_abort(OR_BUF *buf)
MOP ws_mop(const OID *oid, MOP class_mop)
Definition: work_space.c:614
int data_writeval(struct or_buf *buf, const DB_VALUE *value) const
SM_COMPONENT header
Definition: class_object.h:591
unsigned char codeset
Definition: object_domain.h:91
static void representation_to_disk_lwriter(void *buf, void *rep)
char * MOBJ
Definition: work_space.h:174
META_CLASS tf_Metaclass_class
Definition: transform.c:221
PAGEID FILEID
int or_get_json_schema(OR_BUF *buf, REFPTR(char, schema))
static DB_OBJLIST * get_object_set(OR_BUF *buf, int expected)
static void class_to_disk(OR_BUF *buf, SM_CLASS *class_)
#define TP_IS_SET_TYPE(typenum)
#define ER_TF_BUFFER_OVERFLOW
Definition: error_code.h:388
int or_put_domain(OR_BUF *buf, struct tp_domain *domain, int include_classoids, int is_null)
void set_free(DB_COLLECTION *set)
Definition: set_object.c:2560
int db_get_int(const DB_VALUE *value)
const char * name
Definition: class_object.h:616
SM_METATYPE ch_type
Definition: class_object.h:349
DB_TYPE
Definition: dbtype_def.h:670
unsigned short count
Definition: dbtype_def.h:1033
static void tf_free_fixup(OR_FIXUP *fix)
Definition: transform_cl.c:370
#define ER_FAILED
Definition: error_code.h:47
#define OR_MVCC_REPID_MASK
static int object_size(SM_CLASS *class_, MOBJ obj, int *offset_size_ptr)
Definition: transform_cl.c:655
void initval(DB_VALUE *value, int precision, int scale) const
struct tp_domain * setdomain
Definition: object_domain.h:82
static SM_QUERY_SPEC * disk_to_query_spec(OR_BUF *buf)
TP_DOMAIN * domain
Definition: class_object.h:444
static void metharg_to_disk(OR_BUF *buf, SM_METHOD_ARGUMENT *arg)
int tf_Allow_fixups
Definition: transform_cl.c:70
MOBJ tf_disk_to_mem(MOBJ classobj, RECDES *record, int *convertp)
void classobj_initialize_methods(SM_METHOD *methods)
#define ER_SM_CORRUPTED
Definition: error_code.h:335
int classobj_get_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
static void repattribute_to_disk_lwriter(void *buf, void *rat)
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
SM_PARTITION * partition
Definition: class_object.h:760
int or_get_oid(OR_BUF *buf, OID *oid)
MOP pointer
Definition: work_space.h:162
DB_SEQ * properties
Definition: class_object.h:754
#define OR_MVCC_FLAG_VALID_INSID
META_CLASS tf_Metaclass_representation
Definition: transform.c:176
#define assert_release(e)
Definition: error_manager.h:96
int db_make_object(DB_VALUE *value, DB_C_OBJECT *obj)
static SM_METHOD_SIGNATURE * disk_to_methsig(OR_BUF *buf)
DB_COLLECTION * set_create_sequence(int size)
Definition: set_object.c:2432
SM_CLASS_TYPE
Definition: class_object.h:289
META_CLASS tf_Metaclass_root
Definition: transform.c:256
static DB_SEQ * get_property_list(OR_BUF *buf, int expected_size)
INT16 VOLID
#define MVCCID_NULL
static int attribute_size(SM_ATTRIBUTE *att)
SM_NAME_SPACE
#define OBJ_HEADER_BOUND_BITS_OFFSET
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define OR_MVCC_FLAG_VALID_DELID
#define OR_MVCCID_SIZE
static int representation_size(SM_REPRESENTATION *rep)
int fixed_size
Definition: class_object.h:739
static int methfile_to_disk(OR_BUF *buf, SM_METHOD_FILE *file)
struct sm_component * next
Definition: class_object.h:384
int or_packed_enumeration_size(const DB_ENUMERATION *e)
static int partition_info_to_disk(OR_BUF *buf, SM_PARTITION *partition_info)
TP_DOMAIN * domain
Definition: class_object.h:559
#define OR_MVCC_FLAG_SHIFT_BITS
TP_DOMAIN tp_Object_domain
TF_STATUS tf_class_to_disk(MOBJ classobj, RECDES *record)
char * data
void data_readmem(struct or_buf *buf, void *memptr, const tp_domain *domain, int size) const
int db_make_sequence(DB_VALUE *value, DB_C_SET *set)
static int repattribute_size(SM_REPR_ATTRIBUTE *rat)
const char * pname
Definition: class_object.h:694
bool classobj_class_has_indexes(SM_CLASS *class_)
static void disk_to_method(OR_BUF *buf, SM_METHOD *method)
SM_METHOD_ARGUMENT * value
Definition: class_object.h:575
INT32 hpgid
int or_put_value(OR_BUF *buf, DB_VALUE *value, int collapse_null, int include_domain, int include_domain_classoids)
SM_NAME_SPACE name_space
Definition: class_object.h:386
int er_errid(void)
const char * comment
Definition: class_object.h:698
#define OR_BOUND_BIT_BYTES(count)
#define OR_SHORT_SIZE
#define PTR_ALIGN(addr, boundary)
Definition: memory_alloc.h:77
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
struct or_tempoid OR_TEMPOID
PR_TYPE tp_Oid
SM_METHOD_ARGUMENT * classobj_make_method_arg(int index)
void db_ws_free(void *ptr)
Definition: quick_fit.c:194
static void put_string(OR_BUF *buf, const char *string)
void ws_free_string(const char *str)
Definition: work_space.c:3480
#define OR_MVCC_MAX_HEADER_SIZE
LC_OIDSET * oidset
Definition: transform_cl.c:111
LC_OIDMAP * locator_add_oidset_object(LC_OIDSET *oidset, MOP obj_mop)
Definition: locator_cl.c:6629
LC_CLASS_OIDSET * classes
Definition: locator.h:386
int or_skip_set_header(OR_BUF *buf)
#define NULL_PAGEID
ROOT_CLASS sm_Root_class
#define CT_SERIAL_NAME
Definition: transform.h:135
DB_DEFAULT_EXPR_TYPE default_expr_type
Definition: dbtype_def.h:1204
static int repattribute_to_disk(OR_BUF *buf, SM_REPR_ATTRIBUTE *rat)
static void root_to_disk(OR_BUF *buf, ROOT_CLASS *root)
#define OR_VAR_TABLE_SIZE(vars)
int db_make_string(DB_VALUE *value, DB_CONST_C_CHAR str)
INTL_CODESET lang_charset(void)
DB_DEFAULT_EXPR default_expr
Definition: class_object.h:395
void data_writemem(struct or_buf *buf, const void *memptr, const tp_domain *domain) const
int or_put_set_header(OR_BUF *buf, DB_TYPE set_type, int size, int domain, int bound_bits, int offset_table, int element_tags, int common_sub_header)
int setmem(void *memptr, const tp_domain *domain, const DB_VALUE *value) const
PR_TYPE * pr_type_from_id(DB_TYPE id)
PR_TYPE tp_Sequence
void classobj_initialize_default_expr(DB_DEFAULT_EXPR *default_expr)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
Definition: db_set.h:35
static SM_REPR_ATTRIBUTE * disk_to_repattribute(OR_BUF *buf)
const char * sm_ch_name(const MOBJ clobj)
static int string_disk_size(const char *string)
#define OR_MVCC_FLAG_VALID_PREV_VERSION
#define NULL_DEFAULT_EXPRESSION_OPERATOR
Definition: dbtype_def.h:659
#define ER_TF_SIZE_MISMATCH
Definition: error_code.h:390
SM_METHOD_SIGNATURE * classobj_make_method_signature(const char *name)
#define assert(x)
static void put_class_attributes(OR_BUF *buf, SM_CLASS *class_)
#define OR_MVCC_FLAG_MASK
int32_t fileid
Definition: dbtype_def.h:886
#define AUTO_INCREMENT_SERIAL_NAME_MAX_LENGTH
Definition: transform.h:180
META_CLASS tf_Metaclass_resolution
Definition: transform.c:151
int db_make_set(DB_VALUE *value, DB_C_SET *set)
SM_PARTITION * classobj_make_partition_info(void)
void ** references
Definition: transform_cl.c:97
#define TF_OUT_OF_SPACE
Definition: transform_cl.h:46
int setobj_sort(COL *col)
Definition: set_object.c:4437
int or_mvcc_get_repid_and_flags(OR_BUF *buf, int *error)
META_CLASS tf_Metaclass_attribute
Definition: transform.c:91
struct db_object * class_mop
Definition: work_space.h:121
#define OR_SET_HEADER_SIZE
void obj_free_memory(SM_CLASS *class_, MOBJ obj)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
#define TF_ERROR
Definition: transform_cl.h:47
DB_TYPE db_value_type(const DB_VALUE *value)
const char * db_json_get_schema_raw_from_validator(JSON_VALIDATOR *val)
Definition: db_json.cpp:2310
MOBJ tf_disk_to_class(OID *oid, RECDES *record)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
void classobj_free_class(SM_CLASS *class_)
#define DOM_GET_ENUMERATION(dom)
Definition: object_domain.h:38
SM_QUERY_SPEC * classobj_make_query_spec(const char *specification)
DB_VALUE original_value
Definition: class_object.h:393
static int metharg_size(SM_METHOD_ARGUMENT *arg)
HFID * sm_ch_heap(MOBJ clobj)
DB_SEQ * db_seq_copy(DB_SEQ *source)
Definition: db_set.c:428
static int methfile_size(SM_METHOD_FILE *file)
int or_put_int(OR_BUF *buf, int num)
int tf_object_size(MOBJ classobj, MOBJ obj)
bool oid_is_root(const OID *oid)
Definition: oid.c:135
META_CLASS tf_Metaclass_query_spec
Definition: transform.c:230
static SM_RESOLUTION * disk_to_resolution(OR_BUF *buf)
int method_ids
Definition: class_object.h:742
int or_put_bigint(OR_BUF *buf, DB_BIGINT num)
static int tf_do_fixup(OR_FIXUP *fix)
Definition: transform_cl.c:595
SM_NAME_SPACE name_space
Definition: class_object.h:633
int or_overflow(OR_BUF *buf)
DB_SEQ * values
Definition: class_object.h:696
static void clear_new_unbound(char *obj, SM_CLASS *class_, SM_REPRESENTATION *oldrep)
METHOD_FUNCTION function
Definition: class_object.h:594
int or_put_offset(OR_BUF *buf, int num)
static TP_DOMAIN * disk_to_domain2(OR_BUF *buf)
DB_OBJECT * db_get_object(const DB_VALUE *value)
#define OR_MVCC_PREV_VERSION_LSA_SIZE
const char * function_name
Definition: class_object.h:570
VFID vfid
#define TP_DOMAIN_TYPE(dom)
#define OR_MVCC_INSERT_HEADER_SIZE
SM_REPR_ATTRIBUTE * classobj_make_repattribute(int attid, DB_TYPE type_id, TP_DOMAIN *domain)
static int resolution_size(SM_RESOLUTION *res)
int locator_assign_oidset(LC_OIDSET *oidset, LC_OIDMAP_CALLBACK callback)
Definition: locator_cl.c:6687
#define OR_SUB_HEADER_SIZE
static OR_FIXUP * tf_make_fixup(void)
Definition: transform_cl.c:345
int or_put_offset_internal(OR_BUF *buf, int num, int offset_size)
#define NULL
Definition: freelistheap.h:34
struct lc_oidmap * next
Definition: locator.h:346
PR_TYPE tp_Set
struct pr_type * type
Definition: object_domain.h:76
void(* VREADER)(void *, void *)
Definition: transform_cl.c:123
const char * alias
Definition: class_object.h:632
SM_METHOD_SIGNATURE * signatures
Definition: class_object.h:593
void initmem(void *memptr, const tp_domain *domain) const
DB_SEQ * properties
Definition: class_object.h:598
void * client_data
Definition: locator.h:350
struct sm_repr_attribute * next
Definition: class_object.h:648
if(extra_options)
Definition: dynamic_load.c:958
#define DB_ATT_ALIGN(offset)
Definition: memory_alloc.h:93
static OR_VARINFO * read_var_table(OR_BUF *buf, int nvars)
#define OBJ_SET_BOUND_BIT(obj, element)
struct pr_type * type
Definition: class_object.h:443
#define ER_OBJ_CANT_ASSIGN_OID
Definition: error_code.h:945
static char * get_current(OR_BUF *buf, SM_CLASS *class_, MOBJ *obj_ptr, int bound_bit_flag, int offset_size)
Definition: transform_cl.c:925
OID * sm_ch_rep_dir(MOBJ clobj)
TP_DOMAIN * tp_domain_cache(TP_DOMAIN *transient)
int TF_STATUS
Definition: transform_cl.h:37
struct lc_class_oidset * next
Definition: locator.h:365
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define ER_TF_OUT_OF_SYNC
Definition: error_code.h:392
static int get_enumeration(OR_BUF *buf, DB_ENUMERATION *enumeration, int expected)
#define ER_OBJ_INVALID_ATTRIBUTE
Definition: error_code.h:273
LC_OIDSET * locator_make_oid_set(void)
Definition: locator.c:2116
struct pr_type * type
Definition: class_object.h:558
void or_init(OR_BUF *buf, char *data, int length)
#define WS_CHN(obj)
Definition: work_space.h:309
#define NULL_FILEID
const OID oid_Null_oid
Definition: oid.c:68
#define BIG_VAR_OFFSET_SIZE
static void methsig_to_disk_lwriter(void *buf, void *sig)
static void tag_component_namespace(SM_COMPONENT *components, SM_NAME_SPACE name_space)
static OR_VARINFO * read_var_table_internal(OR_BUF *buf, int nvars, int offset_size)
struct db_objlist * next
Definition: dbtype_def.h:442
static char * unpack_allocator(int size)
static char * get_old(OR_BUF *buf, SM_CLASS *class_, MOBJ *obj_ptr, int repid, int bound_bit_flag, int offset_size)
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)
static int method_to_disk(OR_BUF *buf, SM_METHOD *method)
DB_SEQ * properties
Definition: class_object.h:457
void locator_free_oid_set(THREAD_ENTRY *thread_p, LC_OIDSET *oidset)
Definition: locator.c:2227
LC_OIDMAP * oids
Definition: locator.h:366
SM_CONSTRAINT * constraints
Definition: class_object.h:454
#define max(a, b)
#define WS_LIST_APPEND(lst, element)
Definition: work_space.h:577
static int attribute_to_disk(OR_BUF *buf, SM_ATTRIBUTE *att)
int or_put_enumeration(OR_BUF *buf, const DB_ENUMERATION *e)
int or_get_offset_internal(OR_BUF *buf, int *error, int offset_size)
void tf_compile_meta_classes()
Definition: transform.c:550
struct db_object * op
Definition: dbtype_def.h:443
#define CAST_BUFLEN
Definition: porting.h:471
static SM_PARTITION * disk_to_partition_info(OR_BUF *buf)
DB_ENUMERATION enumeration
Definition: object_domain.h:84
#define TP_IS_CHAR_TYPE(typeid)
TP_DOMAIN_COLL_ACTION collation_flag
Definition: object_domain.h:94
int set_put_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2719
static int put_varinfo(OR_BUF *buf, char *obj, SM_CLASS *class_, int offset_size)
Definition: transform_cl.c:616
static void error(const char *msg)
Definition: gencat.c:331
DB_DEFAULT_EXPR_TYPE on_update_default_expr
Definition: class_object.h:452
unsigned int flags
Definition: class_object.h:459
static int rc
Definition: serial.c:50
SM_REPR_ATTRIBUTE * attributes
Definition: class_object.h:669
SM_CLASS_HEADER header
Definition: class_object.h:710
static SM_CLASS * disk_to_class(OR_BUF *buf, SM_CLASS **class_ptr)
#define HFID_IS_NULL(hfid)
int(* LSIZER)(void *)
Definition: transform_cl.c:120
bool db_value_is_null(const DB_VALUE *value)
OID * locator_assign_permanent_oid(MOP mop)
Definition: locator_cl.c:6084
static int check_class_structure(SM_CLASS *class_)
const char * sql_definition
Definition: class_object.h:573
#define ARG_FILE_LINE
Definition: error_manager.h:44
PR_TYPE tp_String
#define OR_BYTE_SIZE
static void domain_to_disk(OR_BUF *buf, TP_DOMAIN *domain)
const char * default_expr_format
Definition: dbtype_def.h:1206
int tr_get_cache_objects(TR_SCHEMA_CACHE *cache, DB_OBJLIST **list)
static void put_property_list(OR_BUF *buf, DB_SEQ *properties)
#define WS_OID(mop)
Definition: work_space.h:293
static char * get_string(OR_BUF *buf, int length)
static TP_DOMAIN * disk_to_domain(OR_BUF *buf)
void(* LWRITER)(void *, void *)
Definition: transform_cl.c:121
SM_METHOD_FILE * classobj_make_method_file(const char *name)
static int put_class_varinfo(OR_BUF *buf, SM_CLASS *class_)
void classobj_free_partition_info(SM_PARTITION *partition_info)
static int put_object_set(OR_BUF *buf, DB_OBJLIST *list)
static int root_size(MOBJ rootobj)
static int property_list_size(DB_SEQ *properties)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static void put_enumeration(OR_BUF *buf, const DB_ENUMERATION *e)
#define strlen(s1)
Definition: intl_support.c:43
#define TF_FIXUP_REFERENCE_QUANT
Definition: transform_cl.c:408
DB_ENUM_ELEMENT * elements
Definition: dbtype_def.h:1031
#define OR_VAR_TABLE_SIZE_INTERNAL(vars, offset_size)
SM_COMPONENT header
Definition: class_object.h:441
static void free_var_table(OR_VARINFO *vars)
static int partition_info_size(SM_PARTITION *partition_info)
SM_RESOLUTION * classobj_make_resolution(MOP class_mop, const char *name, const char *alias, SM_NAME_SPACE name_space)
void classobj_free_prop(DB_SEQ *properties)
Definition: class_object.c:292
#define OR_SUB_DOMAIN_SIZE
PR_TYPE tp_Object
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
static void disk_to_attribute(OR_BUF *buf, SM_ATTRIBUTE *att)
JSON_VALIDATOR * json_validator
int db_json_load_validator(const char *json_schema_raw, JSON_VALIDATOR *&validator)
Definition: db_json.cpp:2362
#define OR_NON_MVCC_HEADER_SIZE
int pr_clear_compressed_string(DB_VALUE *value)
OR_VARINFO * or_get_var_table_internal(OR_BUF *buf, int nvars, char *(*allocator)(int), int offset_size)
void * db_ws_alloc(size_t size)
Definition: quick_fit.c:73
SM_METHOD_ARGUMENT * args
Definition: class_object.h:577
static int tf_class_size(MOBJ classobj)
PR_TYPE tp_VarNChar
OID oid
Definition: locator.h:352
int db_make_varnchar(DB_VALUE *value, const int max_nchar_length, DB_CONST_C_NCHAR str, const int nchar_str_byte_size, const int codeset, const int collation_id)
TR_SCHEMA_CACHE * tr_make_schema_cache(TR_CACHE_TYPE type, DB_OBJLIST *objects)
int or_put_data(OR_BUF *buf, const char *data, int length)
META_CLASS tf_Metaclass_metharg
Definition: transform.c:102
META_CLASS tf_Metaclass_partition
Definition: transform.c:244
#define TP_FLOATING_PRECISION_VALUE
const char * specification
Definition: class_object.h:685
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
static void partition_info_to_disk_lwriter(void *buf, void *partition_info)
static void resolution_to_disk_lwriter(void *buf, void *res)
static int tf_add_fixup(OR_FIXUP *fix, DB_OBJECT *obj, void *ref)
Definition: transform_cl.c:418
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
static int methsig_to_disk(OR_BUF *buf, SM_METHOD_SIGNATURE *sig)
DB_TYPE id
#define OR_OFFSET_SIZE_FLAG
#define DB_IS_NULL(value)
Definition: dbtype.h:63
static int tf_attribute_default_expr_to_property(SM_ATTRIBUTE *attr_list)
#define OR_GET_OFFSET_SIZE(ptr)
static void fixup_callback(LC_OIDMAP *oidmap)
Definition: transform_cl.c:572
struct or_fixup OR_FIXUP
#define STATIC_CAST(dest_type, expr)
Definition: porting.h:1050
static WHEN_DESC on_error
static void methfile_to_disk_lwriter(void *buf, void *file)
const char * name
Definition: class_object.h:385
static SM_METHOD_FILE * disk_to_methfile(OR_BUF *buf)
int or_get_data(OR_BUF *buf, char *data, int length)
static int put_attributes(OR_BUF *buf, char *obj, SM_CLASS *class_)
Definition: transform_cl.c:706
DB_SEQ * classobj_make_prop()
Definition: class_object.c:280
#define DB_MAX_VARNCHAR_PRECISION
Definition: dbtype_def.h:546
struct sm_attribute * order_link
Definition: class_object.h:461
static SM_REPRESENTATION * disk_to_representation(OR_BUF *buf)
int mc_fixed_size
Definition: transform.h:54
MOP sm_Root_class_mop
static int optimize_sets(SM_CLASS *class_, MOBJ volatile obj)
Definition: transform_cl.c:310
static int resolution_to_disk(OR_BUF *buf, SM_RESOLUTION *res)
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int setval(DB_VALUE *dest, const DB_VALUE *src, bool copy) const
int db_make_int(DB_VALUE *value, const int num)
struct db_object * class_mop
Definition: object_domain.h:81
short volid
Definition: dbtype_def.h:887
int or_put_sub_domain(OR_BUF *buf)
MOP sm_find_class(const char *name)
int mc_n_variable
Definition: transform.h:53
static ROOT_CLASS * disk_to_root(OR_BUF *buf)
#define OR_BOUND_BIT_FLAG
static void method_to_disk_lwriter(void *buf, void *method)
INT32 PAGEID
#define OID_ISNULL(oidp)
Definition: oid.h:81
#define SET_AUTO_INCREMENT_SERIAL_NAME(SR_NAME, CL_NAME, AT_NAME)
Definition: transform.h:176
#define LANG_SYS_CODESET
int or_get_int(OR_BUF *buf, int *error)
int collation_id
Definition: object_domain.h:92
char * ws_copy_string(const char *str)
Definition: work_space.c:3457
int or_get_value(OR_BUF *buf, DB_VALUE *value, struct tp_domain *domain, int expected, bool copy)
int get_disk_size_of_mem(const void *mem, const tp_domain *domain=NULL) const
TP_DOMAIN * domain
Definition: class_object.h:652
int or_pad(OR_BUF *buf, int length)
static DB_LIST * get_substructure_set(OR_BUF *buf, LREADER reader, int expected)
static int methsig_size(SM_METHOD_SIGNATURE *sig)
MOP do_get_serial_obj_id(DB_IDENTIFIER *serial_obj_id, DB_OBJECT *serial_class_mop, const char *serial_name)
static int method_size(SM_METHOD *method)
DB_LIST * classobj_alloc_threaded_array(int size, int count)
Definition: class_object.c:211
OID mc_classoid
Definition: transform.h:51
TP_DOMAIN * tp_domain_new(DB_TYPE type)
struct db_list * next
Definition: dbtype_def.h:417
static void or_pack_mop(OR_BUF *buf, MOP mop)
#define TF_SUCCESS
Definition: transform_cl.h:45
void classobj_fixup_loaded_class(SM_CLASS *class_)
#define ER_TF_INVALID_REPRESENTATION
Definition: error_code.h:391
SM_REPRESENTATION * classobj_make_representation()
static int domain_size(TP_DOMAIN *domain)
const char * comment
Definition: class_object.h:467
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)
int or_advance(OR_BUF *buf, int offset)
static void install_substructure_set(OR_BUF *buf, DB_LIST *list, VREADER reader, int expected)
DB_DEFAULT_EXPR_TYPE
Definition: dbtype_def.h:1181
int pr_complete_enum_value(DB_VALUE *value, struct tp_domain *domain)
#define OR_GET_BOUND_BIT(bitptr, element)
DB_LIST *(* LREADER)(void *)
Definition: transform_cl.c:122
int get_disk_size_of_value(const DB_VALUE *value) const
int classobj_drop_prop(DB_SEQ *properties, const char *name)
Definition: class_object.c:394
META_CLASS tf_Metaclass_methfile
Definition: transform.c:139
int classobj_put_prop(DB_SEQ *properties, const char *name, DB_VALUE *pvalue)
Definition: class_object.c:314
#define TP_DOMAIN_COLLATION_FLAG(dom)
int variable_count
Definition: class_object.h:738
TF_STATUS tf_mem_to_disk(MOP classmop, MOBJ classobj, MOBJ volatile obj, RECDES *record, bool *index_flag)
Definition: transform_cl.c:767