CUBRID Engine  latest
load_object.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * load_object.c: simplified object descriptions.
21  */
22 
23 #include "config.h"
24 
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <assert.h>
28 #if defined(WINDOWS)
29 #include <io.h>
30 #else
31 #include <unistd.h>
32 #endif
33 #include <ctype.h>
34 #include <sys/stat.h>
35 #include <math.h>
36 
37 #include "utility.h"
38 #include "misc_string.h"
39 #include "memory_alloc.h"
40 #include "dbtype.h"
41 #include "object_representation.h"
42 #include "work_space.h"
43 #include "class_object.h"
44 #include "object_primitive.h"
45 #include "set_object.h"
46 #include "db.h"
47 #include "schema_manager.h"
48 #include "server_interface.h"
49 #include "load_object.h"
50 #include "db_value_printer.hpp"
51 #include "network_interface_cl.h"
52 #include "printer.hpp"
53 
54 #include "message_catalog.h"
55 #include "string_opfunc.h"
56 #if defined(WINDOWS)
57 #include "porting.h"
58 #endif
59 
60 #define MIGRATION_CHUNK 4096
62 
63 static int object_disk_size (DESC_OBJ * obj, int *offset_size_ptr);
64 static void put_varinfo (OR_BUF * buf, DESC_OBJ * obj, int offset_size);
65 static void put_attributes (OR_BUF * buf, DESC_OBJ * obj);
66 static void get_desc_current (OR_BUF * buf, SM_CLASS * class_, DESC_OBJ * obj, int bound_bit_flag, int offset_size);
67 static SM_ATTRIBUTE *find_current_attribute (SM_CLASS * class_, int id);
68 static void get_desc_old (OR_BUF * buf, SM_CLASS * class_, int repid, DESC_OBJ * obj, int bound_bit_flag,
69  int offset_size);
70 static void print_set (print_output & output_ctx, DB_SET * set);
71 static int fprint_special_set (TEXT_OUTPUT * tout, DB_SET * set);
72 static int bfmt_print (int bfmt, const DB_VALUE * the_db_bit, char *string, int max_size);
73 static const char *strnchr (const char *str, char ch, int nbytes);
74 static int print_quoted_str (TEXT_OUTPUT * tout, const char *str, int len, int max_token_len);
75 static void itoa_strreverse (char *begin, char *end);
76 static int itoa_print (TEXT_OUTPUT * tout, DB_BIGINT value, int base);
77 static int fprint_special_strings (TEXT_OUTPUT * tout, DB_VALUE * value);
78 static void init_load_err_filter (void);
79 static void default_clear_err_filter (void);
80 
81 /*
82  * make_desc_obj - Makes an object descriptor for a particular class.
83  * return: object descriptor
84  * class(in): class structure
85  */
86 DESC_OBJ *
88 {
89  DESC_OBJ *obj;
90  SM_ATTRIBUTE *att;
91  int i;
92 
93  if ((obj = (DESC_OBJ *) malloc (sizeof (DESC_OBJ))) == NULL)
94  {
95  return NULL;
96  }
97  if (class_ == NULL)
98  {
99  return obj;
100  }
101 
102  obj->classop = NULL;
103  obj->class_ = class_;
104  obj->updated_flag = 0;
105  obj->count = class_->att_count;
106  obj->atts = NULL;
107  obj->values = NULL;
108  if (class_->att_count)
109  {
110  obj->values = (DB_VALUE *) malloc (sizeof (DB_VALUE) * class_->att_count);
111  if (obj->values == NULL)
112  {
113  free_and_init (obj);
114  return NULL;
115  }
116  obj->atts = (SM_ATTRIBUTE **) malloc (sizeof (SM_ATTRIBUTE *) * class_->att_count);
117  if (obj->atts == NULL)
118  {
119  free_and_init (obj->values);
120  free_and_init (obj);
121  return NULL;
122  }
123  for (i = 0, att = class_->attributes; i < class_->att_count; i++, att = (SM_ATTRIBUTE *) att->header.next)
124  {
125  db_make_null (&obj->values[i]);
126  obj->atts[i] = att;
127  }
128  }
129  return obj;
130 }
131 
132 /*
133  * desc_free - Frees the storage for an object descriptor.
134  * return: none
135  * obj(out): object descriptor
136  */
137 void
139 {
140  int i;
141 
142  if (obj == NULL)
143  {
144  return;
145  }
146 
147  if (obj->count && obj->values != NULL)
148  {
149  for (i = 0; i < obj->count; i++)
150  {
151  pr_clear_value (&obj->values[i]);
152  }
153  free_and_init (obj->values);
154  }
155  if (obj->atts != NULL)
156  {
157  free_and_init (obj->atts);
158  }
159  free_and_init (obj);
160 }
161 
162 /*
163  * object_disk_size - Calculates the total number of bytes required for the
164  * storage of an object as defined with an object descriptor structure.
165  * return: size in bytes
166  * obj(in): object descriptor
167  */
168 static int
169 object_disk_size (DESC_OBJ * obj, int *offset_size_ptr)
170 {
171  SM_ATTRIBUTE *att;
172  SM_CLASS *class_;
173  int a, i;
174  volatile int size;
175 
176  *offset_size_ptr = OR_BYTE_SIZE;
177 
178  class_ = obj->class_;
179 
180 re_check:
182 
183  if (class_->variable_count)
184  {
185  size += OR_VAR_TABLE_SIZE_INTERNAL (class_->variable_count, *offset_size_ptr);
186  for (a = class_->fixed_count; a < class_->att_count; a++)
187  {
188  att = &class_->attributes[a];
189 
190  for (i = 0; i < obj->count; i++)
191  {
192  if (obj->atts[i] == att)
193  {
194  break;
195  }
196  }
197  if (i < obj->count)
198  {
199  if (att->type->variable_p)
200  {
201  size += pr_data_writeval_disk_size (&obj->values[i]);
202  }
203  else
204  {
205  size += tp_domain_disk_size (att->domain);
206  }
207  }
208  else
209  {
210  if (att->type->variable_p)
211  {
212  if (!DB_IS_NULL (&att->default_value.value))
213  {
215  }
216  }
217  else
218  {
219  size += tp_domain_disk_size (att->domain);
220  }
221  }
222  }
223  }
224 
225  if (*offset_size_ptr == OR_BYTE_SIZE && size > OR_MAX_BYTE)
226  {
227  *offset_size_ptr = OR_SHORT_SIZE; /* 2byte */
228  goto re_check;
229  }
230  if (*offset_size_ptr == OR_SHORT_SIZE && size > OR_MAX_SHORT)
231  {
232  *offset_size_ptr = BIG_VAR_OFFSET_SIZE; /* 4byte */
233  goto re_check;
234  }
235  return (size);
236 }
237 
238 /*
239  * put_varinfo - Writes the variable offset table for an object defined by
240  * an object descriptor structure.
241  * return: void
242  * buf(out): transformer buffer
243  * obj(in): object
244  */
245 static void
246 put_varinfo (OR_BUF * buf, DESC_OBJ * obj, int offset_size)
247 {
248  SM_ATTRIBUTE *att;
249  SM_CLASS *class_;
250  int a, offset, len, i;
251 
252  class_ = obj->class_;
253 
254  if (class_->variable_count)
255  {
256  /* compute the variable offsets relative to the end of the header (beginning of variable table) */
257  offset =
259  offset_size) + class_->fixed_size + OR_BOUND_BIT_BYTES (class_->fixed_count);
260 
261  for (a = class_->fixed_count; a < class_->att_count; a++)
262  {
263  att = &class_->attributes[a];
264 
265  for (i = 0; i < obj->count; i++)
266  {
267  if (obj->atts[i] == att)
268  {
269  break;
270  }
271  }
272  len = 0;
273  if (i < obj->count)
274  {
275  if (att->type->variable_p)
276  {
277  len = pr_data_writeval_disk_size (&obj->values[i]);
278  }
279  else
280  {
281  len = tp_domain_disk_size (att->domain);
282  }
283  }
284  else
285  {
286  if (att->type->variable_p)
287  {
288  if (!DB_IS_NULL (&att->default_value.value))
289  {
291  }
292  }
293  else
294  {
295  len = tp_domain_disk_size (att->domain);
296  }
297  }
298  or_put_offset_internal (buf, offset, offset_size);
299  offset += len;
300  }
301  or_put_offset_internal (buf, offset, offset_size);
302  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
303  }
304 }
305 
306 /*
307  * put_attributes - Writes the attribute values for an object defined by
308  * an object descriptor structure.
309  * return: void
310  * buf(out): transformer buffer
311  * obj(in): object descriptor
312  */
313 static void
315 {
316  SM_ATTRIBUTE *att;
317  int i, bsize, pad;
318  char *bits, *start;
319 
320  /* allocate bound bit array */
321  bits = NULL;
322  bsize = OR_BOUND_BIT_BYTES (obj->class_->fixed_count);
323  if (bsize)
324  {
325  bits = (char *) malloc (bsize);
326  if (bits == NULL)
327  {
328  goto error;
329  }
330  else
331  {
332  memset (bits, 0, bsize);
333  }
334  }
335 
336  /*
337  * Write fixed attribute values, if unbound, leave zero or garbage
338  * it doesn't matter, if the attribute is bound, set the appropriate
339  * bit in the bound bit array
340  */
341  start = buf->ptr;
342  for (att = obj->class_->attributes; att != NULL && !att->type->variable_p; att = (SM_ATTRIBUTE *) att->header.next)
343  {
344  for (i = 0; i < obj->count && obj->atts[i] != att; i++);
345 
346  if (i < obj->count)
347  {
348  if (DB_IS_NULL (&obj->values[i]))
349  {
350  or_pad (buf, tp_domain_disk_size (att->domain));
351  }
352  else
353  {
354  pr_data_writeval (buf, &obj->values[i]);
355  if (bits != NULL)
356  {
357  OR_ENABLE_BOUND_BIT (bits, att->storage_order);
358  }
359  }
360  }
361  else
362  {
363  /* no value, use default if one exists */
364  if (DB_IS_NULL (&att->default_value.value))
365  {
366  or_pad (buf, tp_domain_disk_size (att->domain));
367  }
368  else
369  {
370  pr_data_writeval (buf, &att->default_value.value);
371  if (bits != NULL)
372  {
373  OR_ENABLE_BOUND_BIT (bits, att->storage_order);
374  }
375  }
376  }
377  }
378 
379  /* bring the end of the fixed width block up to proper alignment */
380  pad = (int) (buf->ptr - start);
381  if (pad < obj->class_->fixed_size)
382  {
383  or_pad (buf, obj->class_->fixed_size - pad);
384  }
385  else if (pad > obj->class_->fixed_size)
386  {
387  /* mismatched fixed block calculations */
389  goto error;
390  }
391 
392  /* now write the bound bits if we have any */
393  if (bits != NULL)
394  {
395  or_put_data (buf, bits, bsize);
396  /*
397  * We do not need the bits array anymore, lets free it now.
398  * the pr_data_writeval() function can perform a longjmp()
399  * back to the calling function if we get an overflow,
400  * and bits will not be freed.
401  */
402  free_and_init (bits);
403  }
404 
405  /* finaly do the variable width attributes */
406  for (; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
407  {
408  for (i = 0; i < obj->count && obj->atts[i] != att; i++);
409 
410  if (i < obj->count)
411  {
412  if (!DB_IS_NULL (&obj->values[i]))
413  {
414  pr_data_writeval (buf, &obj->values[i]);
415  }
416  }
417  else
418  {
419  if (!DB_IS_NULL (&att->default_value.value))
420  {
421  pr_data_writeval (buf, &att->default_value.value);
422  }
423  }
424  }
425 
426  return;
427 
428 error:
429  if (bits != NULL)
430  {
431  free_and_init (bits);
432  }
433  or_abort (buf);
434 }
435 
436 /*
437  * text_print_flush - flush TEXT_OUTPUT contents to file
438  * return: NO_ERROR if successful, ER_IO_WRITE if file I/O error occurred
439  * tout(in/out): TEXT_OUTPUT structure
440  */
441 int
443 {
444  /* flush to disk */
445  if (tout->count != (int) fwrite (tout->buffer, 1, tout->count, tout->fp))
446  {
447  return ER_IO_WRITE;
448  }
449 
450  /* re-init */
451  tout->ptr = tout->buffer;
452  tout->count = 0;
453 
454  return NO_ERROR;
455 }
456 
457 /*
458  * text_print - print formatted text to TEXT_OUTPUT
459  * return: NO_ERROR if successful, error code otherwise
460  * tout(out): TEXT_OUTPUT
461  * buf(in): source buffer
462  * buflen(in): length of buffer
463  * fmt(in): format string
464  * ...(in): arguments
465  */
466 int
467 text_print (TEXT_OUTPUT * tout, const char *buf, int buflen, char const *fmt, ...)
468 {
469  int error = NO_ERROR;
470  int nbytes, size;
471  va_list ap;
472 
473  assert (buflen >= 0);
474 
475 start:
476  size = tout->iosize - tout->count; /* free space size */
477 
478  if (buflen)
479  {
480  nbytes = buflen; /* unformatted print */
481  }
482  else
483  {
484  va_start (ap, fmt);
485  nbytes = vsnprintf (tout->ptr, size, fmt, ap);
486  va_end (ap);
487  }
488 
489  if (nbytes > 0)
490  {
491  if (nbytes < size)
492  { /* OK */
493  if (buflen > 0)
494  { /* unformatted print */
495  assert (buf != NULL);
496  memcpy (tout->ptr, buf, buflen);
497  *(tout->ptr + buflen) = '\0'; /* Null terminate */
498  }
499  tout->ptr += nbytes;
500  tout->count += nbytes;
501  }
502  else
503  { /* need more buffer */
505  goto start; /* retry */
506  }
507  }
508 
509 exit_on_end:
510  return error;
511 
512 exit_on_error:
513  CHECK_EXIT_ERROR (error);
514  goto exit_on_end;
515 }
516 
517 /*
518  * desc_obj_to_disk - transforms the object into a disk record for eventual
519  * storage.
520  * return: size in bytes (negative if buffer overflow)
521  * obj(in): object descriptor
522  * record(out): disk record
523  * index_flag(in): set to non-zero if object has indexed attributes
524  * Note:
525  * This is functionally similar to tf_mem_to_disk except that
526  * the object is defined using an object descriptor rather than
527  * a workspace object.
528  * If it returns a number less than zero, there was not enough room
529  * in the buffer and the transformation was aborted.
530  */
531 int
532 desc_obj_to_disk (DESC_OBJ * obj, RECDES * record, bool * index_flag)
533 {
534  OR_BUF orep, *buf;
535  int error, status;
536  bool has_index = false;
537  unsigned int repid_bits;
538  int expected_disk_size;
539  int offset_size;
540 
541  buf = &orep;
542  or_init (buf, record->data, record->area_size);
543  buf->error_abort = 1;
544 
545  expected_disk_size = object_disk_size (obj, &offset_size);
546  if (record->area_size < (expected_disk_size + (OR_MVCC_MAX_HEADER_SIZE - OR_MVCC_INSERT_HEADER_SIZE)))
547  {
548  record->length = -expected_disk_size;
549 
550  *index_flag = false;
551  return (1);
552  }
553 
554  status = setjmp (buf->env);
555  if (status == 0)
556  {
557  error = 0;
558 
559  if (OID_ISTEMP (WS_OID (obj->classop)))
560  {
562  return (1);
563  }
564 
565  /* header */
566 
567  repid_bits = obj->class_->repid;
568  if (obj->class_->fixed_count)
569  {
570  repid_bits |= OR_BOUND_BIT_FLAG;
571  }
572 
573  /* offset size */
574  OR_SET_VAR_OFFSET_SIZE (repid_bits, offset_size);
575 
577  or_put_int (buf, repid_bits);
578  or_put_int (buf, 0); /* CHN, fixed size */
579  or_put_bigint (buf, MVCCID_NULL); /* MVCC insert id */
580 
581  /* variable info block */
582  put_varinfo (buf, obj, offset_size);
583 
584  /* attributes, fixed followed by bound bits, followed by variable */
585  put_attributes (buf, obj);
586 
587  record->length = (int) (buf->ptr - buf->buffer);
588 
589  /* see if there are any indexes */
590  has_index = classobj_class_has_indexes (obj->class_);
591  }
592  else
593  {
594  assert (false); /* impossible case */
595 
596  /*
597  * error, currently can only be from buffer overflow
598  * might be nice to store the "size guess" from the class
599  * SHOULD BE USING TF_STATUS LIKE tf_mem_to_disk, need to
600  * merge these two programs !
601  */
602  record->length = -expected_disk_size;
603  error = 1;
604  has_index = false;
605  }
606 
607  *index_flag = has_index;
608  return (error);
609 }
610 
611 /*
612  * get_desc_current - reads the disk representation of an object and constructs
613  * an object descriptor.
614  * return: void
615  * buf(in/out): transformer buffer
616  * class(in): class structure
617  * obj(out): object descriptor
618  * bound_bit_flag(in): non-zero if we're using bound bits
619  * Note:
620  * The most current representation of the class is expected.
621  */
622 static void
623 get_desc_current (OR_BUF * buf, SM_CLASS * class_, DESC_OBJ * obj, int bound_bit_flag, int offset_size)
624 {
625  SM_ATTRIBUTE *att;
626  int *vars = NULL;
627  int i, j, offset, offset2, pad;
628  char *bits, *start;
629  int rc = NO_ERROR;
630 
631  /* need nicer way to store these */
632  if (class_->variable_count)
633  {
634  vars = (int *) malloc (sizeof (int) * class_->variable_count);
635  if (vars == NULL)
636  {
637  return;
638  }
639  /* get the offsets relative to the end of the header (beginning of variable table) */
640  offset = or_get_offset_internal (buf, &rc, offset_size);
641  for (i = 0; i < class_->variable_count; i++)
642  {
643  offset2 = or_get_offset_internal (buf, &rc, offset_size);
644  vars[i] = offset2 - offset;
645  offset = offset2;
646  }
647  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
648  }
649 
650  bits = NULL;
651  if (bound_bit_flag)
652  {
653  /* assume that the buffer is in contiguous memory and that we can seek ahead to the bound bits. */
654  bits = (char *) buf->ptr + obj->class_->fixed_size;
655  }
656 
657  att = class_->attributes;
658  start = buf->ptr;
659  for (i = 0; i < class_->fixed_count; i++, att = (SM_ATTRIBUTE *) att->header.next)
660  {
661 
662  if (bits != NULL && !OR_GET_BOUND_BIT (bits, i))
663  {
664  /* its a NULL value, skip it */
665  db_value_put_null (&obj->values[i]);
666  or_advance (buf, tp_domain_disk_size (att->domain));
667  }
668  else
669  {
670  /* read the disk value into the db_value */
671  att->type->data_readval (buf, &obj->values[i], att->domain, -1, true, NULL, 0);
672  }
673  }
674 
675  /* round up to a to the end of the fixed block */
676  pad = (int) (buf->ptr - start);
677  if (pad < obj->class_->fixed_size)
678  {
679  or_advance (buf, obj->class_->fixed_size - pad);
680  }
681 
682  /* skip over the bound bits */
683  if (bound_bit_flag)
684  {
686  }
687 
688  /* variable */
689  if (vars != NULL)
690  {
691  for (i = class_->fixed_count, j = 0; i < class_->att_count && j < class_->variable_count;
692  i++, j++, att = (SM_ATTRIBUTE *) att->header.next)
693  {
694  att->type->data_readval (buf, &obj->values[i], att->domain, vars[j], true, NULL, 0);
695  }
696 
697  free_and_init (vars);
698  }
699 }
700 
701 /*
702  * find_current_attribute - locates an attribute definition in a class.
703  * return: attribute structure
704  * class(in): class structure
705  * id(in): attribute id
706  */
707 static SM_ATTRIBUTE *
709 {
710  SM_ATTRIBUTE *att;
711 
712  for (att = class_->attributes; att != NULL; att = (SM_ATTRIBUTE *) att->header.next)
713  {
714  if (att->id == id)
715  {
716  return att;
717  }
718  }
719  return NULL;
720 }
721 
722 /*
723  * get_desc_old - loads the disk representation of an object into an object
724  * descriptor structure.
725  * return: void
726  * buf(in/out): transformer buffer
727  * class(in): class strcuture
728  * repid(in): repid of the stored instance
729  * obj(out): object descriptor being built
730  * bound_bit_flag(in): non-zero if using bound bits
731  * Note:
732  * This loads the disk representation of an object into an object
733  * descriptor structure. This function will handle the transformation
734  * of an obsolete representation of the object into its
735  * newest representation.
736  */
737 static void
738 get_desc_old (OR_BUF * buf, SM_CLASS * class_, int repid, DESC_OBJ * obj, int bound_bit_flag, int offset_size)
739 {
740  SM_REPRESENTATION *oldrep;
741  SM_REPR_ATTRIBUTE *rat, *found;
742  SM_ATTRIBUTE *att;
743  PR_TYPE *type;
744  int *vars = NULL;
745  int i, offset, offset2, total, bytes, att_index, padded_size, fixed_size;
746  SM_ATTRIBUTE **attmap = NULL;
747  char *bits, *start;
748  int rc = NO_ERROR;
749 
750  oldrep = classobj_find_representation (class_, repid);
751 
752  if (oldrep == NULL)
753  {
755  }
756  else
757  {
758  if (oldrep->variable_count)
759  {
760  /* need nicer way to store these */
761  vars = (int *) malloc (sizeof (int) * oldrep->variable_count);
762  if (vars == NULL)
763  {
764  goto abort_on_error;
765  }
766  /* compute the variable offsets relative to the end of the header (beginning of variable table) */
767  offset = or_get_offset_internal (buf, &rc, offset_size);
768  for (i = 0; i < oldrep->variable_count; i++)
769  {
770  offset2 = or_get_offset_internal (buf, &rc, offset_size);
771  vars[i] = offset2 - offset;
772  offset = offset2;
773  }
774  buf->ptr = PTR_ALIGN (buf->ptr, INT_ALIGNMENT);
775  }
776 
777  /* calculate an attribute map */
778  total = oldrep->fixed_count + oldrep->variable_count;
779  attmap = (SM_ATTRIBUTE **) malloc (sizeof (SM_ATTRIBUTE *) * total);
780  if (attmap == NULL)
781  {
782  goto abort_on_error;
783  }
784 
785  memset (attmap, 0, sizeof (SM_ATTRIBUTE *) * total);
786 
787  for (rat = oldrep->attributes, i = 0; rat != NULL; rat = rat->next, i++)
788  attmap[i] = find_current_attribute (class_, rat->attid);
789 
790  rat = oldrep->attributes;
791 
792  /* fixed */
793  start = buf->ptr;
794  for (i = 0; i < oldrep->fixed_count && rat != NULL; i++, rat = rat->next)
795  {
796  type = pr_type_from_id (rat->typeid_);
797  if (type == NULL)
798  {
799  goto abort_on_error;
800  }
801 
802  if (attmap[i] == NULL)
803  {
804  /* its gone, skip over it */
805  type->data_readval (buf, NULL, rat->domain, -1, true, NULL, 0);
806  }
807  else
808  {
809  /* its real, get it into the proper value */
810  type->data_readval (buf, &obj->values[attmap[i]->storage_order], rat->domain, -1, true, NULL, 0);
811  }
812  }
813 
814  fixed_size = (int) (buf->ptr - start);
815  padded_size = DB_ATT_ALIGN (fixed_size);
816  or_advance (buf, (padded_size - fixed_size));
817 
818  /*
819  * sigh, we now have to process the bound bits in much the same way as the
820  * attributes above, it would be nice if these could be done in parallel
821  * but we don't have the fixed size of the old representation so we
822  * can't easily sneak the buffer pointer forward, work on this someday
823  */
824  if (bound_bit_flag && oldrep->fixed_count)
825  {
826  bits = buf->ptr;
827  bytes = OR_BOUND_BIT_BYTES (oldrep->fixed_count);
828  if ((buf->ptr + bytes) > buf->endptr)
829  {
830  or_overflow (buf);
831  }
832 
833  rat = oldrep->attributes;
834  for (i = 0; i < oldrep->fixed_count && rat != NULL; i++, rat = rat->next)
835  {
836  if (attmap[i] != NULL)
837  {
838  if (!OR_GET_BOUND_BIT (bits, i))
839  {
840  DB_VALUE *v = &obj->values[attmap[i]->storage_order];
841  db_value_clear (v);
842  db_value_put_null (v);
843  }
844  }
845  }
846  or_advance (buf, bytes);
847  }
848 
849  /* variable */
850  for (i = 0; i < oldrep->variable_count && rat != NULL; i++, rat = rat->next)
851  {
852  type = pr_type_from_id (rat->typeid_);
853  if (type == NULL)
854  {
855  goto abort_on_error;
856  }
857 
858  att_index = i + oldrep->fixed_count;
859  if (attmap[att_index] == NULL)
860  {
861  /* its null, skip over it */
862  type->data_readval (buf, NULL, rat->domain, vars[i], true, NULL, 0);
863  }
864  else
865  {
866  /* read it into the proper value */
867  type->data_readval (buf, &obj->values[attmap[att_index]->storage_order], rat->domain, vars[i], true, NULL,
868  0);
869  }
870  }
871 
872  /*
873  * initialize new values
874  */
875  for (i = 0, att = class_->attributes; att != NULL; i++, att = (SM_ATTRIBUTE *) att->header.next)
876  {
877  found = NULL;
878  for (rat = oldrep->attributes; rat != NULL && found == NULL; rat = rat->next)
879  {
880  if (rat->attid == att->id)
881  {
882  found = rat;
883  }
884  }
885  if (found == NULL)
886  {
887  /*
888  * formerly used copy_value which converted MOP values to OID
889  * values, is this really necessary ?
890  */
892  }
893  }
894 
895  if (attmap != NULL)
896  {
897  free_and_init (attmap);
898  }
899  if (vars != NULL)
900  {
901  free_and_init (vars);
902  }
903 
904  obj->updated_flag = 1;
905  }
906  return;
907 
908 abort_on_error:
909  if (attmap != NULL)
910  {
911  free (attmap);
912  }
913  if (vars != NULL)
914  {
915  free (vars);
916  }
917  or_abort (buf);
918 }
919 
920 /*
921  * desc_disk_to_obj - similar to tf_disk_to_mem except that it builds an
922  * object descriptor structure rather than a workspace object.
923  * return: NO_ERROR if successful, error code otherwise
924  * classop(in): class MOP
925  * class(in): class structure
926  * record(in): disk record
927  * obj(out): object descriptor
928  */
929 int
930 desc_disk_to_obj (MOP classop, SM_CLASS * class_, RECDES * record, DESC_OBJ * obj)
931 {
932  volatile int error = NO_ERROR;
933  OR_BUF orep, *buf;
934  int repid, status;
935  unsigned int repid_bits;
936  int bound_bit_flag;
937  int save;
938  int i;
939  int rc = NO_ERROR;
940  int offset_size;
941 
942  if (obj == NULL)
943  {
944  return ER_FAILED;
945  }
946  else
947  {
948  /* clear previous values */
949  for (i = 0; i < obj->count; i++)
950  {
951  pr_clear_value (&obj->values[i]);
952  }
953  }
954 
955  /* Kludge, make sure we don't upgrade objects to OID'd during the reading */
958 
959  buf = &orep;
960  or_init (buf, record->data, record->length);
961  buf->error_abort = 1;
962 
963  obj->classop = classop;
964 
965  status = setjmp (buf->env);
966  if (status == 0)
967  {
968  char mvcc_flags;
969 
970  /* offset size */
971  offset_size = OR_GET_OFFSET_SIZE (buf->ptr);
972 
973  /* in case of MVCC, repid_bits contains MVCC flags */
974  repid_bits = or_mvcc_get_repid_and_flags (buf, &rc);
975  repid = repid_bits & OR_MVCC_REPID_MASK;
976 
977  mvcc_flags = (char) ((repid_bits >> OR_MVCC_FLAG_SHIFT_BITS) & OR_MVCC_FLAG_MASK);
978 
979  /* skip chn */
980  or_advance (buf, OR_INT_SIZE);
981 
982  if (mvcc_flags & OR_MVCC_FLAG_VALID_INSID)
983  {
984  /* skip insert id */
985  or_advance (buf, OR_MVCCID_SIZE);
986  }
987 
988  if (mvcc_flags & OR_MVCC_FLAG_VALID_DELID)
989  {
990  /* skip delete id */
991  or_advance (buf, OR_MVCCID_SIZE);
992  }
993 
994  if (mvcc_flags & OR_MVCC_FLAG_VALID_PREV_VERSION)
995  {
996  /* skip prev version lsa */
998  }
999 
1000  bound_bit_flag = repid_bits & OR_BOUND_BIT_FLAG;
1001 
1002  if (repid == class_->repid)
1003  {
1004  get_desc_current (buf, class_, obj, bound_bit_flag, offset_size);
1005  }
1006  else
1007  {
1008  get_desc_old (buf, class_, repid, obj, bound_bit_flag, offset_size);
1009  }
1010  }
1011  else
1012  {
1013  error = ER_TF_BUFFER_UNDERFLOW;
1014  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
1015  }
1016 
1017  pr_Inhibit_oid_promotion = save;
1018 
1019  return error;
1020 }
1021 
1022 /*
1023  * print_set - Print the contents of a real DB_SET (not a set descriptor).
1024  * return: void
1025  * output_ctx(in): output context
1026  * set(in): set reference
1027  */
1028 static void
1029 print_set (print_output & output_ctx, DB_SET * set)
1030 {
1031  DB_VALUE element_value;
1032  int len, i;
1033 
1034  len = set_size (set);
1035  output_ctx ("{");
1036  for (i = 0; i < len; i++)
1037  {
1038  if (set_get_element (set, i, &element_value) == NO_ERROR)
1039  {
1040  desc_value_print (output_ctx, &element_value);
1041  if (i < len - 1)
1042  {
1043  output_ctx (", ");
1044  }
1045  }
1046  }
1047  output_ctx ("}");
1048 }
1049 
1050 /*
1051  * fprint_special_set - Print the contents of a real DB_SET (not a set
1052  * descriptor).
1053  * return: NO_ERROR, if successful, error code otherwise
1054  * tout(in/out): TEXT_OUTPUT structure
1055  * set(in): set reference
1056  */
1057 static int
1059 {
1060  int error = NO_ERROR;
1061  DB_VALUE element_value;
1062  int len, i;
1063 
1064  len = set_size (set);
1065  CHECK_PRINT_ERROR (text_print (tout, "{", 1, NULL));
1066  for (i = 0; i < len; i++)
1067  {
1068  if (set_get_element (set, i, &element_value) == NO_ERROR)
1069  {
1070  CHECK_PRINT_ERROR (desc_value_special_fprint (tout, &element_value));
1071  if (i < len - 1)
1072  {
1073  CHECK_PRINT_ERROR (text_print (tout, ",\n ", 2, NULL));
1074  }
1075  }
1076  }
1077  CHECK_PRINT_ERROR (text_print (tout, "}", 1, NULL));
1078 
1079 exit_on_end:
1080  return error;
1081 
1082 exit_on_error:
1083  CHECK_EXIT_ERROR (error);
1084  goto exit_on_end;
1085 }
1086 
1087 /*
1088  * bfmt_print - Change the given string to a representation of the given bit
1089  * string value in the given format.
1090  * return: -1 if max_size too small, 0 if successful
1091  * bfmt(in): format of bit string (binary or hex format)
1092  * the_db_bit(in): input DB_VALUE
1093  * string(out): output buffer
1094  * max_size(in): size of string
1095  * Note:
1096  * max_size specifies the maximum number of chars that can be stored in
1097  * the string (including final '\0' char); if this is not long enough to
1098  * contain the new string, then an error is returned.
1099  */
1100 #define MAX_DISPLAY_COLUMN 70
1101 #define DBL_MAX_DIGITS ((int)ceil(DBL_MAX_EXP * log10(FLT_RADIX)))
1102 
1103 #define BITS_IN_BYTE 8
1104 #define HEX_IN_BYTE 2
1105 #define BITS_IN_HEX 4
1106 #define BYTE_COUNT(bit_cnt) (((bit_cnt)+BITS_IN_BYTE-1)/BITS_IN_BYTE)
1107 #define BYTE_COUNT_HEX(bit_cnt) (((bit_cnt)+BITS_IN_HEX-1)/BITS_IN_HEX)
1108 
1109 static int
1110 bfmt_print (int bfmt, const DB_VALUE * the_db_bit, char *string, int max_size)
1111 {
1112  /*
1113  * Description:
1114  */
1115  int length = 0;
1116  int string_index = 0;
1117  int byte_index;
1118  int bit_index;
1119  const char *bstring;
1120  int error = NO_ERROR;
1121  static char digits[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
1122  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1123  };
1124 
1125  /* Get the buffer and the length from the_db_bit */
1126  bstring = db_get_bit (the_db_bit, &length);
1127 
1128  switch (bfmt)
1129  {
1130  case 0: /* BIT_STRING_BINARY */
1131  if (length + 1 > max_size)
1132  {
1133  error = -1;
1134  }
1135  else
1136  {
1137  for (byte_index = 0; byte_index < BYTE_COUNT (length); byte_index++)
1138  {
1139  for (bit_index = 7; bit_index >= 0 && string_index < length; bit_index--)
1140  {
1141  *string = digits[((bstring[byte_index] >> bit_index) & 0x1)];
1142  string++;
1143  string_index++;
1144  }
1145  }
1146  *string = '\0';
1147  }
1148  break;
1149 
1150  case 1: /* BIT_STRING_HEX */
1151  if (BYTE_COUNT_HEX (length) + 1 > max_size)
1152  {
1153  error = -1;
1154  }
1155  else
1156  {
1157  for (byte_index = 0; byte_index < BYTE_COUNT (length); byte_index++)
1158  {
1159  *string = digits[((bstring[byte_index] >> BITS_IN_HEX) & 0x0f)];
1160  string++;
1161  string_index++;
1162  if (string_index < BYTE_COUNT_HEX (length))
1163  {
1164  *string = digits[((bstring[byte_index] & 0x0f))];
1165  string++;
1166  string_index++;
1167  }
1168  }
1169  *string = '\0';
1170  }
1171  break;
1172 
1173  default:
1174  break;
1175  }
1176 
1177  return error;
1178 }
1179 
1180 /*
1181  * strnchr - strchr with string length constraints
1182  * return: a pointer to the given 'ch', or a null pointer if not found
1183  * str(in): string
1184  * ch(in): character to find
1185  * nbytes(in): length of string
1186  */
1187 const static char *
1188 strnchr (const char *str, char ch, int nbytes)
1189 {
1190  for (; nbytes; str++, nbytes--)
1191  {
1192  if (*str == ch)
1193  {
1194  return str;
1195  }
1196  }
1197  return NULL;
1198 }
1199 
1200 /*
1201  * print_quoted_str - print quoted string sequences separated by new line to
1202  * TEXT_OUTPUT given
1203  * return: NO_ERROR if successful, error code otherwise
1204  * tout(out): destination buffer
1205  * str(in) : string input
1206  * len(in): length of string
1207  * max_token_len(in): width of string to format
1208  * Note:
1209  * FIXME :: return error in fwrite...
1210  */
1211 static int
1212 print_quoted_str (TEXT_OUTPUT * tout, const char *str, int len, int max_token_len)
1213 {
1214  int error = NO_ERROR;
1215  const char *p, *end;
1216  int partial_len, write_len, left_nbytes;
1217  const char *internal_quote_p;
1218 
1219  /* opening quote */
1220  CHECK_PRINT_ERROR (text_print (tout, "'", 1, NULL));
1221 
1222  left_nbytes = 0;
1223  internal_quote_p = strnchr (str, '\'', len); /* first found single-quote */
1224  for (p = str, end = str + len, partial_len = len; p < end; p += write_len, partial_len -= write_len)
1225  {
1226  write_len = MIN (partial_len, left_nbytes > 0 ? left_nbytes : max_token_len);
1227  if (internal_quote_p == NULL || (p + write_len <= internal_quote_p))
1228  {
1229  /* not found single-quote in write_len */
1230  CHECK_PRINT_ERROR (text_print (tout, p, write_len, NULL));
1231  if (p + write_len < end) /* still has something to work */
1232  {
1233  CHECK_PRINT_ERROR (text_print (tout, "\'+\n \'", 5, NULL));
1234  }
1235  left_nbytes = 0;
1236  }
1237  else
1238  {
1239  left_nbytes = write_len;
1240  write_len = CAST_STRLEN (internal_quote_p - p + 1);
1241  CHECK_PRINT_ERROR (text_print (tout, p, write_len, NULL));
1242  left_nbytes -= (write_len + 1);
1243  /*
1244  * write internal "'" as "''", check for still has something to
1245  * work
1246  */
1248  (tout, (left_nbytes <= 0) ? "'\'+\n \'" : "'", (left_nbytes <= 0) ? 6 : 1, NULL));
1249  /* found the next single-quote */
1250  internal_quote_p = strnchr (p + write_len, '\'', partial_len - write_len);
1251  }
1252  }
1253 
1254  /* closing quote */
1255  CHECK_PRINT_ERROR (text_print (tout, "'", 1, NULL));
1256 
1257 exit_on_end:
1258  return error;
1259 
1260 exit_on_error:
1261  CHECK_EXIT_ERROR (error);
1262  goto exit_on_end;
1263 }
1264 
1265 #define INTERNAL_BUFFER_SIZE (400) /* bigger than DBL_MAX_DIGITS */
1266 
1267 /*
1268  * itoa_strreverse - reverse a string
1269  * return: void
1270  * begin(in/out): begin position of a string
1271  * end(in/out): end position of a string
1272  */
1273 static void
1274 itoa_strreverse (char *begin, char *end)
1275 {
1276  char aux;
1277 
1278  while (end > begin)
1279  {
1280  aux = *end;
1281  *end-- = *begin;
1282  *begin++ = aux;
1283  }
1284 }
1285 
1286 /*
1287  * itoa_print - 'itoa' print to TEXT_OUTPUT
1288  * return: NO_ERROR, if successful, error number, if not successful.
1289  * tout(out): output
1290  * value(in): value container
1291  * base(in): radix
1292  * Note:
1293  * Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C"
1294  * with slight modification to optimize for specific architecture:
1295  */
1296 static int
1297 itoa_print (TEXT_OUTPUT * tout, DB_BIGINT value, int base)
1298 {
1299  int error = NO_ERROR;
1300  char *wstr;
1301  bool is_negative;
1302  DB_BIGINT quotient;
1303  DB_BIGINT remainder;
1304  int nbytes;
1305  static const char itoa_digit[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1306 
1307  wstr = tout->ptr;
1308 
1309  /* Validate base */
1310  if (base < 2 || base > 35)
1311  {
1312  goto exit_on_error; /* give up */
1313  }
1314 
1315  /* Take care of sign - in case of INT_MIN, it remains as it is */
1316  is_negative = (value < 0) ? true : false;
1317  if (is_negative)
1318  {
1319  value = -value; /* change to the positive number */
1320  }
1321 
1322  /* Conversion. Number is reversed. */
1323  do
1324  {
1325  quotient = value / base;
1326  remainder = value % base;
1327  *wstr++ = itoa_digit[(remainder >= 0) ? remainder : -remainder];
1328  }
1329  while ((value = quotient) != 0);
1330 
1331  if (is_negative)
1332  {
1333  *wstr++ = '-';
1334  }
1335  *wstr = '\0'; /* Null terminate */
1336 
1337  /* Reverse string */
1338  itoa_strreverse (tout->ptr, wstr - 1);
1339 
1340  nbytes = CAST_STRLEN (wstr - tout->ptr);
1341 
1342  tout->ptr += nbytes;
1343  tout->count += nbytes;
1344 
1345 exit_on_end:
1346  return error;
1347 
1348 exit_on_error:
1349  CHECK_EXIT_ERROR (error);
1350  goto exit_on_end;
1351 }
1352 
1353 /*
1354  * fprint_special_strings - print special DB_VALUE to TEXT_OUTPUT
1355  * return: NO_ERROR if successful, error code otherwise
1356  * tout(out): output
1357  * value(in): DB_VALUE
1358  */
1359 static int
1361 {
1362  int error = NO_ERROR;
1363  char buf[INTERNAL_BUFFER_SIZE];
1364  char *ptr;
1365  const char *str_ptr = NULL;
1366  char *json_body = NULL;
1367  DB_TYPE type;
1368  int len;
1369  DB_DATETIMETZ *dt_tz;
1370  DB_TIMESTAMPTZ *ts_tz;
1371 
1372  type = DB_VALUE_TYPE (value);
1373  switch (type)
1374  {
1375  case DB_TYPE_NULL:
1376  CHECK_PRINT_ERROR (text_print (tout, "NULL", 4, NULL));
1377  break;
1378 
1379  case DB_TYPE_BIGINT:
1380  if (tout->iosize - tout->count < INTERNAL_BUFFER_SIZE)
1381  {
1382  /* flush remaining buffer */
1384  }
1385  CHECK_PRINT_ERROR (itoa_print (tout, db_get_bigint (value), 10 /* base */ ));
1386  break;
1387  case DB_TYPE_INTEGER:
1388  if (tout->iosize - tout->count < INTERNAL_BUFFER_SIZE)
1389  {
1390  /* flush remaining buffer */
1392  }
1393  CHECK_PRINT_ERROR (itoa_print (tout, db_get_int (value), 10 /* base */ ));
1394  break;
1395  case DB_TYPE_SMALLINT:
1396  if (tout->iosize - tout->count < INTERNAL_BUFFER_SIZE)
1397  {
1398  /* flush remaining buffer */
1400  }
1401  CHECK_PRINT_ERROR (itoa_print (tout, db_get_short (value), 10 /* base */ ));
1402  break;
1403 
1404  case DB_TYPE_FLOAT:
1405  case DB_TYPE_DOUBLE:
1406  {
1407  char *pos;
1408 
1409  pos = tout->ptr;
1411  (tout, NULL, 0, "%.*g", (type == DB_TYPE_FLOAT) ? 10 : 17,
1412  (type == DB_TYPE_FLOAT) ? db_get_float (value) : db_get_double (value)));
1413 
1414  /* if tout flushed, then this float/double should be the first content */
1415  if ((pos < tout->ptr && !strchr (pos, '.')) || (pos > tout->ptr && !strchr (tout->buffer, '.')))
1416  {
1417  CHECK_PRINT_ERROR (text_print (tout, ".", 1, NULL));
1418  }
1419  }
1420  break;
1421 
1422  case DB_TYPE_ENUMERATION:
1423  if (tout->iosize - tout->count < INTERNAL_BUFFER_SIZE)
1424  {
1425  /* flush remaining buffer */
1427  }
1428  CHECK_PRINT_ERROR (itoa_print (tout, db_get_enum_short (value), 10 /* base */ ));
1429  break;
1430 
1431  case DB_TYPE_DATE:
1433  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "date '%s'", buf));
1434  break;
1435 
1436  case DB_TYPE_TIME:
1438  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "time '%s'", buf));
1439  break;
1440 
1441  case DB_TYPE_TIMESTAMP:
1443  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "timestamp '%s'", buf));
1444  break;
1445 
1446  case DB_TYPE_TIMESTAMPLTZ:
1448  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "timestampltz '%s'", buf));
1449  break;
1450 
1451  case DB_TYPE_TIMESTAMPTZ:
1452  ts_tz = db_get_timestamptz (value);
1454  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "timestamptz '%s'", buf));
1455  break;
1456 
1457  case DB_TYPE_DATETIME:
1459  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "datetime '%s'", buf));
1460  break;
1461 
1462  case DB_TYPE_DATETIMELTZ:
1464  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "datetimeltz '%s'", buf));
1465  break;
1466 
1467  case DB_TYPE_DATETIMETZ:
1468  dt_tz = db_get_datetimetz (value);
1469  db_datetimetz_to_string (buf, MAX_DISPLAY_COLUMN, &dt_tz->datetime, &dt_tz->tz_id);
1470  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "datetimetz '%s'", buf));
1471  break;
1472 
1473  case DB_TYPE_MONETARY:
1474  /* Always print symbol before value, even if for turkish lira the user format is after value :
1475  * intl_get_currency_symbol_position */
1476  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "%s%.*f",
1478  db_get_monetary (value)->amount));
1479  break;
1480 
1481  case DB_TYPE_NCHAR:
1482  case DB_TYPE_VARNCHAR:
1483  CHECK_PRINT_ERROR (text_print (tout, "N", 1, NULL));
1484  /* fall through */
1485  case DB_TYPE_CHAR:
1486  case DB_TYPE_VARCHAR:
1487  str_ptr = db_get_string (value);
1488 
1489  len = db_get_string_size (value);
1490  if (len < 0)
1491  {
1492  len = (int) strlen (str_ptr);
1493  }
1494 
1495  CHECK_PRINT_ERROR (print_quoted_str (tout, str_ptr, len, MAX_DISPLAY_COLUMN));
1496  break;
1497 
1498  case DB_TYPE_NUMERIC:
1499  ptr = numeric_db_value_print (value, buf);
1500 
1501  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, !strchr (ptr, '.') ? "%s." : "%s", ptr));
1502  break;
1503 
1504  case DB_TYPE_BIT:
1505  case DB_TYPE_VARBIT:
1506  {
1507  int max_size = ((db_get_string_length (value) + 3) / 4) + 1;
1508  if (max_size > INTERNAL_BUFFER_SIZE)
1509  {
1510  ptr = (char *) malloc (max_size);
1511  if (ptr == NULL)
1512  {
1514  break; /* FIXME */
1515  }
1516  }
1517  else
1518  {
1519  ptr = buf;
1520  }
1521 
1522  if (bfmt_print (1 /* BIT_STRING_HEX */ , value, ptr, max_size) ==
1523  NO_ERROR)
1524  {
1525  CHECK_PRINT_ERROR (text_print (tout, "X", 1, NULL));
1526  CHECK_PRINT_ERROR (print_quoted_str (tout, ptr, max_size - 1, MAX_DISPLAY_COLUMN));
1527  }
1528 
1529  if (ptr != buf)
1530  {
1531  free_and_init (ptr);
1532  }
1533  break;
1534  }
1535 
1536  /* other stubs */
1537  case DB_TYPE_ERROR:
1538  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "%d", db_get_error (value)));
1539  break;
1540 
1541  case DB_TYPE_POINTER:
1542  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "%p", db_get_pointer (value)));
1543  break;
1544 
1545  case DB_TYPE_JSON:
1546  json_body = db_get_json_raw_body (value);
1547  CHECK_PRINT_ERROR (text_print (tout, NULL, 0, "'%s'", json_body));
1548  db_private_free (NULL, json_body);
1549  break;
1550 
1551  default:
1552  /* the others are handled by callers or internal-use only types */
1553  break;
1554  }
1555 
1556 exit_on_end:
1557  return error;
1558 
1559 exit_on_error:
1560  CHECK_EXIT_ERROR (error);
1561  goto exit_on_end;
1562 }
1563 
1564 /*
1565  * desc_value_special_fprint - Print a description of the given value.
1566  * return: NO_ERROR, if successful, error number, if not successful.
1567  * tout(out): TEXT_OUTPUT
1568  * value(in): value container
1569  * Note:
1570  * This is based on db_value_print() but has extensions for the
1571  * handling of set descriptors, and ELO's used by the desc_ module.
1572  * String printing is also hacked for "unprintable" characters.
1573  */
1574 int
1576 {
1577  int error = NO_ERROR;
1578 
1579  switch (DB_VALUE_TYPE (value))
1580  {
1581  case DB_TYPE_SET:
1582  case DB_TYPE_MULTISET:
1583  case DB_TYPE_SEQUENCE:
1585  break;
1586 
1587  case DB_TYPE_BLOB:
1588  case DB_TYPE_CLOB:
1590  break;
1591 
1592  default:
1593  CHECK_PRINT_ERROR (fprint_special_strings (tout, value));
1594  break;
1595  }
1596 
1597 exit_on_end:
1598  return error;
1599 
1600 exit_on_error:
1601  CHECK_EXIT_ERROR (error);
1602  goto exit_on_end;
1603 }
1604 
1605 /*
1606  * desc_value_print - Print a description of the given value.
1607  * return: void
1608  * output_ctx(in): output context
1609  * value(in): value container
1610  * Note:
1611  * This is based on db_value_print() but has extensions for the
1612  * handling of set descriptors, and ELO's used by the desc_ module.
1613  * String printing is also hacked for "unprintable" characters.
1614  */
1615 void
1616 desc_value_print (print_output & output_ctx, DB_VALUE * value)
1617 {
1618  switch (DB_VALUE_TYPE (value))
1619  {
1620  case DB_TYPE_SET:
1621  case DB_TYPE_MULTISET:
1622  case DB_TYPE_SEQUENCE:
1623  print_set (output_ctx, db_get_set (value));
1624  break;
1625 
1626  case DB_TYPE_BLOB:
1627  case DB_TYPE_CLOB:
1629  break;
1630 
1631  default:
1632  db_print_value (output_ctx, value);
1633  break;
1634  }
1635 }
1636 
1637 static bool filter_ignore_errors[-ER_LAST_ERROR] = { false, };
1638 
1639 static bool filter_ignore_init = false;
1640 /*
1641  * init_load_err_filter - init error filter array
1642  * return: void
1643  */
1644 static void
1646 {
1647  int ifrom, ito;
1648  memset (filter_ignore_errors, false, sizeof (filter_ignore_errors));
1649  filter_ignore_errors[0] = true; /* ER_WARNING_SEVERITY */
1650  for (ifrom = -ER_DISK_ALMOST_OUT_OF_SPACE, ito = -ER_DISK_TEMP_LAST_ALMOST_OUT_OF_SPACE; ifrom <= ito; ifrom++)
1651  {
1652  filter_ignore_errors[ifrom] = true;
1653  }
1656  filter_ignore_init = true;
1657 }
1658 
1659 /*
1660  * default_clear_err_filter - clear error filter array
1661  * return: void
1662  */
1663 static void
1665 {
1666  int ifrom, ito;
1667  filter_ignore_errors[0] = false; /* ER_WARNING_SEVERITY */
1668  for (ifrom = -ER_DISK_ALMOST_OUT_OF_SPACE, ito = -ER_DISK_TEMP_LAST_ALMOST_OUT_OF_SPACE; ifrom <= ito; ifrom++)
1669  {
1670  filter_ignore_errors[ifrom] = false;
1671  }
1673 }
1674 
1675 /*
1676  * init_load_err_filter - loads error codes from an external file.
1677  * return: number of error filter set
1678  */
1679 int
1681 {
1682  int i, num_ignore_error_list;
1683  int set_count = 0, errcode;
1684  char rdbuf[32];
1685  int ignore_error_list[-ER_LAST_ERROR];
1686 
1687  if (ef == NULL)
1688  {
1689  return set_count;
1690  }
1691  if (!filter_ignore_init)
1692  {
1694  }
1695  memset (rdbuf, 0, sizeof (rdbuf));
1696  while (feof (ef) == 0)
1697  {
1698  if (fgets (rdbuf, 30, ef) == NULL)
1699  {
1700  break;
1701  }
1702  if (rdbuf[0] == '#')
1703  {
1704  continue;
1705  }
1706  if (rdbuf[0] != '-' && rdbuf[0] != '+')
1707  {
1708  continue;
1709  }
1710  if (strncmp (rdbuf, "+DEFAULT", 8) == 0)
1711  {
1713  }
1714  else
1715  {
1716  errcode = atoi (&rdbuf[1]);
1717  if (errcode <= 0 || errcode >= -ER_LAST_ERROR)
1718  {
1719  continue;
1720  }
1721  if (rdbuf[0] == '-')
1722  {
1723  filter_ignore_errors[errcode] = true;
1724  }
1725  else
1726  {
1727  filter_ignore_errors[errcode] = false;
1728  }
1729  set_count++;
1730  }
1731  }
1732 
1733  /* set ws_ignore_error_list */
1734  for (i = 1, num_ignore_error_list = 0; i < -ER_LAST_ERROR; i++)
1735  {
1736  if (filter_ignore_errors[i] == true)
1737  {
1738  ignore_error_list[num_ignore_error_list] = -i;
1739  num_ignore_error_list++;
1740  }
1741  }
1742 
1743  if (num_ignore_error_list > 0)
1744  {
1745  ws_set_ignore_error_list_for_mflush (num_ignore_error_list, ignore_error_list);
1746  }
1747 
1748  return set_count;
1749 }
1750 
1751 // TODO: this is specific to loader. I don't think it belongs here.
1752 /*
1753  * er_filter_errid - check for ignorable errid
1754  * return: NO_ERROR if ignorable errid. otherwise, error-code clear
1755  * ignorable errid
1756  * ignore_warning(in): true to filter out warnings. otherwise, false
1757  */
1758 int
1759 er_filter_errid (bool ignore_warning)
1760 {
1761  int errcode = er_errid (), erridx;
1762 
1763  if (errcode == NO_ERROR)
1764  { /* don't have to check */
1765  return NO_ERROR;
1766  }
1767 
1768  if (!filter_ignore_init)
1769  { /* need to init */
1771  }
1772 
1773  erridx = (errcode < 0) ? -errcode : errcode;
1774  if (filter_ignore_errors[erridx])
1775  { /* ignore error if ignorable */
1776  goto clear_errid;
1777  }
1778 
1779  if (filter_ignore_errors[0])
1780  {
1781  if (ignore_warning && er_get_severity () == ER_WARNING_SEVERITY)
1782  {
1783  goto clear_errid;
1784  }
1785  }
1786 
1787 exit_on_end:
1788  return errcode;
1789 
1790 clear_errid:
1791  if (errcode != NO_ERROR)
1792  { /* clear ignorable errid */
1793  er_clearid ();
1794  errcode = NO_ERROR;
1795  }
1796  goto exit_on_end;
1797 }
1798 
1799 /* *INDENT-OFF* */
1800 void
1801 get_ignored_errors (std::vector<int> &vec)
1802 {
1803  for (int i = 0; i < -ER_LAST_ERROR; i++)
1804  {
1805  if (filter_ignore_errors[i])
1806  {
1807  vec.push_back (-i);
1808  }
1809  }
1810 }
1811 /* *INDENT-ON* */
SM_REPRESENTATION * classobj_find_representation(SM_CLASS *class_, int id)
#define OR_SET_VAR_OFFSET_SIZE(val, offset_size)
DB_C_FLOAT db_get_float(const DB_VALUE *value)
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 default_clear_err_filter(void)
Definition: load_object.c:1664
int tp_domain_disk_size(TP_DOMAIN *domain)
static int print_quoted_str(TEXT_OUTPUT *tout, const char *str, int len, int max_token_len)
Definition: load_object.c:1212
int count
Definition: load_object.h:59
void desc_value_print(print_output &output_ctx, DB_VALUE *value)
Definition: load_object.c:1616
#define NO_ERROR
Definition: error_code.h:46
int area_size
int db_value_put_null(DB_VALUE *value)
Definition: db_macro.c:122
DB_COLLECTION * db_get_set(const DB_VALUE *value)
int pr_data_writeval_disk_size(DB_VALUE *value)
SM_CLASS * class_
Definition: load_object.h:57
int fixed_count
Definition: class_object.h:737
int db_timestamptz_to_string(char *buf, int bufsize, DB_TIMESTAMP *utime, const TZ_ID *tz_id)
Definition: db_date.c:4090
void or_abort(OR_BUF *buf)
static int bfmt_print(int bfmt, const DB_VALUE *the_db_bit, char *string, int max_size)
Definition: load_object.c:1110
FILE * fp
Definition: load_object.h:75
char * MOBJ
Definition: work_space.h:174
static void begin(char *test_name)
DB_CONST_C_BIT db_get_bit(const DB_VALUE *value, int *length)
static bool filter_ignore_init
Definition: load_object.c:1639
int db_date_to_string(char *buf, int bufsize, DB_DATE *date)
Definition: db_date.c:3953
int db_get_int(const DB_VALUE *value)
DB_TIMESTAMP timestamp
Definition: dbtype_def.h:766
DB_TYPE
Definition: dbtype_def.h:670
int text_print(TEXT_OUTPUT *tout, const char *buf, int buflen, char const *fmt,...)
Definition: load_object.c:467
DB_C_DOUBLE db_get_double(const DB_VALUE *value)
#define ER_FAILED
Definition: error_code.h:47
#define OR_MVCC_REPID_MASK
int updated_flag
Definition: load_object.h:58
TP_DOMAIN * domain
Definition: class_object.h:444
static const char * strnchr(const char *str, char ch, int nbytes)
Definition: load_object.c:1188
#define ER_SM_CORRUPTED
Definition: error_code.h:335
int desc_obj_to_disk(DESC_OBJ *obj, RECDES *record, bool *index_flag)
Definition: load_object.c:532
SM_ATTRIBUTE * attributes
Definition: class_object.h:721
DESC_OBJ * make_desc_obj(SM_CLASS *class_)
Definition: load_object.c:87
#define OR_MVCC_FLAG_VALID_INSID
char * db_get_json_raw_body(const DB_VALUE *value)
Definition: db_macro.c:5082
static int fprint_special_set(TEXT_OUTPUT *tout, DB_SET *set)
Definition: load_object.c:1058
int db_timestampltz_to_string(char *buf, int bufsize, DB_TIMESTAMP *utime)
Definition: db_date.c:4146
#define MVCCID_NULL
SM_DEFAULT_VALUE default_value
Definition: class_object.h:451
#define OR_MVCC_FLAG_VALID_DELID
#define OR_MVCCID_SIZE
int fixed_size
Definition: class_object.h:739
struct sm_component * next
Definition: class_object.h:384
DB_DATETIMETZ * db_get_datetimetz(const DB_VALUE *value)
static void put_attributes(OR_BUF *buf, DESC_OBJ *obj)
Definition: load_object.c:314
#define OR_MVCC_FLAG_SHIFT_BITS
char * data
#define CAST_STRLEN
Definition: porting.h:470
bool classobj_class_has_indexes(SM_CLASS *class_)
#define MIGRATION_CHUNK
Definition: load_object.c:60
int er_errid(void)
#define OR_BOUND_BIT_BYTES(count)
#define OR_SHORT_SIZE
#define ER_TF_BUFFER_UNDERFLOW
Definition: error_code.h:387
#define PTR_ALIGN(addr, boundary)
Definition: memory_alloc.h:77
int set_size(DB_COLLECTION *set)
Definition: set_object.c:3036
void er_clearid(void)
static int itoa_print(TEXT_OUTPUT *tout, DB_BIGINT value, int base)
Definition: load_object.c:1297
static SM_ATTRIBUTE * find_current_attribute(SM_CLASS *class_, int id)
Definition: load_object.c:708
char * buffer
Definition: load_object.h:67
static char migration_buffer[MIGRATION_CHUNK]
Definition: load_object.c:61
#define OR_MVCC_MAX_HEADER_SIZE
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
int db_datetimetz_to_string(char *buf, int bufsize, DB_DATETIME *dt, const TZ_ID *tz_id)
Definition: db_date.c:4302
DB_TIMESTAMPTZ * db_get_timestamptz(const DB_VALUE *value)
int db_timestamp_to_string(char *buf, int bufsize, DB_TIMESTAMP *utime)
Definition: db_date.c:4054
int er_get_severity(void)
DB_MONETARY * db_get_monetary(const DB_VALUE *value)
int att_count
Definition: class_object.h:720
static void print_set(print_output &output_ctx, DB_SET *set)
Definition: load_object.c:1029
PR_TYPE * pr_type_from_id(DB_TYPE id)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
#define ER_BO_NOTIFY_AUTO_VOLEXT
Definition: error_code.h:186
Definition: db_set.h:35
static int fprint_special_strings(TEXT_OUTPUT *tout, DB_VALUE *value)
Definition: load_object.c:1360
const char * sm_ch_name(const MOBJ clobj)
static void itoa_strreverse(char *begin, char *end)
Definition: load_object.c:1274
#define OR_MVCC_FLAG_VALID_PREV_VERSION
#define assert(x)
#define OR_MVCC_FLAG_MASK
#define OR_ENABLE_BOUND_BIT(bitptr, element)
int desc_disk_to_obj(MOP classop, SM_CLASS *class_, RECDES *record, DESC_OBJ *obj)
Definition: load_object.c:930
#define CHECK_EXIT_ERROR(e)
Definition: load_object.h:38
static void get_desc_old(OR_BUF *buf, SM_CLASS *class_, int repid, DESC_OBJ *obj, int bound_bit_flag, int offset_size)
Definition: load_object.c:738
int or_mvcc_get_repid_and_flags(OR_BUF *buf, int *error)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void db_print_value(print_output &output_ctx, const db_value *value)
#define OID_ISTEMP(oidp)
Definition: oid.h:80
DB_VALUE original_value
Definition: class_object.h:393
DB_DATETIME datetime
Definition: dbtype_def.h:783
#define BITS_IN_HEX
Definition: load_object.c:1105
int or_put_int(OR_BUF *buf, int num)
#define BYTE_COUNT(bit_cnt)
Definition: load_object.c:1106
int or_put_bigint(OR_BUF *buf, DB_BIGINT num)
int or_overflow(OR_BUF *buf)
#define OR_MVCC_PREV_VERSION_LSA_SIZE
static void put_varinfo(OR_BUF *buf, DESC_OBJ *obj, int offset_size)
Definition: load_object.c:246
#define OR_MVCC_INSERT_HEADER_SIZE
static void get_desc_current(OR_BUF *buf, SM_CLASS *class_, DESC_OBJ *obj, int bound_bit_flag, int offset_size)
Definition: load_object.c:623
int or_put_offset_internal(OR_BUF *buf, int num, int offset_size)
#define NULL
Definition: freelistheap.h:34
unsigned short db_get_enum_short(const DB_VALUE *value)
char * ptr
Definition: load_object.h:69
struct sm_repr_attribute * next
Definition: class_object.h:648
#define DB_ATT_ALIGN(offset)
Definition: memory_alloc.h:93
struct pr_type * type
Definition: class_object.h:443
#define ER_LOG_MAX_ARCHIVES_HAS_BEEN_EXCEEDED
Definition: error_code.h:736
#define CHECK_PRINT_ERROR(print_fnc)
Definition: load_object.h:32
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
void or_init(OR_BUF *buf, char *data, int length)
int set_get_element(DB_COLLECTION *set, int index, DB_VALUE *value)
Definition: set_object.c:2575
#define BIG_VAR_OFFSET_SIZE
DB_VALUE * values
Definition: load_object.h:61
int desc_value_special_fprint(TEXT_OUTPUT *tout, DB_VALUE *value)
Definition: load_object.c:1575
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)
DB_BIGINT db_get_bigint(const DB_VALUE *value)
int db_time_to_string(char *buf, int bufsize, DB_TIME *time)
Definition: db_date.c:3994
#define ER_IO_WRITE
Definition: error_code.h:63
int db_datetime_to_string(char *buf, int bufsize, DB_DATETIME *datetime)
Definition: db_date.c:4225
int er_filter_errid(bool ignore_warning)
Definition: load_object.c:1759
int64_t DB_BIGINT
Definition: dbtype_def.h:751
int or_get_offset_internal(OR_BUF *buf, int *error, int offset_size)
static void error(const char *msg)
Definition: gencat.c:331
MOP classop
Definition: load_object.h:56
#define INTERNAL_BUFFER_SIZE
Definition: load_object.c:1265
static int rc
Definition: serial.c:50
SM_REPR_ATTRIBUTE * attributes
Definition: class_object.h:669
int pr_Inhibit_oid_promotion
char * numeric_db_value_print(const DB_VALUE *val, char *buf)
#define ER_DISK_ALMOST_OUT_OF_SPACE
Definition: error_code.h:75
#define ARG_FILE_LINE
Definition: error_manager.h:44
#define OR_BYTE_SIZE
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
#define WS_OID(mop)
Definition: work_space.h:293
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
DB_DATE * db_get_date(const DB_VALUE *value)
#define OR_VAR_TABLE_SIZE_INTERNAL(vars, offset_size)
SM_COMPONENT header
Definition: class_object.h:441
SM_ATTRIBUTE ** atts
Definition: load_object.h:60
#define INT_ALIGNMENT
Definition: memory_alloc.h:61
DB_TIMESTAMP * db_get_timestamp(const DB_VALUE *value)
int db_get_string_size(const DB_VALUE *value)
DB_C_SHORT db_get_short(const DB_VALUE *value)
int or_put_data(OR_BUF *buf, const char *data, int length)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
int db_make_null(DB_VALUE *value)
char * msgcat_message(int cat_id, int set_id, int msg_id)
#define DB_IS_NULL(value)
Definition: dbtype.h:63
#define OR_GET_OFFSET_SIZE(ptr)
void get_ignored_errors(std::vector< int > &vec)
Definition: load_object.c:1801
int db_get_error(const DB_VALUE *value)
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
void desc_free(DESC_OBJ *obj)
Definition: load_object.c:138
int db_get_string_length(const DB_VALUE *value)
#define MAX_DISPLAY_COLUMN
Definition: load_object.c:1100
void pr_data_writeval(struct or_buf *buf, DB_VALUE *value)
static int object_disk_size(DESC_OBJ *obj, int *offset_size_ptr)
Definition: load_object.c:169
#define OR_BOUND_BIT_FLAG
DB_TIME * db_get_time(const DB_VALUE *value)
int or_pad(OR_BUF *buf, int length)
DB_C_POINTER db_get_pointer(const DB_VALUE *value)
#define BYTE_COUNT_HEX(bit_cnt)
Definition: load_object.c:1107
int ws_set_ignore_error_list_for_mflush(int error_count, int *error_list)
Definition: work_space.c:4927
#define ER_DISK_TEMP_LAST_ALMOST_OUT_OF_SPACE
Definition: error_code.h:84
#define ER_LAST_ERROR
Definition: error_code.h:1646
#define ER_TF_INVALID_REPRESENTATION
Definition: error_code.h:391
static bool filter_ignore_errors[-ER_LAST_ERROR]
Definition: load_object.c:1637
const char ** p
Definition: dynamic_load.c:945
DB_CONST_C_CHAR db_get_string(const DB_VALUE *value)
int or_advance(OR_BUF *buf, int offset)
int text_print_flush(TEXT_OUTPUT *tout)
Definition: load_object.c:442
#define OR_GET_BOUND_BIT(bitptr, element)
int db_datetimeltz_to_string(char *buf, int bufsize, DB_DATETIME *dt)
Definition: db_date.c:4350
char * intl_get_money_esc_ISO_symbol(const DB_CURRENCY currency)
static void init_load_err_filter(void)
Definition: load_object.c:1645
int variable_count
Definition: class_object.h:738
int er_filter_fileset(FILE *ef)
Definition: load_object.c:1680
#define MSGCAT_CATALOG_UTILS