CUBRID Engine  latest
csql_result_format.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  * csql_result_format.c : string formatting function
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <float.h>
28 #include <time.h>
29 
30 #include "csql.h"
31 #include "cnv.h"
32 #include "memory_alloc.h"
33 #include "language_support.h"
34 #include "string_opfunc.h"
35 #include "unicode_support.h"
36 
37 #include "dbtype.h"
38 
39 #if defined (SUPPRESS_STRLEN_WARNING)
40 #define strlen(s1) ((int) strlen(s1))
41 #endif /* defined (SUPPRESS_STRLEN_WARNING) */
42 
43 #ifndef UX_CHAR
44 #define UX_CHAR wchar_t
45 #endif
46 
47 #define CMSB(x) ((x) & 0x80)
48  /* Checks if MSB of the character value is ON/OFF */
49 #define FORMERBYTE(x) ((UX_CHAR)(((unsigned)(x) & 0xff00) >> 8))
50 #define LATTERBYTE(x) ((UX_CHAR)((x) & 0xff))
51 
52 #define COMMAS_OFFSET(COND, N) (COND == TRUE ? (N / 3) : 0)
53 
54 #define TIME_STRING_MAX 20
55 
56 #define OID_LENGTH 15
57 
58 #define COMMA_CHAR ','
59 
60 #define SHORT_TO_INT(short_val) ((int)short_val)
61 #define OBJECT_SYMBOL_MAX 512
62 
63 #define DATE_ABREV_NAME_LENGTH 3
64 #define DATE_TEMP_BUFFER_LENGTH 50
65 
66 /*
67  * double, float, numeric type conversion profile
68  */
72 
74 {
75  char format; /* Use the following macros */
76  int fieldwidth; /* the width of the entire return string */
77  int precision; /* how many places after the decimal point */
78  bool leadingsign; /* whether or not to print '+' for positive numbers */
79  bool leadingzeros; /* whether or not to print leading zeros */
80  bool trailingzeros; /* whether or not to print trailing zeros */
81  bool commas; /* whether or not to print commas */
82 };
83 
84 /* double conversion 'format' macros */
85 #define DOUBLE_FORMAT_SCIENTIFIC 'e'
86 #define DOUBLE_FORMAT_DECIMAL 'f'
87 
89  DOUBLE_FORMAT_SCIENTIFIC, 0, DBL_DIG, false, false, true, false
90 };
91 
93  DOUBLE_FORMAT_SCIENTIFIC, 0, FLT_DIG, false, false, true, false
94 };
95 
97  DOUBLE_FORMAT_DECIMAL, -1, -1, false, false, true, true
98 };
99 
100 
101 /*
102  * integer, short type conversion profile
103  */
107 
109 {
110  char format; /* Use the following macros */
111  int fieldwidth; /* the width of the entire return string */
112  bool leadingsymbol; /* whether or not to print the leading symbol */
113  bool leadingzeros; /* whether or not to print leading zeros */
114  bool commas; /* whether or not to print commas */
115 };
116 
117 /* integer conversion 'format' macros */
118 #define INT_FORMAT_UNSIGNED_DECIMAL 'u'
119 #define INT_FORMAT_SIGNED_DECIMAL 'd'
120 #define INT_FORMAT_OCTAL 'o'
121 #define INT_FORMAT_HEXADECIMAL 'x'
122 #define INT_FORMAT_CHARACTER 'c'
123 
125  INT_FORMAT_SIGNED_DECIMAL, 0, false, false, false
126 };
127 
129  INT_FORMAT_SIGNED_DECIMAL, 0, false, false, false
130 };
131 
133  INT_FORMAT_SIGNED_DECIMAL, 0, false, false, false
134 };
135 
136 
137 /*
138  * monetary type conversion profile
139  */
140 
141 typedef struct
142 {
143  int fieldwidth; /* the width of the entire return string */
144  int decimalplaces; /* how many places after the decimal point */
145  bool leadingsign; /* whether or not to print + symbol */
146  bool currency_symbol; /* whether or not to print currency symbol */
147  bool leadingzeros; /* whether or not to print leading zeros */
148  bool trailingzeros; /* whether or not to print trailing zeros */
149  bool commas; /* whether or not to print commas */
151 
153  0, 2, false, true, false, true, true
154 };
155 
156 
157 /*
158  * DB_TIME type conversion profile
159  */
160 
161 typedef struct
162 {
163  const char *format; /* Use the following macros */
165 
166 /* DB_TIME conversion 'format' macros */
167 #define TIME_FORMAT_TWELVE_HOUR "%I:%M:%S %p"
168 #define TIME_FORMAT_TWELVE_HOUR_W_TIMEZONE "%I:%M:%S %p %Z"
169 #define TIME_FORMAT_TWENTY_FOUR_HOUR "%H:%M:%S"
170 #define TIME_FORMAT_TWENTY_FOUR_HOUR_W_TIMEZONE "%H:%M:%S %Z"
171 
174 };
175 
176 
177 /*
178  * DB_DATE type conversion profile
179  */
180 
181 typedef struct
182 {
183  int format; /* Use the following enumeration value */
185 
186 /* DB_DATE conversion 'format' enumeration */
187 enum
188 {
189  DATE_FORMAT_FULL_TEXT, /* standard US text format. "September 15, 2008" */
190  DATE_FORMAT_ABREV_TEXT, /* abbreviated US text format. "Sept. 15, 2008" */
191  DATE_FORMAT_FULL_TEXT_W_DAY, /* standard US format with day name. "Thursday, March 20, 2008" */
192  DATE_FORMAT_ABREV_TEXT_W_DAY, /* abbreviated US format with day name. "Thu, Mar 20, 2008" */
193  DATE_FORMAT_FULL_EURO_TEXT, /* standard European text format. "10. June 2008" */
194  DATE_FORMAT_ABREV_EURO_TEXT, /* abbreviated European format "15. Sep 1990" */
195  DATE_FORMAT_YYMMDD, /* YY/MM/DD format "08/06/10" */
196  DATE_FORMAT_MMDDYY, /* MM/DD/YY format "06/10/08" */
197  DATE_FORMAT_DDMMYY, /* DD/MM/YY format "10/06/08" */
198  DATE_FORMAT_MMDDYYYY /* MM/DD/YYYY format "06/10/2008" */
199 };
200 
203 };
204 
205 /* object conversion 'format' enumeration */
206 enum
207 {
210 };
211 
212 /*
213  * set type conversion profile
214  */
215 
216 typedef struct
217 {
218  char begin_notation; /* what character to use to denote begin of set '\0' for no character */
219  char end_notation; /* what character to use to denote end of set '\0' for no character */
220  int max_entries; /* max no. of entries to display, (-1 for all) */
222 
224  '{', '}', -1
225 };
226 
227 
228 /*
229  * string type conversion profile
230  */
231 
232 typedef struct
233 {
234  char string_delimiter; /* the character to use for a string delimiter ('\0' for none). */
236 
238  '\''
239 };
240 
241 /* TODO: locale ?*/
242 static const char *day_of_week_names[] = {
243  "Sunday",
244  "Monday",
245  "Tuesday",
246  "Wednesday",
247  "Thursday",
248  "Friday",
249  "Saturday"
250 };
251 
252 static const char *month_of_year_names[] = {
253  "January",
254  "February",
255  "March",
256  "April",
257  "May",
258  "June",
259  "July",
260  "August",
261  "September",
262  "October",
263  "November",
264  "December"
265 };
266 
267 static void add_commas (char *string);
268 static void strip_trailing_zeros (char *numeric_string);
269 static char *double_to_string (double double_value, int field_width, int precision, const bool leading_sign,
270  const char *leading_str, const char *trailing_str, bool leading_zeros,
271  bool trailing_zeros, bool commas, char conversion);
272 #if defined (ENABLE_UNUSED_FUNCTION)
273 static char *time_as_string (DB_TIME * time_value, const char *conversion);
274 #endif
275 static char *date_as_string (DB_DATE * date_value, int format);
276 static char *bigint_to_string (DB_BIGINT int_value, int field_width, bool leading_zeros, bool leading_symbol,
277  bool commas, char conversion);
278 static char *object_to_string (DB_OBJECT * object, int format);
279 static char *numeric_to_string (DB_VALUE * value, bool commas);
280 static char *bit_to_string (DB_VALUE * value, char string_delimiter, bool plain_string);
281 static char *set_to_string (DB_VALUE * value, char begin_notation, char end_notation, int max_entries,
282  bool plain_string, CSQL_OUTPUT_TYPE output_type, char column_encolser);
283 static char *duplicate_string (const char *string);
284 static char *string_to_string (const char *string_value, char string_delimiter, char string_introducer, int length,
285  int *result_length, bool plain_string, bool change_single_quote);
286 static int get_object_print_format (void);
287 
288 /*
289  * add_commas() - counts the digits in this string and adds the commas
290  * return: none
291  * string(in/out): string to add commas to
292  */
293 static void
294 add_commas (char *string)
295 {
296  int i, num_of_digits, last_digit, num_of_commas, string_len;
297 
298  if (string == NULL)
299  {
300  return;
301  }
302 
303  num_of_digits = last_digit = num_of_commas = 0;
304  string_len = strlen (string);
305 
306  /*
307  * First count the digits before the decimal place
308  */
309  for (i = 0; i < string_len; i++)
310  {
311  /* checking for CMSB is necessary for internationalization */
312  if (!(CMSB (string[i])) && isdigit (string[i]))
313  {
314  if (num_of_digits)
315  {
316  last_digit = i; /* keep track of last digit found */
317  }
318  num_of_digits++; /* increment total number of digits found */
319  }
320  else
321  {
322  if (num_of_digits) /* check to see if any found yet, if not keep checking */
323  {
324  break; /* otherwise stop */
325  }
326  }
327  }
328 
329  /*
330  * If no digits, exit
331  */
332  if (!num_of_digits)
333  return;
334 
335  /*
336  * Calculate the number of commas we are going to insert
337  */
338  num_of_commas = num_of_digits / 3;
339  if (!(num_of_digits % 3))
340  {
341  num_of_commas--;
342  }
343 
344  /*
345  * Add them if necessary
346  */
347  if (num_of_commas)
348  {
349  char *temp;
350  int l1, l2;
351 
352  l1 = string_len;
353  l2 = string_len + num_of_commas;
354 
355  temp = string;
356 
357  do
358  {
359  temp[l2--] = string[l1--];
360  }
361  while (string[l1] != '.');
362 
363  temp[l2--] = string[l1--];
364 
365  for (i = 0; num_of_commas; i++)
366  {
367  if (i && !(i % 3) && num_of_commas)
368  {
369  temp[l2--] = COMMA_CHAR;
370  --num_of_commas;
371  }
372  if (l1 && l2)
373  {
374  temp[l2--] = string[l1--];
375  }
376  }
377  }
378 }
379 
380 /*
381  * strip_trailing_zeros() - Strip the trailing zeros from the end of a numeric string
382  * return: none
383  * numeric_string(in/out): the numeric string to strip trailing zeros from
384  *
385  * Note: Strip the trailing zeros from the end of a numeric string.
386  * This function will only strip them from a string with
387  * a decimal place. The numeric string can either be in
388  * decimal notation or scientific notation. The string can
389  * also have trailing characters (e.g., 123.45 DM).
390  */
391 static void
392 strip_trailing_zeros (char *numeric_string)
393 {
394  char *prefix;
395  size_t remainder_len;
396 
397  if (numeric_string == NULL)
398  {
399  return;
400  }
401 
402  /*
403  * First check to see if this is even necessary
404  */
405  if ((prefix = strchr (numeric_string, '.')) == NULL)
406  {
407  return;
408  }
409 
410  /*
411  * Now count the number of trailing zeros
412  */
413 
414  if ((remainder_len = strcspn (prefix + 1, "0123456789")) == 0)
415  {
416  /* No trailing characters */
417  char *remainder = numeric_string + strlen (numeric_string);
418 
419  while (remainder-- > prefix)
420  {
421  if (*remainder == '0')
422  {
423  *remainder = '\0';
424  }
425  else
426  {
427  break;
428  }
429  }
430  }
431  else
432  {
433  int num_of_trailing_zeros = 0;
434  char *remainder = numeric_string + remainder_len;
435  char *end = numeric_string + strlen (numeric_string);
436 
437  while (remainder-- > prefix)
438  {
439  if (*remainder == '0')
440  {
441  num_of_trailing_zeros++;
442  }
443  else
444  {
445  break;
446  }
447  }
448 
449  while ((remainder++ + num_of_trailing_zeros) < end)
450  {
451  *remainder = *(remainder + num_of_trailing_zeros);
452  }
453  }
454 }
455 
456 /*
457  * double_to_string() - convert double value to string
458  * return: formatted string
459  * double_value(in): double value to convert
460  * field_width(in): the overall fieldwidth
461  * precision(in): the number of places after the decimal point
462  * leading_sign(in): true if leading sign '+' should be forced to show
463  * leading_str(in): the leading symbols to show, NULL if none desired
464  * trailing_str(in): the traling symbols to show, NULL if none desired
465  * leading_zeros(in): whether or not to show leading zeros
466  * trailing_zeros(in): whether or not to show trailing zeros
467  * commas(in): whether or not to show commas (every three digits)
468  * conversion(in): conversion format character, scientific or decimal
469  */
470 static char *
471 double_to_string (double double_value, int field_width, int precision, const bool leading_sign, const char *leading_str,
472  const char *trailing_str, bool leading_zeros, bool trailing_zeros, bool commas, char conversion)
473 {
474  char numeric_conversion_string[1024];
475  char precision_string[16];
476  char format_string[32];
477  int i, overall_fieldwidth;
478 
479  if (field_width < 0)
480  {
481  field_width = 0;
482  }
483 
484  overall_fieldwidth = field_width;
485 
486  if (precision < 0)
487  {
488  precision = 0;
489  }
490 
491  snprintf (precision_string, sizeof (precision_string) - 1, ".%u", (int) precision);
492 
493  i = 0;
494 
495  format_string[i++] = '%';
496 
497  if ((double_value < (double) 0) || (leading_sign == true))
498  {
499  format_string[i++] = '+';
500  if (overall_fieldwidth)
501  {
502  overall_fieldwidth++;
503  }
504  }
505 
506  if (leading_zeros == true)
507  {
508  format_string[i++] = '0';
509  }
510 
511  if ((trailing_zeros == true) && (precision))
512  {
513  format_string[i++] = '#';
514  }
515 
516  format_string[i++] = '*';
517  format_string[i] = 0;
518 
519 
520  strcat ((char *) format_string, (char *) precision_string);
521  i = strlen (format_string);
522  format_string[i++] = conversion;
523  format_string[i] = 0;
524  if ((overall_fieldwidth > 0) && (conversion == DOUBLE_FORMAT_SCIENTIFIC))
525  {
526  overall_fieldwidth += 4;
527  }
528 
529  if (!sprintf ((char *) numeric_conversion_string, (char *) format_string, (int) field_width, double_value))
530  {
531  return (NULL);
532  }
533  else
534  {
535  char *return_string;
536  int actual_fieldwidth = strlen (numeric_conversion_string);
537  int leading_size = (leading_str != NULL) ? strlen (leading_str) : 0;
538  int trailing_size = (trailing_str != NULL) ? strlen (trailing_str) : 0;
539 
540  if ((size_t) (leading_size + actual_fieldwidth + 1) > sizeof (numeric_conversion_string))
541  {
542  return NULL;
543  }
544  if (leading_size > 0)
545  {
546  memmove (numeric_conversion_string + leading_size, numeric_conversion_string, actual_fieldwidth);
547  memcpy (numeric_conversion_string, leading_str, leading_size);
548 
549  numeric_conversion_string[actual_fieldwidth + leading_size] = '\0';
550  actual_fieldwidth += leading_size;
551  }
552 #if defined(HPUX)
553  /* workaround for HP's broken printf */
554  if (strstr (numeric_conversion_string, "+.+") || strstr (numeric_conversion_string, "++"))
555  sprintf (numeric_conversion_string, "Inf");
556  if (strstr (numeric_conversion_string, "-.-") || strstr (numeric_conversion_string, "--"))
557  sprintf (numeric_conversion_string, "-Inf");
558 #endif
559 
560  if (trailing_zeros == false)
561  {
562  strip_trailing_zeros (numeric_conversion_string);
563  actual_fieldwidth = strlen (numeric_conversion_string);
564  }
565 
566  if ((size_t) (trailing_size + actual_fieldwidth + 1) > sizeof (numeric_conversion_string))
567  {
568  return NULL;
569  }
570 
571  if (trailing_size > 0)
572  {
573  memcpy (numeric_conversion_string + actual_fieldwidth, trailing_str, trailing_size);
574  numeric_conversion_string[actual_fieldwidth + trailing_size] = '\0';
575  actual_fieldwidth += trailing_size;
576  }
577 
578  if (field_width == 0)
579  {
580  if ((return_string =
581  (char *) malloc (actual_fieldwidth + COMMAS_OFFSET (commas, actual_fieldwidth) + 1)) == NULL)
582  {
583  return (NULL);
584  }
585  (void) strcpy (return_string, numeric_conversion_string);
586  }
587  else
588  {
589  if ((return_string =
590  (char *) malloc (overall_fieldwidth + COMMAS_OFFSET (commas, actual_fieldwidth) + 1)) == NULL)
591  {
592  return (NULL);
593  }
594  if (actual_fieldwidth <= overall_fieldwidth)
595  {
596  return_string = strcpy (return_string, numeric_conversion_string);
597  }
598  else
599  {
600  return_string[overall_fieldwidth] = numeric_conversion_string[actual_fieldwidth];
601  while (overall_fieldwidth)
602  {
603  return_string[--overall_fieldwidth] = numeric_conversion_string[--actual_fieldwidth];
604  }
605  }
606  }
607  if (commas == true)
608  {
609  add_commas (return_string);
610  }
611  return (return_string);
612  }
613 }
614 
615 #if defined (ENABLE_UNUSED_FUNCTION)
616 /*
617  * time_as_string() - convert time value to string
618  * return: formatted string
619  * time_value(in): time value to convert
620  * conversion(in): conversion format string
621  */
622 static char *
623 time_as_string (DB_TIME * time_value, const char *conversion)
624 {
625  char temp_string[TIME_STRING_MAX];
626 
627  if (time_value == NULL)
628  {
629  return NULL;
630  }
631 
632  if (!db_strftime (temp_string, (int) TIME_STRING_MAX, conversion, (DB_DATE *) NULL, time_value))
633  {
634  return (NULL);
635  }
636  return (duplicate_string (temp_string));
637 
638 }
639 #endif
640 
641 /*
642  * date_as_string() - convert date value to string
643  * return: formatted string
644  * date_value(in): date value to convert
645  * format(in): conversion format type
646  */
647 static char *
648 date_as_string (DB_DATE * date_value, int format)
649 {
650  char temp_buffer[DATE_TEMP_BUFFER_LENGTH];
651  int month, day, year;
652 
653  if (date_value == NULL)
654  {
655  return (NULL);
656  }
657 
658  db_date_decode (date_value, &month, &day, &year);
659  switch (format)
660  {
662  {
663  (void) sprintf (temp_buffer, "%02d/%02d/%04d", month, day, year);
664  }
665  break;
667  (void) sprintf (temp_buffer, "%s %d, %04d", month_of_year_names[month - 1], day, year);
668  break;
670  {
671  char month_name[DATE_ABREV_NAME_LENGTH + 1];
672  (void) strncpy (month_name, month_of_year_names[month - 1], DATE_ABREV_NAME_LENGTH);
673  month_name[DATE_ABREV_NAME_LENGTH] = '\0';
674  (void) sprintf (temp_buffer, "%s %d, %04d", month_name, day, year);
675  }
676  break;
678  {
679  int dayofweek = db_date_weekday (date_value);
680  if (dayofweek < 0 || dayofweek > 6)
681  {
682  return (NULL);
683  }
684  (void) sprintf (temp_buffer, "%s, %s %d, %04d", day_of_week_names[dayofweek], month_of_year_names[month - 1],
685  day, year);
686  }
687  break;
689  {
690  char day_name[DATE_ABREV_NAME_LENGTH + 1];
691  char month_name[DATE_ABREV_NAME_LENGTH + 1];
692 
693  int dayofweek = db_date_weekday (date_value);
694  if (dayofweek < 0 || dayofweek > 6)
695  {
696  return (NULL);
697  }
698  (void) strncpy (day_name, day_of_week_names[dayofweek], DATE_ABREV_NAME_LENGTH);
699  day_name[DATE_ABREV_NAME_LENGTH] = '\0';
700  (void) strncpy (month_name, month_of_year_names[month - 1], DATE_ABREV_NAME_LENGTH);
701  month_name[DATE_ABREV_NAME_LENGTH] = '\0';
702  (void) sprintf (temp_buffer, "%s, %s %d, %04d", day_name, month_name, day, year);
703  }
704  break;
706  (void) sprintf (temp_buffer, "%d. %s %04d", day, month_of_year_names[month - 1], year);
707  break;
709  {
710  char month_name[DATE_ABREV_NAME_LENGTH + 1];
711  (void) strncpy (month_name, month_of_year_names[month - 1], DATE_ABREV_NAME_LENGTH);
712  month_name[DATE_ABREV_NAME_LENGTH] = '\0';
713  (void) sprintf (temp_buffer, "%d. %s %04d", day, month_name, year);
714  }
715  break;
716  case DATE_FORMAT_YYMMDD:
717  {
718  (void) sprintf (temp_buffer, "%02d/%02d/%02d", year % 100, month, day);
719  }
720  break;
721  case DATE_FORMAT_MMDDYY:
722  {
723  (void) sprintf (temp_buffer, "%02d/%02d/%02d", month, day, year % 100);
724  }
725  break;
726  case DATE_FORMAT_DDMMYY:
727  {
728  (void) sprintf (temp_buffer, "%02d/%02d/%02d", day, month, year % 100);
729  }
730  break;
731  default:
732  /* invalid format type */
733  temp_buffer[0] = '\0';
734  break;
735  }
736  return (duplicate_string (temp_buffer));
737 }
738 
739 /*
740  * int_to_string() - convert integer value to string
741  * return: formatted string
742  * int_value(in): integer value to convert
743  * field_width(in): the desired field width
744  * leading_zeros(in): whether or not to show leading zeros
745  * leading_symbol(in): whether or not to show the leading symbol
746  * commas(in): whether or not to display commas
747  * conversion(in): conversion format charactern
748  */
749 static char *
750 bigint_to_string (DB_BIGINT int_value, int field_width, bool leading_zeros, bool leading_symbol, bool commas,
751  char conversion)
752 {
753  char numeric_conversion_string[1024];
754  char format_string[10];
755  char long_decimal = 'l';
756  int i = 0;
757  int overall_fieldwidth;
758 
759  if (field_width < 0)
760  {
761  field_width = 0;
762  }
763 
764  overall_fieldwidth = field_width;
765  format_string[i++] = '%';
766 
767  if (leading_zeros == true)
768  {
769  format_string[i++] = '0';
770  }
771 
772  if (leading_symbol == true)
773  {
774  format_string[i++] = '#';
775  if (overall_fieldwidth)
776  {
777  switch (conversion)
778  {
780  {
781  if (overall_fieldwidth && (int_value < 0))
782  {
783  overall_fieldwidth++;
784  }
785  break;
786  }
788  {
789  if (overall_fieldwidth)
790  {
791  overall_fieldwidth += 2;
792  }
793  break;
794  }
795  default:
796  break;
797  }
798  }
799  }
800 
801  if (int_value < 0)
802  {
803  format_string[i++] = '+';
804  }
805 
806  format_string[i++] = '*';
807 
808  format_string[i++] = long_decimal;
809  format_string[i++] = long_decimal;
810  format_string[i++] = conversion;
811  format_string[i++] = (char) 0;
812 
813  if (!sprintf (numeric_conversion_string, (char *) format_string, (int) field_width, int_value))
814  {
815  return (NULL);
816  }
817  else
818  {
819  char *return_string;
820  int actual_fieldwidth = strlen (numeric_conversion_string);
821 
822  if (field_width == 0)
823  {
824  if ((return_string =
825  (char *) malloc (actual_fieldwidth + COMMAS_OFFSET (commas, actual_fieldwidth) + 1)) == NULL)
826  {
827  return (NULL);
828  }
829  (void) strcpy (return_string, (const char *) &numeric_conversion_string[0]);
830  }
831  else
832  {
833  if ((return_string =
834  (char *) malloc (overall_fieldwidth + COMMAS_OFFSET (commas, actual_fieldwidth) + 1)) == NULL)
835  {
836  return (NULL);
837  }
838  if (actual_fieldwidth <= overall_fieldwidth)
839  {
840  return_string = strcpy (return_string, numeric_conversion_string);
841  }
842  else
843  {
844  return_string[overall_fieldwidth] = numeric_conversion_string[actual_fieldwidth];
845  while (overall_fieldwidth)
846  {
847  return_string[--overall_fieldwidth] = numeric_conversion_string[--actual_fieldwidth];
848  }
849  }
850  }
851  if (commas == true)
852  {
853  add_commas (return_string);
854  }
855  return (return_string);
856  }
857 }
858 
859 /*
860  * object_to_string() - convert object to string
861  * return: formatted string
862  * object(in): object value to convert
863  * format(in): conversion format type
864  */
865 static char *
867 {
868  if (object == NULL)
869  return NULL;
870 
871  if (format == OBJECT_FORMAT_OID)
872  {
873  char temp_string[OBJECT_SYMBOL_MAX];
874 
875  if (!db_print_mop (object, temp_string, OBJECT_SYMBOL_MAX))
876  {
877  return (NULL);
878  }
879  return (duplicate_string (temp_string));
880  }
881  else
882  {
883  char *name;
884 
885  name = (char *) db_get_class_name (object);
886  if (name == NULL)
887  {
888  return (NULL);
889  }
890  else
891  {
892  return (duplicate_string (name));
893  }
894  }
895 }
896 
897 /*
898  * numeric_to_string() - convert numeric value to string
899  * return: formatted string
900  * value(in): numeric value to convert
901  * commas(in): whether or not to display commas
902  */
903 static char *
905 {
906  char str_buf[NUMERIC_MAX_STRING_SIZE];
907  char *return_string;
908  int prec;
909  int comma_length;
910  int max_length;
911 
912  /*
913  * Allocate string length based on precision plus the commas plus a
914  * character for each of the sign, decimal point, and NULL terminator.
915  */
916  prec = DB_VALUE_PRECISION (value);
917  comma_length = COMMAS_OFFSET (commas, prec);
918  max_length = prec + comma_length + 3;
919  return_string = (char *) malloc (max_length);
920  if (return_string == NULL)
921  {
922  return (NULL);
923  }
924 
925  numeric_db_value_print (value, str_buf);
926  if (strlen (str_buf) > max_length - 1)
927  {
928  free_and_init (return_string);
929  return (duplicate_string ("NUM OVERFLOW"));
930  }
931  strcpy (return_string, str_buf);
932 
933  return return_string;
934 }
935 
936 /*
937  * bit_to_string() - convert bit value to string
938  * return: formatted string
939  * value(in): bit value to convert
940  */
941 static char *
942 bit_to_string (DB_VALUE * value, char string_delimiter, bool plain_string)
943 {
944  char *temp_string;
945  char *return_string;
946  int max_length;
947 
948  /*
949  * Allocate string length based on precision plus the the leading
950  * introducer plus quotes, and NULL terminator. Precision / 4 (rounded up)
951  * represents the number of bytes needed to represent the bit string in
952  * hexadecimal.
953  */
954  max_length = ((db_get_string_length (value) + 3) / 4) + 4;
955  temp_string = (char *) malloc (max_length);
956  if (temp_string == NULL)
957  {
958  return (NULL);
959  }
960 
961  if (db_bit_string (value, "%X", temp_string, max_length) != CSQL_SUCCESS)
962  {
963  free_and_init (temp_string);
964  return (NULL); /* Should never get here */
965  }
966 
967  return_string =
968  string_to_string (temp_string, string_delimiter, 'X', strlen (temp_string), NULL, plain_string, false);
969  free_and_init (temp_string);
970 
971  return (return_string);
972 }
973 
974 /*
975  * set_to_string() - convert set value to string
976  * return: formatted string
977  * value(in): set value to convert
978  * begin_notation(in): character to use to denote begin of set
979  * end_notation(in): character to use to denote end of set
980  * max_entries(in): maximum number of entries to convert. -1 for all
981  * plain_string(in): refine string for plain output
982  * output_type(in): query output or loaddb output
983  * column_enclosure(in): column enclosure for query output
984  */
985 static char *
986 set_to_string (DB_VALUE * value, char begin_notation, char end_notation, int max_entries, bool plain_string,
987  CSQL_OUTPUT_TYPE output_type, char column_enclosure)
988 {
989  int cardinality, total_string_length, i;
990  char **string_array;
991  char *return_string = NULL;
992  DB_VALUE element;
993  int set_error;
994  DB_SET *set;
995 
996  set = db_get_set (value);
997  if (set == NULL)
998  {
999  return (NULL);
1000  }
1001 
1002  /* pre-fetch any objects in the set, this will prevent multiple server calls during set rendering */
1003  db_fetch_set (set, DB_FETCH_READ, 0);
1004 
1005  /* formerly we filtered out deleted elements here, now just use db_set_size to get the current size, including NULL &
1006  * deleted elements */
1007  cardinality = db_set_size (set);
1008 
1009  if (cardinality < 0)
1010  {
1011  return (NULL);
1012  }
1013  else if (cardinality == 0)
1014  {
1015  char temp_buffer[4];
1016 
1017  i = 0;
1018  if (begin_notation != '\0')
1019  {
1020  temp_buffer[i++] = begin_notation;
1021  }
1022  if (end_notation != '\0')
1023  {
1024  temp_buffer[i++] = end_notation;
1025  }
1026  temp_buffer[i] = '\0';
1027  return (duplicate_string ((const char *) &(temp_buffer[0])));
1028  }
1029 
1030  if (max_entries != -1 && max_entries < cardinality)
1031  {
1032  cardinality = max_entries;
1033  }
1034  string_array = (char **) malloc ((cardinality + 2) * sizeof (char *));
1035  if (string_array == NULL)
1036  {
1037  return (NULL);
1038  }
1039 
1040  memset (string_array, 0, (cardinality + 2) * sizeof (char *));
1041 
1042  total_string_length = cardinality * 2;
1043  for (i = 0; i < cardinality; i++)
1044  {
1045  set_error = db_set_get (set, i, &element);
1046  if (set_error != NO_ERROR)
1047  {
1048  goto finalize;
1049  }
1050  string_array[i] = csql_db_value_as_string (&element, NULL, plain_string, output_type, column_enclosure);
1051  db_value_clear (&element);
1052  if (string_array[i] == NULL)
1053  {
1054  string_array[i] = duplicate_string ("NULL");
1055  if (string_array[i] == NULL)
1056  {
1057  goto finalize;
1058  }
1059  }
1060  total_string_length += strlen (string_array[i]);
1061  } /* for (i = 0; i < cardinality... */
1062 
1063  return_string = (char *) malloc (total_string_length + 4);
1064  if (return_string == NULL)
1065  {
1066  goto finalize;
1067  }
1068 
1069  if (begin_notation != '\0')
1070  {
1071  (void) sprintf (return_string, "%c%s", begin_notation, string_array[0]);
1072  }
1073  else
1074  {
1075  (void) strcpy (return_string, string_array[0]);
1076  }
1077 
1078  for (i = 1; i < cardinality; i++)
1079  {
1080  (void) strcat (return_string, ", ");
1081  (void) strcat (return_string, string_array[i]);
1082  }
1083  if (end_notation != '\0')
1084  {
1085  int len = strlen (return_string);
1086 
1087  return_string[len++] = end_notation;
1088  return_string[len] = '\0';
1089  }
1090 
1091 finalize:
1092  for (i = 0; i < cardinality; i++)
1093  {
1094  if (string_array[i] == NULL)
1095  {
1096  break;
1097  }
1098  free_and_init (string_array[i]);
1099  }
1100  free_and_init (string_array);
1101 
1102  return return_string;
1103 }
1104 
1105 /*
1106  * duplicate_string() - Return an allocated copy of the string
1107  * return: new string
1108  * string(in): string value
1109  */
1110 static char *
1111 duplicate_string (const char *string)
1112 {
1113 
1114  char *new_string;
1115 
1116  if (string == NULL)
1117  {
1118  return NULL;
1119  }
1120 
1121  new_string = (char *) malloc (strlen (string) + 1);
1122  if (new_string)
1123  {
1124  strcpy (new_string, string);
1125  }
1126 
1127  return (new_string);
1128 
1129 }
1130 
1131 /*
1132  * csql_string_to_plain_string() - Refine the string and return it
1133  * return: refined plain string
1134  * string_value(in): source string to duplicate
1135  * length(in): length of the source string
1136  * result_length(out): : length of output string
1137  *
1138  * note: replace newline and tab with escaped string
1139  */
1140 char *
1141 csql_string_to_plain_string (const char *string_value, int length, int *result_length)
1142 {
1143  char *return_string;
1144  char *ptr;
1145  char *con_buf_ptr = NULL;
1146  int con_buf_size = 0;
1147  int num_found = 0;
1148  int i;
1149 
1150  if (string_value == NULL)
1151  {
1152  return NULL;
1153  }
1154 
1155  ptr = (char *) string_value;
1156  while (*ptr != '\0')
1157  {
1158  if (*ptr == '\t' || *ptr == '\n' || *ptr == '\\')
1159  {
1160  num_found++;
1161  }
1162  ptr++;
1163  }
1164 
1165  if (num_found == 0)
1166  {
1167  if (result_length != NULL)
1168  {
1169  *result_length = length;
1170  }
1171  return duplicate_string (string_value);
1172  }
1173 
1174  return_string = (char *) malloc (length + num_found + 1);
1175  if (return_string == NULL)
1176  {
1177  return NULL;
1178  }
1179 
1180  ptr = return_string;
1181  for (i = 0; i < length; i++)
1182  {
1183  if (string_value[i] == '\t')
1184  {
1185  ptr += sprintf (ptr, "\\t");
1186  }
1187  else if (string_value[i] == '\n')
1188  {
1189  ptr += sprintf (ptr, "\\n");
1190  }
1191  else if (string_value[i] == '\\')
1192  {
1193  ptr += sprintf (ptr, "\\\\");
1194  }
1195  else
1196  {
1197  *(ptr++) = string_value[i];
1198  }
1199  }
1200  *ptr = '\0';
1201 
1203  && (*csql_text_utf8_to_console) (return_string, strlen (return_string), &con_buf_ptr, &con_buf_size) == NO_ERROR)
1204  {
1205  if (con_buf_ptr != NULL)
1206  {
1207  free (return_string);
1208  return_string = con_buf_ptr;
1209  ptr = con_buf_ptr + con_buf_size;
1210  }
1211  }
1212 
1213  if (result_length)
1214  {
1215  *result_length = CAST_STRLEN (ptr - return_string);
1216  }
1217 
1218  return return_string;
1219 }
1220 
1221 /*
1222  * string_to_string() - Copy the string and return it
1223  * return: formatted string
1224  * string_value(in): source string to duplicate
1225  * string_delimiter(in): delimiter to surround string with (0 if none)
1226  * string_introducer(in): introducer for the string (0 if none)
1227  * length(in): length of the source string
1228  * result_length(out): : length of output string
1229  * plain_string(in): refine string for plain output
1230  * change_single_quote(in): refine string for query output
1231  */
1232 static char *
1233 string_to_string (const char *string_value, char string_delimiter, char string_introducer, int length,
1234  int *result_length, bool plain_string, bool change_single_quote)
1235 {
1236  char *return_string;
1237  char *ptr;
1238  char *con_buf_ptr = NULL;
1239  int con_buf_size = 0;
1240  int num_found = 0, i = 0;
1241 
1242  if (plain_string == true)
1243  {
1244  return csql_string_to_plain_string (string_value, length, result_length);
1245  }
1246 
1247  if (string_delimiter == '\0')
1248  {
1249  return (duplicate_string (string_value));
1250  }
1251 
1252  if (string_value == NULL)
1253  {
1254  return NULL;
1255  }
1256 
1257  if (change_single_quote == true)
1258  {
1259  ptr = (char *) string_value;
1260 
1261  while (*ptr != '\0')
1262  {
1263  if (*ptr == '\'')
1264  {
1265  num_found++;
1266  }
1267  ptr++;
1268  }
1269  }
1270 
1271  if ((return_string = (char *) malloc (length + 4 + num_found)) == NULL)
1272  {
1273  return (NULL);
1274  }
1275 
1276  ptr = return_string;
1277  if (string_introducer)
1278  {
1279  *ptr++ = string_introducer;
1280  }
1281  *ptr++ = string_delimiter;
1282 
1283  if (change_single_quote == true)
1284  {
1285  for (i = 0; i < length; i++)
1286  {
1287  if (string_value[i] == '\'')
1288  {
1289  *(ptr++) = string_value[i];
1290  *(ptr++) = '\'';
1291  }
1292  else
1293  {
1294  *(ptr++) = string_value[i];
1295  }
1296  }
1297  *(ptr++) = string_delimiter;
1298  *ptr = '\0';
1299  }
1300  else
1301  {
1302  memcpy (ptr, string_value, length);
1303  ptr[length] = string_delimiter;
1304  ptr = ptr + length + 1;
1305  *ptr = '\0';
1306  }
1307 
1309  && (*csql_text_utf8_to_console) (return_string, strlen (return_string), &con_buf_ptr, &con_buf_size) == NO_ERROR)
1310  {
1311  if (con_buf_ptr != NULL)
1312  {
1313  free (return_string);
1314  return_string = con_buf_ptr;
1315  ptr = con_buf_ptr + con_buf_size;
1316  }
1317  }
1318 
1319  if (result_length)
1320  {
1321  *result_length = CAST_STRLEN (ptr - return_string);
1322  }
1323  return return_string;
1324 }
1325 
1326 /*
1327  * csql_db_value_as_string() - convert DB_VALUE to string
1328  * return: formatted string
1329  * value(in): value to convert
1330  * length(out): length of output string
1331  * plain_output(in): refine string for plain output
1332  * output_type(in): query output or loaddb output
1333  * column_enclosure(in): column enclosure for query output
1334  */
1335 char *
1336 csql_db_value_as_string (DB_VALUE * value, int *length, bool plain_string, CSQL_OUTPUT_TYPE output_type,
1337  char column_enclosure)
1338 {
1339  char *result = NULL;
1340  char *json_body = NULL;
1341  int len = 0;
1342  char string_delimiter =
1343  (output_type != CSQL_UNKNOWN_OUTPUT) ? column_enclosure : default_string_profile.string_delimiter;
1344  bool change_single_quote = (output_type != CSQL_UNKNOWN_OUTPUT && column_enclosure == '\'');
1345 
1346  if (value == NULL)
1347  {
1348  return (NULL);
1349  }
1350 
1351  switch (DB_VALUE_TYPE (value))
1352  {
1353  case DB_TYPE_BIGINT:
1354  result =
1355  bigint_to_string (db_get_bigint (value), default_bigint_profile.fieldwidth, default_bigint_profile.leadingzeros,
1356  default_bigint_profile.leadingsymbol, default_bigint_profile.commas,
1357  default_bigint_profile.format);
1358  if (result)
1359  {
1360  len = strlen (result);
1361  }
1362  break;
1363  case DB_TYPE_INTEGER:
1364  result =
1365  bigint_to_string (db_get_int (value), default_int_profile.fieldwidth, default_int_profile.leadingzeros,
1366  default_int_profile.leadingsymbol, default_int_profile.commas, default_int_profile.format);
1367  if (result)
1368  {
1369  len = strlen (result);
1370  }
1371  break;
1372  case DB_TYPE_SHORT:
1373  result =
1374  bigint_to_string (SHORT_TO_INT (db_get_short (value)), default_short_profile.fieldwidth,
1375  default_short_profile.leadingzeros, default_short_profile.leadingsymbol,
1376  default_short_profile.commas, default_short_profile.format);
1377  if (result)
1378  {
1379  len = strlen (result);
1380  }
1381  break;
1382  case DB_TYPE_FLOAT:
1383  result =
1384  double_to_string ((double) db_get_float (value), default_float_profile.fieldwidth,
1385  default_float_profile.precision, default_float_profile.leadingsign, nullptr, nullptr,
1386  default_float_profile.leadingzeros, default_float_profile.trailingzeros,
1387  default_float_profile.commas, default_float_profile.format);
1388  if (result)
1389  {
1390  len = strlen (result);
1391  }
1392  break;
1393  case DB_TYPE_DOUBLE:
1394  result =
1395  double_to_string (db_get_double (value), default_double_profile.fieldwidth, default_double_profile.precision,
1396  default_double_profile.leadingsign, nullptr, nullptr, default_double_profile.leadingzeros,
1397  default_double_profile.trailingzeros, default_double_profile.commas,
1398  default_double_profile.format);
1399  if (result)
1400  {
1401  len = strlen (result);
1402  }
1403  break;
1404  case DB_TYPE_NUMERIC:
1405  result = numeric_to_string (value, default_numeric_profile.commas);
1406  if (result)
1407  {
1408  len = strlen (result);
1409  }
1410  break;
1411  case DB_TYPE_VARCHAR:
1412  case DB_TYPE_CHAR:
1413  {
1414  int dummy, bytes_size, decomp_size;
1415  bool need_decomp = false;
1416  const char *str;
1417  char *decomposed = NULL;
1418 
1419  str = db_get_char (value, &dummy);
1420  bytes_size = db_get_string_size (value);
1421  if (bytes_size > 0 && db_get_string_codeset (value) == INTL_CODESET_UTF8)
1422  {
1423  need_decomp =
1424  unicode_string_need_decompose (str, bytes_size, &decomp_size, lang_get_generic_unicode_norm ());
1425  }
1426 
1427  if (need_decomp)
1428  {
1429  decomposed = (char *) malloc (decomp_size * sizeof (char));
1430  if (decomposed != NULL)
1431  {
1432  unicode_decompose_string (str, bytes_size, decomposed, &decomp_size, lang_get_generic_unicode_norm ());
1433 
1434  str = decomposed;
1435  bytes_size = decomp_size;
1436  }
1437  else
1438  {
1439  return NULL;
1440  }
1441  }
1442 
1443  result = string_to_string (str, string_delimiter, '\0', bytes_size, &len, plain_string, change_single_quote);
1444 
1445  if (decomposed != NULL)
1446  {
1447  free_and_init (decomposed);
1448  }
1449 
1450  }
1451  break;
1452  case DB_TYPE_VARNCHAR:
1453  case DB_TYPE_NCHAR:
1454  {
1455  int dummy, bytes_size, decomp_size;
1456  bool need_decomp = false;
1457  const char *str;
1458  char *decomposed = NULL;
1459 
1460  str = db_get_char (value, &dummy);
1461  bytes_size = db_get_string_size (value);
1462  if (bytes_size > 0 && db_get_string_codeset (value) == INTL_CODESET_UTF8)
1463  {
1464  need_decomp =
1465  unicode_string_need_decompose (str, bytes_size, &decomp_size, lang_get_generic_unicode_norm ());
1466  }
1467 
1468  if (need_decomp)
1469  {
1470  decomposed = (char *) malloc (decomp_size * sizeof (char));
1471  if (decomposed != NULL)
1472  {
1473  unicode_decompose_string (str, bytes_size, decomposed, &decomp_size, lang_get_generic_unicode_norm ());
1474 
1475  str = decomposed;
1476  bytes_size = decomp_size;
1477  }
1478  else
1479  {
1480  return NULL;
1481  }
1482  }
1483 
1484  result = string_to_string (str, string_delimiter, 'N', bytes_size, &len, plain_string, change_single_quote);
1485 
1486  if (decomposed != NULL)
1487  {
1488  free_and_init (decomposed);
1489  }
1490  }
1491  break;
1492  case DB_TYPE_VARBIT:
1493  case DB_TYPE_BIT:
1494  result = bit_to_string (value, string_delimiter, plain_string);
1495  if (result)
1496  {
1497  len = strlen (result);
1498  }
1499  break;
1500  case DB_TYPE_OBJECT:
1502  if (result == NULL)
1503  {
1504  result = duplicate_string ("NULL");
1505  }
1506  if (result)
1507  {
1508  len = strlen (result);
1509  }
1510  break;
1511  case DB_TYPE_VOBJ:
1513  if (result == NULL)
1514  {
1515  result = duplicate_string ("NULL");
1516  }
1517  if (result)
1518  {
1519  len = strlen (result);
1520  }
1521  break;
1522  case DB_TYPE_JSON:
1523  json_body = db_get_json_raw_body (value);
1524  result = duplicate_string (json_body);
1525  db_private_free (NULL, json_body);
1526  if (result)
1527  {
1528  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1529  {
1530  char *new_result;
1531 
1532  new_result =
1533  string_to_string (result, column_enclosure, '\0', strlen (result), &len, false, change_single_quote);
1534 
1535  if (new_result)
1536  {
1537  free (result);
1538  result = new_result;
1539  }
1540  }
1541  len = strlen (result);
1542  }
1543  break;
1544  case DB_TYPE_SET:
1545  case DB_TYPE_MULTISET:
1546  case DB_TYPE_SEQUENCE:
1547  result =
1548  set_to_string (value, default_set_profile.begin_notation, default_set_profile.end_notation,
1549  default_set_profile.max_entries, plain_string, output_type, column_enclosure);
1550  if (result)
1551  {
1552  len = strlen (result);
1553  }
1554  break;
1555  case DB_TYPE_TIME:
1556  {
1557  char buf[TIME_BUF_SIZE];
1558  if (db_time_to_string (buf, sizeof (buf), db_get_time (value)))
1559  {
1560  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1561  {
1562  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1563  }
1564  else
1565  {
1566  result = duplicate_string (buf);
1567  }
1568  }
1569  if (result)
1570  {
1571  len = strlen (result);
1572  }
1573  break;
1574  }
1575  case DB_TYPE_MONETARY:
1576  {
1577  char *leading_str = NULL;
1578  char *trailing_str = NULL;
1579  DB_MONETARY *monetary_val = db_get_monetary (value);
1580  DB_CURRENCY currency = monetary_val->type;
1581 
1582  if (default_monetary_profile.currency_symbol)
1583  {
1584  if (intl_get_currency_symbol_position (currency) == 1)
1585  {
1586  trailing_str = intl_get_money_symbol_console (currency);
1587  }
1588  else
1589  {
1590  leading_str = intl_get_money_symbol_console (currency);
1591  }
1592  }
1593 
1594  if (db_get_monetary (value) == NULL)
1595  {
1596  result = NULL;
1597  }
1598  else
1599  {
1600  result = double_to_string (monetary_val->amount, default_monetary_profile.fieldwidth,
1601  default_monetary_profile.decimalplaces, default_monetary_profile.leadingsign,
1602  leading_str, trailing_str, default_monetary_profile.leadingzeros,
1603  default_monetary_profile.trailingzeros, default_monetary_profile.commas,
1605  }
1606 
1607  if (result)
1608  {
1609  len = strlen (result);
1610  }
1611  }
1612  break;
1613  case DB_TYPE_DATE:
1614  /* default format for all locales */
1615  result = date_as_string (db_get_date (value), default_date_profile.format);
1616  if (result)
1617  {
1618  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1619  {
1620  char *new_result;
1621 
1622  new_result = string_to_string (result, column_enclosure, '\0', strlen (result), &len, false, false);
1623 
1624  if (new_result)
1625  {
1626  free (result);
1627  result = new_result;
1628  }
1629  }
1630  len = strlen (result);
1631  }
1632  break;
1633  case DB_TYPE_TIMESTAMP:
1634  {
1635  char buf[TIMESTAMP_BUF_SIZE];
1636  if (db_utime_to_string (buf, sizeof (buf), db_get_timestamp (value)))
1637  {
1638  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1639  {
1640  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1641  }
1642  else
1643  {
1644  result = duplicate_string (buf);
1645  }
1646  }
1647 
1648  if (result)
1649  {
1650  len = strlen (result);
1651  }
1652  }
1653  break;
1654  case DB_TYPE_TIMESTAMPTZ:
1655  {
1656  char buf[TIMESTAMPTZ_BUF_SIZE];
1657  DB_TIMESTAMPTZ *ts_tz = db_get_timestamptz (value);
1658  if (db_timestamptz_to_string (buf, sizeof (buf), &(ts_tz->timestamp), &(ts_tz->tz_id)))
1659  {
1660  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1661  {
1662  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1663  }
1664  else
1665  {
1666  result = duplicate_string (buf);
1667  }
1668  }
1669 
1670  if (result)
1671  {
1672  len = strlen (result);
1673  }
1674  }
1675  break;
1676  case DB_TYPE_TIMESTAMPLTZ:
1677  {
1678  char buf[TIMESTAMPTZ_BUF_SIZE];
1679 
1680  if (db_timestampltz_to_string (buf, sizeof (buf), db_get_timestamp (value)))
1681  {
1682  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1683  {
1684  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1685  }
1686  else
1687  {
1688  result = duplicate_string (buf);
1689  }
1690  }
1691 
1692  if (result)
1693  {
1694  len = strlen (result);
1695  }
1696  }
1697  break;
1698  case DB_TYPE_DATETIME:
1699  {
1700  char buf[DATETIME_BUF_SIZE];
1701  if (db_datetime_to_string (buf, sizeof (buf), db_get_datetime (value)))
1702  {
1703  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1704  {
1705  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1706  }
1707  else
1708  {
1709  result = duplicate_string (buf);
1710  }
1711  }
1712 
1713  if (result)
1714  {
1715  len = strlen (result);
1716  }
1717  }
1718  break;
1719  case DB_TYPE_DATETIMETZ:
1720  {
1721  char buf[DATETIMETZ_BUF_SIZE];
1722  DB_DATETIMETZ *dt_tz = db_get_datetimetz (value);
1723  if (db_datetimetz_to_string (buf, sizeof (buf), &(dt_tz->datetime), &(dt_tz->tz_id)))
1724  {
1725  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1726  {
1727  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1728  }
1729  else
1730  {
1731  result = duplicate_string (buf);
1732  }
1733  }
1734 
1735  if (result)
1736  {
1737  len = strlen (result);
1738  }
1739  }
1740  break;
1741  case DB_TYPE_DATETIMELTZ:
1742  {
1743  char buf[DATETIMETZ_BUF_SIZE];
1744 
1745  if (db_datetimeltz_to_string (buf, sizeof (buf), db_get_datetime (value)))
1746  {
1747  if (output_type == CSQL_QUERY_OUTPUT || output_type == CSQL_LOADDB_OUTPUT)
1748  {
1749  result = string_to_string (buf, column_enclosure, '\0', strlen (buf), &len, false, false);
1750  }
1751  else
1752  {
1753  result = duplicate_string (buf);
1754  }
1755  }
1756 
1757  if (result)
1758  {
1759  len = strlen (result);
1760  }
1761  }
1762  break;
1763  case DB_TYPE_NULL:
1764  result = duplicate_string ("NULL");
1765  if (result)
1766  {
1767  len = strlen (result);
1768  }
1769  break;
1770 
1771  case DB_TYPE_BLOB:
1772  case DB_TYPE_CLOB:
1773  {
1774  DB_ELO *elo = db_get_elo (value);
1775 
1776  if (elo != NULL)
1777  {
1778  result = duplicate_string (elo->locator);
1779  }
1780 
1781  if (result != NULL)
1782  {
1783  len = strlen (result);
1784  }
1785  }
1786  break;
1787 
1788  case DB_TYPE_ENUMERATION:
1789  {
1790  int bytes_size, decomp_size;
1791  bool need_decomp = false;
1792  const char *str;
1793  char *decomposed = NULL;
1794 
1795  if (output_type == CSQL_LOADDB_OUTPUT)
1796  {
1797  result = bigint_to_string (SHORT_TO_INT (db_get_enum_short (value)), default_short_profile.fieldwidth,
1798  default_short_profile.leadingzeros, default_short_profile.leadingsymbol,
1799  default_short_profile.commas, default_short_profile.format);
1800  if (result)
1801  {
1802  len = strlen (result);
1803  }
1804  break;
1805  }
1806 
1807  if (db_get_enum_short (value) == 0 && db_get_enum_string (value) == NULL)
1808  {
1809  /* ENUM special error value */
1810  str = "";
1811  bytes_size = 0;
1812  }
1813  else
1814  {
1815  str = db_get_enum_string (value);
1816  bytes_size = db_get_enum_string_size (value);
1817  }
1818  if (bytes_size > 0 && db_get_enum_codeset (value) == INTL_CODESET_UTF8)
1819  {
1820  need_decomp =
1821  unicode_string_need_decompose ((char *) str, bytes_size, &decomp_size, lang_get_generic_unicode_norm ());
1822  }
1823 
1824  if (need_decomp)
1825  {
1826  decomposed = (char *) malloc (decomp_size * sizeof (char));
1827  if (decomposed != NULL)
1828  {
1829  unicode_decompose_string ((char *) str, bytes_size, decomposed, &decomp_size,
1831 
1832  str = decomposed;
1833  bytes_size = decomp_size;
1834  }
1835  else
1836  {
1837  return NULL;
1838  }
1839  }
1840 
1841  result = string_to_string (str, string_delimiter, '\0', bytes_size, &len, plain_string, change_single_quote);
1842  if (decomposed != NULL)
1843  {
1844  free_and_init (decomposed);
1845  }
1846  }
1847  break;
1848 
1849  default:
1850  {
1851  char temp_buffer[256];
1852 
1853  (void) sprintf (temp_buffer, "<%s>", db_get_type_name (DB_VALUE_TYPE (value)));
1854  result = duplicate_string (temp_buffer);
1855  if (result)
1856  {
1857  len = strlen (result);
1858  }
1859  }
1860  }
1861 
1862  if (length)
1863  {
1864  *length = len;
1865  }
1866  return result;
1867 }
1868 
1869 static int
1871 {
1873 }
static void add_commas(char *string)
DB_C_FLOAT db_get_float(const DB_VALUE *value)
int db_strftime(char *s, int smax, const char *fmt, DB_DATE *date, DB_TIME *timeval)
Definition: db_date.c:973
#define NO_ERROR
Definition: error_code.h:46
DB_COLLECTION * db_get_set(const DB_VALUE *value)
#define COMMA_CHAR
int db_timestamptz_to_string(char *buf, int bufsize, DB_TIMESTAMP *utime, const TZ_ID *tz_id)
Definition: db_date.c:4090
const char * db_get_class_name(DB_OBJECT *class_)
Definition: db_info.c:608
const char * db_get_type_name(DB_TYPE type_id)
Definition: db_info.c:722
char * csql_db_value_as_string(DB_VALUE *value, int *length, bool plain_string, CSQL_OUTPUT_TYPE output_type, char column_enclosure)
static DB_TYPE_SET_PROFILE default_set_profile
int db_get_int(const DB_VALUE *value)
DB_TIMESTAMP timestamp
Definition: dbtype_def.h:766
static DB_TYPE_TIME_PROFILE default_time_profile
DB_C_DOUBLE db_get_double(const DB_VALUE *value)
#define DATE_TEMP_BUFFER_LENGTH
static DB_TYPE_FLOAT_PROFILE default_float_profile
int db_get_enum_codeset(const DB_VALUE *value)
int db_get_enum_string_size(const DB_VALUE *value)
char * db_get_json_raw_body(const DB_VALUE *value)
Definition: db_macro.c:5082
char * csql_string_to_plain_string(const char *string_value, int length, int *result_length)
#define DATETIME_BUF_SIZE
Definition: string_opfunc.h:92
int db_timestampltz_to_string(char *buf, int bufsize, DB_TIMESTAMP *utime)
Definition: db_date.c:4146
int intl_get_currency_symbol_position(const DB_CURRENCY currency)
static char * bigint_to_string(DB_BIGINT int_value, int field_width, bool leading_zeros, bool leading_symbol, bool commas, char conversion)
DB_DATETIMETZ * db_get_datetimetz(const DB_VALUE *value)
DB_CONST_C_CHAR db_get_char(const DB_VALUE *value, int *length)
CSQL_OUTPUT_TYPE
Definition: csql.h:247
static char * date_as_string(DB_DATE *date_value, int format)
static DB_TYPE_SHORT_PROFILE default_short_profile
#define CAST_STRLEN
Definition: porting.h:470
#define DATE_ABREV_NAME_LENGTH
#define DB_VALUE_PRECISION(value)
Definition: dbtype.h:73
static char * object_to_string(DB_OBJECT *object, int format)
int db_print_mop(DB_OBJECT *obj, char *buffer, int maxlen)
Definition: db_old.c:733
DB_ELO * db_get_elo(const DB_VALUE *value)
int db_date_weekday(DB_DATE *date)
Definition: db_date.c:321
int db_datetimetz_to_string(char *buf, int bufsize, DB_DATETIME *dt, const TZ_ID *tz_id)
Definition: db_date.c:4302
#define DATETIMETZ_BUF_SIZE
Definition: string_opfunc.h:95
DB_TIMESTAMPTZ * db_get_timestamptz(const DB_VALUE *value)
DB_MONETARY * db_get_monetary(const DB_VALUE *value)
#define TIME_BUF_SIZE
Definition: broker_tester.c:57
DB_CURRENCY
Definition: dbtype_def.h:799
static int get_object_print_format(void)
Definition: db_set.h:35
void unicode_decompose_string(const char *str_in, const int size_in, char *str_out, int *size_out, const UNICODE_NORMALIZATION *norm)
int db_set_get(DB_SET *set, int index, DB_VALUE *value)
Definition: db_set.c:508
static void strip_trailing_zeros(char *numeric_string)
static char * string_to_string(const char *string_value, char string_delimiter, char string_introducer, int length, int *result_length, bool plain_string, bool change_single_quote)
#define TIME_FORMAT_TWELVE_HOUR
#define DOUBLE_FORMAT_SCIENTIFIC
static void return_string(CSS_CONN_ENTRY *conn, unsigned short request_id, char **buffer, int *buffer_size)
Definition: commdb.c:216
static char * double_to_string(double double_value, int field_width, int precision, const bool leading_sign, const char *leading_str, const char *trailing_str, bool leading_zeros, bool trailing_zeros, bool commas, char conversion)
#define TIMESTAMP_BUF_SIZE
Definition: string_opfunc.h:91
static DB_TYPE_NUMERIC_PROFILE default_numeric_profile
DB_DATETIME datetime
Definition: dbtype_def.h:783
#define CMSB(x)
static DB_TYPE_BIGINT_PROFILE default_bigint_profile
DB_OBJECT * db_get_object(const DB_VALUE *value)
int db_fetch_set(DB_SET *set, DB_FETCH_MODE purpose, int quit_on_error)
Definition: db_admin.c:2372
static DB_TYPE_MONETARY_PROFILE default_monetary_profile
UNICODE_NORMALIZATION * lang_get_generic_unicode_norm(void)
#define NULL
Definition: freelistheap.h:34
unsigned short db_get_enum_short(const DB_VALUE *value)
#define NUMERIC_MAX_STRING_SIZE
DB_CURRENCY type
Definition: dbtype_def.h:832
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
int db_set_size(DB_SET *set)
Definition: db_set.c:557
#define db_utime_to_string
Definition: tz_support.h:29
DB_BIGINT db_get_bigint(const DB_VALUE *value)
static const char * time_as_string(DB_TRIGGER_TIME tr_time)
int db_time_to_string(char *buf, int bufsize, DB_TIME *time)
Definition: db_date.c:3994
int db_datetime_to_string(char *buf, int bufsize, DB_DATETIME *datetime)
Definition: db_date.c:4225
int64_t DB_BIGINT
Definition: dbtype_def.h:751
int db_bit_string(const DB_VALUE *the_db_bit, const char *bit_format, char *string, int max_size)
Definition: cnv.c:8575
static const char * month_of_year_names[]
DB_CONST_C_CHAR db_get_enum_string(const DB_VALUE *value)
#define DOUBLE_FORMAT_DECIMAL
#define INT_FORMAT_HEXADECIMAL
#define SHORT_TO_INT(short_val)
char * numeric_db_value_print(const DB_VALUE *val, char *buf)
static DB_TYPE_STRING_PROFILE default_string_profile
unsigned int DB_TIME
Definition: dbtype_def.h:754
int(* csql_text_utf8_to_console)(const char *, const int, char **, int *)
Definition: csql.c:113
unsigned int DB_DATE
Definition: dbtype_def.h:771
static DB_TYPE_DOUBLE_PROFILE default_double_profile
#define COMMAS_OFFSET(COND, N)
char * locator
Definition: dbtype_def.h:948
#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)
char * intl_get_money_symbol_console(const DB_CURRENCY currency)
bool prm_get_bool_value(PARAM_ID prm_id)
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)
bool unicode_string_need_decompose(const char *str_in, const int size_in, int *decomp_size, const UNICODE_NORMALIZATION *norm)
#define OBJECT_SYMBOL_MAX
#define TIMESTAMPTZ_BUF_SIZE
Definition: string_opfunc.h:94
static char * set_to_string(DB_VALUE *value, char begin_notation, char end_notation, int max_entries, bool plain_string, CSQL_OUTPUT_TYPE output_type, char column_encolser)
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int i
Definition: dynamic_load.c:954
void db_date_decode(const DB_DATE *date, int *monthp, int *dayp, int *yearp)
Definition: db_date.c:338
DB_DATETIME * db_get_datetime(const DB_VALUE *value)
static const char * day_of_week_names[]
#define INT_FORMAT_SIGNED_DECIMAL
int db_value_clear(DB_VALUE *value)
Definition: db_macro.c:1588
int db_get_string_length(const DB_VALUE *value)
#define TIME_STRING_MAX
DB_TIME * db_get_time(const DB_VALUE *value)
static char * bit_to_string(DB_VALUE *value, char string_delimiter, bool plain_string)
static char * numeric_to_string(DB_VALUE *value, bool commas)
static DB_TYPE_INTEGER_PROFILE default_int_profile
static DB_TYPE_DATE_PROFILE default_date_profile
double amount
Definition: dbtype_def.h:831
int db_get_string_codeset(const DB_VALUE *value)
int db_datetimeltz_to_string(char *buf, int bufsize, DB_DATETIME *dt)
Definition: db_date.c:4350
static char * duplicate_string(const char *string)