Skip to content

File db_macro.c

File List > compat > db_macro.c

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/*
 * db_macro.c - API functions related to db_make and DB_GET
 *
 */

#ident "$Id$"

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

#include "system_parameter.h"
#include "error_manager.h"
#include "db.h"
#include "db_value_printer.hpp"
#include "string_opfunc.h"
#include "set_object.h"
#include "cnv.h"
#include "tz_support.h"
#if !defined(SERVER_MODE)
#include "object_accessor.h"
#endif
#include "elo.h"
#include "db_elo.h"
#include "db_set_function.h"
#include "numeric_opfunc.h"
#include "object_primitive.h"
#include "object_representation.h"
#include "db_json.hpp"

#if defined (SUPPRESS_STRLEN_WARNING)
#define strlen(s1)  ((int) strlen(s1))
#endif /* defined (SUPPRESS_STRLEN_WARNING) */

#include "dbtype.h"
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"

#define DB_NUMBER_ZERO      0

#define VALCNV_TOO_BIG_TO_MATTER   1024

enum
{
  C_TO_VALUE_NOERROR = 0,
  C_TO_VALUE_UNSUPPORTED_CONVERSION = -1,
  C_TO_VALUE_CONVERSION_ERROR = -2,
  C_TO_VALUE_TRUNCATION_ERROR = -3
};

typedef struct valcnv_buffer VALCNV_BUFFER;
struct valcnv_buffer
{
  size_t length;
  unsigned char *bytes;
};

SESSION_ID db_Session_id = DB_EMPTY_SESSION;
bool db_Keep_session = false;

int db_Row_count = DB_ROW_COUNT_NOT_SET;

static int valcnv_Max_set_elements = 10;

#if defined(SERVER_MODE)
int db_Connect_status = DB_CONNECTION_STATUS_CONNECTED;
#else
int db_Connect_status = DB_CONNECTION_STATUS_NOT_CONNECTED;
#endif
int db_Disable_modifications = 0;


static int coerce_char_to_dbvalue (DB_VALUE * value, char *buf, const int buflen);


static VALCNV_BUFFER *valcnv_append_bytes (VALCNV_BUFFER * old_string,
                       const char *new_tail, const size_t new_tail_length);
static VALCNV_BUFFER *valcnv_append_string (VALCNV_BUFFER * old_string, const char *new_tail);
static VALCNV_BUFFER *valcnv_convert_float_to_string (VALCNV_BUFFER * buf, const float value);
static VALCNV_BUFFER *valcnv_convert_double_to_string (VALCNV_BUFFER * buf, const double value);
static VALCNV_BUFFER *valcnv_convert_bit_to_string (VALCNV_BUFFER * buf, const DB_VALUE * value);
static VALCNV_BUFFER *valcnv_convert_set_to_string (VALCNV_BUFFER * buf, DB_SET * set);
static VALCNV_BUFFER *valcnv_convert_money_to_string (const double value);
static VALCNV_BUFFER *valcnv_convert_data_to_string (VALCNV_BUFFER * buf, const DB_VALUE * value);
static VALCNV_BUFFER *valcnv_convert_db_value_to_string (VALCNV_BUFFER * buf, const DB_VALUE * value);

/*
 *  db_value_put_null()
 *  return : Error indicator
 *  value(out) : value container to set NULL.
 */
int
db_value_put_null (DB_VALUE * value)
{
  CHECK_1ARG_ERROR (value);

  value->domain.general_info.is_null = 1;
  value->need_clear = false;

  return NO_ERROR;
}

/* For strings that have a size of 0, this check will fail, and therefore
 * the new interface for db_make_* functions will set the value to null, which is wrong.
 * We need to investigate if this set to 0 will work or not.
 */
inline bool
IS_INVALID_PRECISION (int p, int m)
{
  return (p != DB_DEFAULT_PRECISION) && ((p < 0) || (p > m));
}

/*
 *  db_value_domain_init() - initialize value container with given type
 *                           and precision/scale.
 *  return : Error indicator.
 *  value(in/out) : DB_VALUE container to initialize.
 *  type(in)      : Type.
 *  precision(in) : Precision.
 *  scale(in)     : Scale.
 *
 */
int
db_value_domain_init (DB_VALUE * value, const DB_TYPE type, const int precision, const int scale)
{
  int error = NO_ERROR;

  CHECK_1ARG_ERROR (value);

  /* It's important to initialize the codeset of the data portion since it is considered domain information.  It
   * doesn't matter what we set it to, since it will be reset correctly when data is stored in the DB_VALUE by one of
   * the db_make* function. */
  value->data.ch.info.codeset = 0;
  value->domain.general_info.type = type;
  value->domain.numeric_info.precision = precision;
  value->domain.numeric_info.scale = scale;
  value->need_clear = false;
  value->domain.general_info.is_null = 1;

  switch (type)
    {
    case DB_TYPE_NUMERIC:
      if (precision == DB_DEFAULT_PRECISION)
    {
      value->domain.numeric_info.precision = DB_DEFAULT_NUMERIC_PRECISION;
    }
      else
    {
      value->domain.numeric_info.precision = precision;
    }
      if (scale == DB_DEFAULT_SCALE)
    {
      value->domain.numeric_info.scale = DB_DEFAULT_NUMERIC_SCALE;
    }
      else
    {
      value->domain.numeric_info.scale = scale;
    }
      if (IS_INVALID_PRECISION (precision, DB_MAX_NUMERIC_PRECISION) || precision == 0)
    {
      error = ER_INVALID_PRECISION;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_INVALID_PRECISION, 3, precision, 0, DB_MAX_NUMERIC_PRECISION);
      value->domain.numeric_info.precision = DB_DEFAULT_NUMERIC_PRECISION;
      value->domain.numeric_info.scale = DB_DEFAULT_NUMERIC_SCALE;
    }
      break;

    case DB_TYPE_BIT:
      if (precision == DB_DEFAULT_PRECISION)
    {
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }
      else
    {
      value->domain.char_info.length = precision;
    }
      if (IS_INVALID_PRECISION (precision, DB_MAX_BIT_PRECISION))
    {
      error = ER_INVALID_PRECISION;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_INVALID_PRECISION, 3, precision, 0, DB_MAX_BIT_PRECISION);
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }

      if (precision == 0)
    {
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }
      value->data.ch.info.codeset = INTL_CODESET_RAW_BITS;
      break;

    case DB_TYPE_VARBIT:
      if (precision == DB_DEFAULT_PRECISION)
    {
      value->domain.char_info.length = DB_MAX_VARBIT_PRECISION;
    }
      else
    {
      value->domain.char_info.length = precision;
    }
      if (IS_INVALID_PRECISION (precision, DB_MAX_VARBIT_PRECISION))
    {
      error = ER_INVALID_PRECISION;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_INVALID_PRECISION, 3, precision, 0, DB_MAX_VARBIT_PRECISION);
      value->domain.char_info.length = DB_MAX_VARBIT_PRECISION;
    }

      if (precision == 0)
    {
      value->domain.char_info.length = DB_MAX_VARBIT_PRECISION;
    }
      value->data.ch.info.codeset = INTL_CODESET_RAW_BITS;
      break;

    case DB_TYPE_CHAR:
      if (precision == DB_DEFAULT_PRECISION)
    {
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }
      else
    {
      value->domain.char_info.length = precision;
    }
      if (IS_INVALID_PRECISION (precision, DB_MAX_CHAR_PRECISION))
    {
      error = ER_INVALID_PRECISION;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_INVALID_PRECISION, 3, precision, 0, DB_MAX_CHAR_PRECISION);
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }

      if (precision == 0)
    {
      value->domain.char_info.length = TP_FLOATING_PRECISION_VALUE;
    }
      value->data.ch.info.codeset = LANG_SYS_CODESET;
      value->domain.char_info.collation_id = LANG_SYS_COLLATION;
      break;

    case DB_TYPE_VARCHAR:
      if (precision == DB_DEFAULT_PRECISION)
    {
      value->domain.char_info.length = DB_MAX_VARCHAR_PRECISION;
    }
      else
    {
      value->domain.char_info.length = precision;
    }
      if (IS_INVALID_PRECISION (precision, DB_MAX_VARCHAR_PRECISION))
    {
      error = ER_INVALID_PRECISION;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_INVALID_PRECISION, 3, precision, 0, DB_MAX_VARCHAR_PRECISION);
      value->domain.char_info.length = DB_MAX_VARCHAR_PRECISION;
    }

      if (precision == 0)
    {
      value->domain.char_info.length = DB_MAX_VARCHAR_PRECISION;
    }
      value->data.ch.info.codeset = LANG_SYS_CODESET;
      value->domain.char_info.collation_id = LANG_SYS_COLLATION;
      break;

    case DB_TYPE_ENUMERATION:
      value->data.enumeration.str_val.info.codeset = LANG_SYS_CODESET;
      value->domain.char_info.collation_id = LANG_SYS_COLLATION;
      break;

    case DB_TYPE_JSON:
      value->data.json.document = NULL;
      value->data.json.schema_raw = NULL;
      break;

    case DB_TYPE_NULL:
    case DB_TYPE_INTEGER:
    case DB_TYPE_BIGINT:
    case DB_TYPE_FLOAT:
    case DB_TYPE_DOUBLE:
    case DB_TYPE_OBJECT:
    case DB_TYPE_SET:
    case DB_TYPE_MULTISET:
    case DB_TYPE_SEQUENCE:
    case DB_TYPE_MIDXKEY:
    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
    case DB_TYPE_TIME:
    case DB_TYPE_TIMESTAMP:
    case DB_TYPE_TIMESTAMPTZ:
    case DB_TYPE_TIMESTAMPLTZ:
    case DB_TYPE_DATETIME:
    case DB_TYPE_DATETIMETZ:
    case DB_TYPE_DATETIMELTZ:
    case DB_TYPE_DATE:
    case DB_TYPE_MONETARY:
    case DB_TYPE_VARIABLE:
    case DB_TYPE_SUB:
    case DB_TYPE_POINTER:
    case DB_TYPE_ERROR:
    case DB_TYPE_SHORT:
    case DB_TYPE_VOBJ:
    case DB_TYPE_OID:
    case DB_TYPE_RESULTSET:
      break;

    default:
      error = ER_UCI_INVALID_DATA_TYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      break;
    }

  return error;
}

// db_value_domain_init_default - default value initialization
//
// value - db_value to init
// type - desired type of value
//
void
db_value_domain_init_default (DB_VALUE * value, const DB_TYPE type)
{
  // default initialization should not fail
  (void) db_value_domain_init (value, type, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}

/*
 * db_value_domain_min() - Initialize value(db_value_init)
 *                         and set to the minimum value of the domain.
 * return : Error indicator.
 * value(in/out)   : Pointer to a DB_VALUE.
 * type(in)        : type.
 * precision(in)   : precision.
 * scale(in)       : scale.
 * codeset(in)     : codeset.
 * collation_id(in): collation_id.
 * enumeration(in) : enumeration elements for DB_TYPE_ENUMERATION.
 */
int
db_value_domain_min (DB_VALUE * value, const DB_TYPE type,
             const int precision, const int scale, const int codeset,
             const int collation_id, const DB_ENUMERATION * enumeration)
{
  int error;

  error = db_value_domain_init (value, type, precision, scale);
  if (error != NO_ERROR)
    {
      return error;
    }

  switch (type)
    {
    case DB_TYPE_NULL:
      break;
    case DB_TYPE_INTEGER:
      value->data.i = DB_INT32_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_BIGINT:
      value->data.bigint = DB_BIGINT_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_FLOAT:
      /* FLT_MIN is minimum normalized positive floating-point number. */
      value->data.f = -FLT_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DOUBLE:
      /* DBL_MIN is minimum normalized positive double precision number. */
      value->data.d = -DBL_MAX;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_OBJECT: not in server-side code */
    case DB_TYPE_SET:
    case DB_TYPE_MULTISET:
    case DB_TYPE_SEQUENCE:
      value->data.set = NULL;
      value->domain.general_info.is_null = 1;   /* NULL SET value */
      break;
    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
      elo_init_structure (&value->data.elo);
      value->domain.general_info.is_null = 1;   /* NULL ELO value */
      break;
    case DB_TYPE_TIME:
      value->data.time = DB_TIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMP:
    case DB_TYPE_TIMESTAMPLTZ:
      value->data.utime = DB_UTIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMPTZ:
      value->data.timestamptz.timestamp = DB_UTIME_MIN;
      value->data.timestamptz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIME:
    case DB_TYPE_DATETIMELTZ:
      value->data.datetime.date = DB_DATE_MIN;
      value->data.datetime.time = DB_TIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIMETZ:
      value->data.datetimetz.datetime.date = DB_DATE_MIN;
      value->data.datetimetz.datetime.time = DB_TIME_MIN;
      value->data.datetimetz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATE:
      value->data.date = DB_DATE_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_MONETARY:
      /* DBL_MIN is minimum normalized positive double precision number. */
      value->data.money.amount = -DBL_MAX;
      value->data.money.type = DB_CURRENCY_DEFAULT;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_VARIABLE: internal use only */
      /* case DB_TYPE_SUB: internal use only */
      /* case DB_TYPE_POINTER: method arguments only */
      /* case DB_TYPE_ERROR: method arguments only */
    case DB_TYPE_SHORT:
      value->data.sh = DB_INT16_MIN;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_VOBJ: internal use only */
    case DB_TYPE_OID:
      value->data.oid.pageid = NULL_PAGEID;
      value->data.oid.slotid = NULL_PAGEID;
      value->data.oid.volid = NULL_PAGEID;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_DB_VALUE: special for esql */
    case DB_TYPE_NUMERIC:
      {
    char str[DB_MAX_NUMERIC_PRECISION + 2];

    memset (str, 0, DB_MAX_NUMERIC_PRECISION + 2);
    str[0] = '-';
    memset (str + 1, '9', value->domain.numeric_info.precision);
    numeric_coerce_dec_str_to_num (str, value->data.num.d.buf);
    value->domain.general_info.is_null = 0;
      }
      break;
    case DB_TYPE_BIT:
    case DB_TYPE_VARBIT:
      value->data.ch.info.style = MEDIUM_STRING;
      value->data.ch.info.codeset = INTL_CODESET_RAW_BITS;
      value->data.ch.info.is_max_string = false;
      value->data.ch.info.compressed_need_clear = false;
      value->data.ch.medium.size = 1;
      value->data.ch.medium.length = -1;
      value->data.ch.medium.buf = (char *) "\0";    /* zero; 0 */
      value->data.ch.medium.compressed_buf = NULL;
      value->data.ch.medium.compressed_size = DB_NOT_YET_COMPRESSED;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_STRING: internally DB_TYPE_VARCHAR */
      /* space is the min value, matching the comparison in qstr_compare */
    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
      value->data.ch.info.style = MEDIUM_STRING;
      value->data.ch.info.codeset = codeset;
      value->data.ch.info.is_max_string = false;
      value->data.ch.info.compressed_need_clear = false;
      value->data.ch.medium.size = 1;
      value->data.ch.medium.length = -1;
      value->data.ch.medium.buf = (char *) "\40";   /* space; 32 */
      value->data.ch.medium.compressed_buf = NULL;
      value->data.ch.medium.compressed_size = DB_NOT_YET_COMPRESSED;
      value->domain.general_info.is_null = 0;
      value->domain.char_info.collation_id = collation_id;
      break;
    case DB_TYPE_ENUMERATION:
      db_make_enumeration (value, 0, NULL, 0, codeset, collation_id);
      break;
      /* case DB_TYPE_TABLE: internal use only */
    case DB_TYPE_JSON:
    case DB_TYPE_RESULTSET:
      value->domain.general_info.is_null = 1;
      value->need_clear = false;
      break;
    default:
      error = ER_UCI_INVALID_DATA_TYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      break;
    }

  return error;
}

/*
 * db_value_domain_max() - Initialize value(db_value_init)
 *                         and set to the maximum value of the domain.
 * return : Error indicator.
 * value(in/out)   : Pointer to a DB_VALUE.
 * type(in)    : type.
 * precision(in)   : precision.
 * scale(in)       : scale.
 * codeset(in)     : codeset.
 * collation_id(in): collation_id.
 * enumeration(in) : enumeration elements for DB_TYPE_ENUMERATION.
 */
int
db_value_domain_max (DB_VALUE * value, const DB_TYPE type,
             const int precision, const int scale, const int codeset,
             const int collation_id, const DB_ENUMERATION * enumeration)
{
  int error;

  error = db_value_domain_init (value, type, precision, scale);
  if (error != NO_ERROR)
    {
      return error;
    }

  switch (type)
    {
    case DB_TYPE_NULL:
      break;
    case DB_TYPE_INTEGER:
      value->data.i = DB_INT32_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_BIGINT:
      value->data.bigint = DB_BIGINT_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_FLOAT:
      value->data.f = FLT_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DOUBLE:
      value->data.d = DBL_MAX;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_OBJECT: not in server-side code */
    case DB_TYPE_SET:
    case DB_TYPE_MULTISET:
    case DB_TYPE_SEQUENCE:
      value->data.set = NULL;
      value->domain.general_info.is_null = 1;   /* NULL SET value */
      break;
    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
      elo_init_structure (&value->data.elo);
      value->domain.general_info.is_null = 1;   /* NULL ELO value */
      break;
    case DB_TYPE_TIME:
      value->data.time = DB_TIME_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMP:
    case DB_TYPE_TIMESTAMPLTZ:
      value->data.utime = DB_UTIME_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMPTZ:
      value->data.timestamptz.timestamp = DB_UTIME_MAX;
      value->data.timestamptz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIME:
    case DB_TYPE_DATETIMELTZ:
      value->data.datetime.date = DB_DATE_MAX;
      value->data.datetime.time = DB_TIME_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIMETZ:
      value->data.datetimetz.datetime.date = DB_DATE_MAX;
      value->data.datetimetz.datetime.time = DB_TIME_MAX;
      value->data.datetimetz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATE:
      value->data.date = DB_DATE_MAX;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_MONETARY:
      value->data.money.amount = DBL_MAX;
      value->data.money.type = DB_CURRENCY_DEFAULT;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_VARIABLE: internal use only */
      /* case DB_TYPE_SUB: internal use only */
      /* case DB_TYPE_POINTER: method arguments only */
      /* case DB_TYPE_ERROR: method arguments only */
    case DB_TYPE_SHORT:
      value->data.sh = DB_INT16_MAX;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_VOBJ: internal use only */
    case DB_TYPE_OID:
      value->data.oid.pageid = DB_INT32_MAX;
      value->data.oid.slotid = DB_INT16_MAX;
      value->data.oid.volid = DB_INT16_MAX;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_DB_VALUE: special for esql */
    case DB_TYPE_NUMERIC:
      {
    char str[DB_MAX_NUMERIC_PRECISION + 1];

    memset (str, 0, DB_MAX_NUMERIC_PRECISION + 1);
    memset (str, '9', value->domain.numeric_info.precision);
    numeric_coerce_dec_str_to_num (str, value->data.num.d.buf);
    value->domain.general_info.is_null = 0;
      }
      break;
    case DB_TYPE_BIT:
    case DB_TYPE_VARBIT:
      value->data.ch.info.style = MEDIUM_STRING;
      value->data.ch.info.codeset = INTL_CODESET_RAW_BITS;
      value->data.ch.info.is_max_string = true;
      value->data.ch.info.compressed_need_clear = false;
      value->data.ch.medium.size = 0;
      value->data.ch.medium.length = -1;
      value->data.ch.medium.buf = NULL;
      value->data.ch.medium.compressed_buf = NULL;
      value->data.ch.medium.compressed_size = DB_NOT_YET_COMPRESSED;
      value->domain.general_info.is_null = 0;
      break;
      /* case DB_TYPE_STRING: internally DB_TYPE_VARCHAR */
    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
      /* Case for the maximum String type. Just set the is_max_string flag to TRUE. */
      value->data.ch.info.style = MEDIUM_STRING;
      value->data.ch.info.codeset = codeset;
      value->data.ch.info.is_max_string = true;
      value->data.ch.info.compressed_need_clear = false;
      value->data.ch.medium.size = 0;
      value->data.ch.medium.length = -1;
      value->data.ch.medium.buf = NULL;
      value->data.ch.medium.compressed_buf = NULL;
      value->data.ch.medium.compressed_size = DB_NOT_YET_COMPRESSED;
      value->domain.general_info.is_null = 0;
      value->domain.char_info.collation_id = collation_id;
      break;
    case DB_TYPE_ENUMERATION:
      if (enumeration == NULL || enumeration->count <= 0)
    {
      db_make_enumeration (value, DB_ENUM_ELEMENTS_MAX, NULL, 0, (unsigned char) codeset, collation_id);
      value->data.ch.info.is_max_string = true;
    }
      else
    {
      db_make_enumeration (value, enumeration->count,
                   enumeration->elements[enumeration->count - 1].str_val.medium.buf,
                   enumeration->elements[enumeration->count - 1].str_val.medium.size,
                   (unsigned char) codeset, collation_id);
    }
      break;
      /* case DB_TYPE_TABLE: internal use only */
    case DB_TYPE_JSON:
    case DB_TYPE_RESULTSET:
      value->domain.general_info.is_null = 1;
      value->need_clear = false;
      break;
    default:
      error = ER_UCI_INVALID_DATA_TYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      break;
    }

  return error;
}

/*
 * db_value_domain_default() - Initialize value(db_value_init)
 *                 and set to the default value of the domain.
 * return : Error indicator
 * value(in/out)   : Pointer to a DB_VALUE
 * type(in)    : type
 * precision(in)   : precision
 * scale(in)       : scale
 * codeset(in)     : codeset.
 * collation_id(in): collation_id.
 * enumeration(in) : enumeration elements for DB_TYPE_ENUMERATION
 */
int
db_value_domain_default (DB_VALUE * value, const DB_TYPE type,
             const int precision, const int scale,
             const int codeset, const int collation_id, DB_ENUMERATION * enumeration)
{
  int error = NO_ERROR;

  if (TP_IS_NUMERIC_TYPE (type))
    {
      return db_value_domain_zero (value, type, precision, scale);
    }

  error = db_value_domain_init (value, type, precision, scale);
  if (error != NO_ERROR)
    {
      return error;
    }

  switch (type)
    {
    case DB_TYPE_NULL:
      break;
    case DB_TYPE_INTEGER:
    case DB_TYPE_BIGINT:
    case DB_TYPE_FLOAT:
    case DB_TYPE_DOUBLE:
    case DB_TYPE_SHORT:
    case DB_TYPE_MONETARY:
    case DB_TYPE_NUMERIC:
      assert (false);
      break;
    case DB_TYPE_SET:
      /* empty set */
      db_make_set (value, db_set_create_basic (NULL, NULL));
      break;
    case DB_TYPE_MULTISET:
      /* empty multi-set */
      db_make_multiset (value, db_set_create_multi (NULL, NULL));
      break;
    case DB_TYPE_SEQUENCE:
      /* empty sequence */
      db_make_sequence (value, db_seq_create (NULL, NULL, 0));
      break;
    case DB_TYPE_TIME:
      value->data.time = DB_TIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMP:
    case DB_TYPE_TIMESTAMPLTZ:
      value->data.utime = DB_UTIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_TIMESTAMPTZ:
      value->data.timestamptz.timestamp = DB_UTIME_MIN;
      value->data.timestamptz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIME:
    case DB_TYPE_DATETIMELTZ:
      value->data.datetime.date = DB_DATE_MIN;
      value->data.datetime.time = DB_TIME_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATETIMETZ:
      value->data.datetimetz.datetime.date = DB_DATE_MIN;
      value->data.datetimetz.datetime.time = DB_TIME_MIN;
      value->data.datetimetz.tz_id = *tz_get_utc_tz_id ();
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DATE:
      value->data.date = DB_DATE_MIN;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_OID:
      value->data.oid.pageid = NULL_PAGEID;
      value->data.oid.slotid = NULL_PAGEID;
      value->data.oid.volid = NULL_PAGEID;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_BIT:
    case DB_TYPE_VARBIT:
      db_make_bit (value, 1, "0", 1);
      break;
    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
      value->data.ch.info.style = MEDIUM_STRING;
      value->data.ch.info.codeset = codeset;
      value->data.ch.info.is_max_string = false;
      value->data.ch.info.compressed_need_clear = false;
      value->data.ch.medium.size = 0;
      value->data.ch.medium.length = -1;
      value->data.ch.medium.buf = (char *) "";
      value->data.ch.medium.compressed_buf = NULL;
      value->data.ch.medium.compressed_size = DB_NOT_YET_COMPRESSED;
      value->domain.general_info.is_null = 0;
      value->domain.char_info.collation_id = collation_id;
      break;
    case DB_TYPE_ENUMERATION:
      db_make_enumeration (value, 0, NULL, 0, codeset, collation_id);
      break;
    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
      value->data.elo.type = ELO_NULL;
      value->domain.general_info.is_null = 0;
      break;
#if 1               /* TODO - */
    case DB_TYPE_OBJECT:
    case DB_TYPE_MIDXKEY:
    case DB_TYPE_VARIABLE:
    case DB_TYPE_SUB:
    case DB_TYPE_POINTER:
    case DB_TYPE_ERROR:
    case DB_TYPE_VOBJ:
#endif
    default:
      error = ER_UCI_INVALID_DATA_TYPE;
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      break;
    }

  return error;
}

/*
 * db_value_domain_zero() - Initialize value(db_value_init)
 *              and set to the value 'zero' of the domain.
 * return : Error indicator
 * value(in/out) : Pointer to a DB_VALUE
 * type(in)      : type
 * precision(in) : precision
 * scale(in)     : scale
 *
 * Note : this makes sense only for number data types, for all other
 *    types it returns an error (ER_UCI_INVALID_DATA_TYPE);
 */
int
db_value_domain_zero (DB_VALUE * value, const DB_TYPE type, const int precision, const int scale)
{
  int error = NO_ERROR;

  assert (TP_IS_NUMERIC_TYPE (type));

  error = db_value_domain_init (value, type, precision, scale);
  if (error != NO_ERROR)
    {
      return error;
    }

  switch (type)
    {
    case DB_TYPE_INTEGER:
      value->data.i = DB_NUMBER_ZERO;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_BIGINT:
      value->data.bigint = DB_NUMBER_ZERO;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_FLOAT:
      value->data.f = DB_NUMBER_ZERO;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_DOUBLE:
      value->data.d = DB_NUMBER_ZERO;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_MONETARY:
      value->data.money.amount = DB_NUMBER_ZERO;
      value->data.money.type = DB_CURRENCY_DEFAULT;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_SHORT:
      value->data.sh = DB_NUMBER_ZERO;
      value->domain.general_info.is_null = 0;
      break;
    case DB_TYPE_NUMERIC:
      numeric_coerce_dec_str_to_num ("0", value->data.num.d.buf);
      value->domain.general_info.is_null = 0;
      break;
    default:
      error = ER_UCI_INVALID_DATA_TYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      break;
    }

  return error;
}

/*
 * db_string_truncate() - truncate string in DB_TYPE_STRING value container
 * return         : Error indicator.
 * value(in/out)  : Pointer to a DB_VALUE
 * precision(in)  : value's precision after truncate.
 */
int
db_string_truncate (DB_VALUE * value, const int precision)
{
  int error = NO_ERROR;
  DB_VALUE src_value;
  char *string = NULL;
  const char *val_str = NULL;
  int length;
  int byte_size;

  switch (DB_VALUE_TYPE (value))
    {
    case DB_TYPE_STRING:
      val_str = db_get_string (value);
      if (val_str != NULL && db_get_string_length (value) > precision)
    {
      intl_char_size ((unsigned char *) val_str, precision, db_get_string_codeset (value), &byte_size);
      string = (char *) db_private_alloc (NULL, byte_size + 1);
      if (string == NULL)
        {
          error = ER_OUT_OF_VIRTUAL_MEMORY;
          break;
        }

      assert (byte_size < db_get_string_size (value));
      strncpy (string, val_str, byte_size);
      string[byte_size] = '\0';
      db_make_varchar (&src_value, precision, string, byte_size,
               db_get_string_codeset (value), db_get_string_collation (value));

      pr_clear_value (value);
      tp_String.setval (value, &src_value, true);

      pr_clear_value (&src_value);
    }
      break;

    case DB_TYPE_CHAR:
      val_str = db_get_char (value);
      if (val_str != NULL && db_get_string_size (value) > precision)
    {
      /* char_count <= byte_count in every codeset, so byte_size <= precision guarantees no truncation */
      intl_char_count ((unsigned char *) val_str, db_get_string_size (value),
               db_get_string_codeset (value), &length);
      if (length > precision)
        {
          intl_char_size ((unsigned char *) val_str, precision, db_get_string_codeset (value), &byte_size);
          string = (char *) db_private_alloc (NULL, byte_size + 1);
          if (string == NULL)
        {
          error = ER_OUT_OF_VIRTUAL_MEMORY;
          break;
        }

          assert (byte_size < db_get_string_size (value));
          strncpy (string, val_str, byte_size);
          string[byte_size] = '\0';
          db_make_char (&src_value, precision, string, byte_size,
                db_get_string_codeset (value), db_get_string_collation (value));

          pr_clear_value (value);
          tp_Char.setval (value, &src_value, true);

          pr_clear_value (&src_value);
        }
    }
      break;

    case DB_TYPE_BIT:
      val_str = db_get_bit (value, &length);
      length = (length + 7) >> 3;
      if (val_str != NULL && length > precision)
    {
      string = (char *) db_private_alloc (NULL, precision);
      if (string == NULL)
        {
          error = ER_OUT_OF_VIRTUAL_MEMORY;
          break;
        }

      memcpy (string, val_str, precision);
      db_make_bit (&src_value, precision << 3, string, precision << 3);

      pr_clear_value (value);
      tp_Bit.setval (value, &src_value, true);

      pr_clear_value (&src_value);
    }
      break;

    case DB_TYPE_VARBIT:
      val_str = db_get_bit (value, &length);
      length = (length >> 3) + ((length & 7) ? 1 : 0);
      if (val_str != NULL && length > precision)
    {
      string = (char *) db_private_alloc (NULL, precision);
      if (string == NULL)
        {
          error = ER_OUT_OF_VIRTUAL_MEMORY;
          break;
        }

      memcpy (string, val_str, precision);
      db_make_varbit (&src_value, precision << 3, string, precision << 3);

      pr_clear_value (value);
      tp_VarBit.setval (value, &src_value, true);

      pr_clear_value (&src_value);

    }
      break;

    case DB_TYPE_NULL:
      break;
    default:
      {
    error = ER_UCI_INVALID_DATA_TYPE;
    er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_UCI_INVALID_DATA_TYPE, 0);
      }
      break;
    }

  if (string != NULL)
    {
      db_private_free (NULL, string);
    }

  return error;
}

/*
 * db_value_type_is_collection() -
 * return :
 * value(in) :
 */
bool
db_value_type_is_collection (const DB_VALUE * value)
{
  bool is_collection;
  DB_TYPE type;

  CHECK_1ARG_FALSE (value);

  type = db_value_type (value);
  is_collection = (TP_IS_SET_TYPE (type) || type == DB_TYPE_VOBJ);

  return is_collection;
}

#if defined (ENABLE_UNUSED_FUNCTION)
/*
 * db_value_eh_key() -
 * return :
 * value(in) :
 */
void *
db_value_eh_key (DB_VALUE * value)
{
  DB_OBJECT *obj;

  CHECK_1ARG_NULL (value);

  switch (value->domain.general_info.type)
    {
    case DB_TYPE_STRING:
      return db_get_string (value);
    case DB_TYPE_OBJECT:
      obj = db_get_object (value);
      if (obj == NULL)
    {
      return NULL;
    }
      else
    {
      return WS_OID (obj);
    }
    default:
      return &value->data;
    }
}

/*
 * db_value_put_db_data()
 * return     : Error indicator.
 * value(in/out) : Pointer to a DB_VALUE to set data.
 * data(in)      : Pointer to a DB_DATA.
 */
int
db_value_put_db_data (DB_VALUE * value, const DB_DATA * data)
{
  CHECK_2ARGS_ERROR (value, data);

  value->data = *data;      /* structure copy */
  return NO_ERROR;
}
#endif

/*
 * db_value_get_db_data()
 * return      : DB_DATA of value container.
 * value(in)   : Pointer to a DB_VALUE.
 */
DB_DATA *
db_value_get_db_data (DB_VALUE * value)
{
  CHECK_1ARG_NULL (value);

  return &value->data;
}

/*
 * db_value_alter_type() - change the type of given value container.
 * return         : Error indicator.
 * value(in/out)  : Pointer to a DB_VALUE.
 * type(in)       : new type.
 */
int
db_value_alter_type (DB_VALUE * value, const DB_TYPE type)
{
  CHECK_1ARG_ERROR (value);

  value->domain.general_info.type = type;
  return NO_ERROR;
}

/*
 *  db_value_put() -
 *
 *  return: an error indicator
 *     ER_DB_UNSUPPORTED_CONVERSION -
 *          The C type to DB type conversion is not supported.
 *
 *     ER_OBJ_VALUE_CONVERSION_ERROR -
 *         An error occurred while performing the requested conversion.
 *
 *     ER_OBJ_INVALID_ARGUMENTS - The value pointer is NULL.
 *
 *  value(out)      : Pointer to a DB_VALUE.  The value container will need
 *                    to be initialized prior to entry as explained below.
 *  c_type(in)      : The type of the C destination buffer (and, therefore, an
 *                    indication of the type of coercion desired)
 *  input(in)       : Pointer to a C buffer
 *  input_length(in): The length of the buffer.  The buffer length is measured
 *                    in bit for C types DB_C_BIT and DB_C_VARBIT and is
 *                    measured in bytes for all other types.
 *
 */
int
db_value_put (DB_VALUE * value, const DB_TYPE_C c_type, void *input, const int input_length)
{
  int error_code = NO_ERROR;
  int status = C_TO_VALUE_NOERROR;

  if ((value == NULL) || (input == NULL))
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0);
      return ER_OBJ_INVALID_ARGUMENTS;
    }
  else if (input_length == -1)
    {
      db_make_null (value);
      return NO_ERROR;
    }

  switch (c_type)
    {
    case DB_TYPE_C_CHAR:
    case DB_TYPE_C_VARCHAR:
      status = coerce_char_to_dbvalue (value, (char *) input, input_length);
      break;

    default:
      status = C_TO_VALUE_UNSUPPORTED_CONVERSION;
      assert (false);
      break;
    }

  if (status == C_TO_VALUE_UNSUPPORTED_CONVERSION)
    {
      error_code = ER_DB_UNSUPPORTED_CONVERSION;
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_DB_UNSUPPORTED_CONVERSION, 1, "db_value_put");
    }
  else if (status == C_TO_VALUE_CONVERSION_ERROR)
    {
      error_code = ER_OBJ_INVALID_ARGUMENTS;
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OBJ_INVALID_ARGUMENTS, 0);
    }

  return error_code;
}

/*
 * db_value_put_encoded_time() -
 * return :
 * value(out):
 * time(in):
 */
int
db_value_put_encoded_time (DB_VALUE * value, const DB_TIME * time)
{
  CHECK_1ARG_ERROR (value);

  value->domain.general_info.type = DB_TYPE_TIME;
  value->need_clear = false;
  if (time)
    {
      value->data.time = *time;
      value->domain.general_info.is_null = 0;
    }
  else
    {
      value->domain.general_info.is_null = 1;
    }

  return NO_ERROR;
}

/*
 * db_value_put_encoded_date() -
 * return :
 * value(out):
 * date(in):
 */
int
db_value_put_encoded_date (DB_VALUE * value, const DB_DATE * date)
{
  CHECK_1ARG_ERROR (value);

  value->domain.general_info.type = DB_TYPE_DATE;
  if (date)
    {
      value->data.date = *date;
      value->domain.general_info.is_null = 0;
    }
  else
    {
      value->domain.general_info.is_null = 1;
    }
  value->need_clear = false;

  return NO_ERROR;
}

/*
 * db_value_put_monetary_currency() -
 * return :
 * value(out):
 * type(in):
 */
int
db_value_put_monetary_currency (DB_VALUE * value, DB_CURRENCY const type)
{
  int error;

  CHECK_1ARG_ERROR (value);

  /* check for valid currency type don't put default case in the switch!!! */
  error = ER_INVALID_CURRENCY_TYPE;
  switch (type)
    {
    case DB_CURRENCY_DOLLAR:
    case DB_CURRENCY_YEN:
    case DB_CURRENCY_WON:
    case DB_CURRENCY_TL:
    case DB_CURRENCY_BRITISH_POUND:
    case DB_CURRENCY_CAMBODIAN_RIEL:
    case DB_CURRENCY_CHINESE_RENMINBI:
    case DB_CURRENCY_INDIAN_RUPEE:
    case DB_CURRENCY_RUSSIAN_RUBLE:
    case DB_CURRENCY_AUSTRALIAN_DOLLAR:
    case DB_CURRENCY_CANADIAN_DOLLAR:
    case DB_CURRENCY_BRASILIAN_REAL:
    case DB_CURRENCY_ROMANIAN_LEU:
    case DB_CURRENCY_EURO:
    case DB_CURRENCY_SWISS_FRANC:
    case DB_CURRENCY_DANISH_KRONE:
    case DB_CURRENCY_NORWEGIAN_KRONE:
    case DB_CURRENCY_BULGARIAN_LEV:
    case DB_CURRENCY_VIETNAMESE_DONG:
    case DB_CURRENCY_CZECH_KORUNA:
    case DB_CURRENCY_POLISH_ZLOTY:
    case DB_CURRENCY_SWEDISH_KRONA:
    case DB_CURRENCY_CROATIAN_KUNA:
    case DB_CURRENCY_SERBIAN_DINAR:
      error = NO_ERROR;     /* it's a type we expect */
      break;
    default:
      break;
    }

  if (error != NO_ERROR)
    {
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, type);
    }
  else
    {
      value->domain.general_info.type = DB_TYPE_MONETARY;
      value->data.money.type = type;
    }
  value->need_clear = false;

  return error;
}

/*
 * db_value_put_monetary_amount_as_double() -
 * return :
 * value(out):
 * amount(in):
 */
int
db_value_put_monetary_amount_as_double (DB_VALUE * value, const double amount)
{
  CHECK_1ARG_ERROR (value);

  value->domain.general_info.type = DB_TYPE_MONETARY;
  value->data.money.amount = amount;
  value->domain.general_info.is_null = 0;
  value->need_clear = false;

  return NO_ERROR;
}

/*
 *  OBTAIN DATA VALUES OF DB_VALUE
 */

/*
 * db_value_get_monetary_currency() -
 * return :
 * value(in):
 */
DB_CURRENCY
db_value_get_monetary_currency (const DB_VALUE * value)
{
  CHECK_1ARG_ZERO_WITH_TYPE (value, DB_CURRENCY);

  return value->data.money.type;
}

/*
 * db_value_get_monetary_amount_as_double() -
 * return :
 * value(in):
 */
double
db_value_get_monetary_amount_as_double (const DB_VALUE * value)
{
  CHECK_1ARG_ZERO (value);

  return value->data.money.amount;
}

/*
 * db_value_create() - construct an empty value container
 * return : a newly allocated value container
 */
DB_VALUE *
db_value_create (void)
{
  DB_VALUE *retval;

  CHECK_CONNECT_NULL ();

  retval = pr_make_ext_value ();

  return (retval);
}

/*
 * db_value_copy()- A new value is created and a copy is made of the contents
 *                  of the supplied container.  If the supplied value contains
 *                  external allocates such as strings or sets,
 *                  the external strings or sets are copied as well.
 * return    : A newly created value container.
 * value(in) : The value to copy.
 */
DB_VALUE *
db_value_copy (DB_VALUE * value)
{
  DB_VALUE *new_ = NULL;

  CHECK_CONNECT_NULL ();

  if (value != NULL)
    {
      new_ = pr_make_ext_value ();
      pr_clone_value (value, new_);
    }

  return (new_);
}

/*
 * db_value_clone() - Copies the contents of one value to another without
 *                    allocating a new container.
 *                    The destination container is NOT initialized prior
 *                    to the clone so it must be cleared before calling this
 *                    function.
 * return : Error indicator
 * src(in)     : DB_VALUE pointer of source value container.
 * dest(out)   : DB_VALUE pointer of destination value container.
 *
 */
int
db_value_clone (DB_VALUE * src, DB_VALUE * dest)
{
  int error = NO_ERROR;

  CHECK_CONNECT_ERROR ();

  if (src != NULL && dest != NULL)
    {
      error = pr_clone_value (src, dest);
    }

  return error;
}

/*
 * db_value_clear() - the value container is initialized to an empty state
 *        the internal type tag will be set to DB_TYPE_NULL.  Any external
 *        allocations such as strings or sets will be freed.
 *        The container itself is not freed and may be reused.
 * return: Error indicator
 * value(out) : the value to clear
 *
 */
int
db_value_clear (DB_VALUE * value)
{
  int error = NO_ERROR;

  /* don't check connection here, we always allow things to be freed */
  if (value != NULL)
    {
      error = pr_clear_value (value);
    }

  return error;
}

/*
 * db_value_free() - the value container is cleared and freed.  Any external
 *        allocations within the container such as strings or sets will also
 *        be freed.
 *
 * return     : Error indicator.
 * value(out) : The value to free.
 */
int
db_value_free (DB_VALUE * value)
{
  int error = NO_ERROR;

  /* don't check connection here, we always allow things to be freed */
  if (value != NULL)
    {
      error = pr_free_ext_value (value);
    }

  return error;
}

/*
 * db_value_clear_array() - all the value containers in the values array are
 *        initialized to an empty state; their internal type tag will be set
 *        to DB_TYPE_NULL. Any external allocations such as strings or sets
 *        will be freed.
 *        The array itself is not freed and may be reused.
 * return: Error indicator
 * value_array(out) : the value array to clear
 */
int
db_value_clear_array (DB_VALUE_ARRAY * value_array)
{
  int error = NO_ERROR;
  int i = 0;

  assert (value_array != NULL && value_array->size >= 0);

  for (i = 0; i < value_array->size; ++i)
    {
      int tmp_error = NO_ERROR;

      assert (value_array->vals != NULL);

      /* don't check connection here, we always allow things to be freed */
      tmp_error = pr_clear_value (&value_array->vals[i]);
      if (tmp_error != NO_ERROR && error == NO_ERROR)
    {
      error = tmp_error;
    }
    }

  return error;
}

/*
 * db_value_print() - describe the contents of a value container
 * return   : none
 * value(in): value container to print.
 */
void
db_value_print (const DB_VALUE * value)
{
  CHECK_CONNECT_VOID ();

  if (value != NULL)
    {
      db_fprint_value (stdout, value);
    }

}

/*
 * db_value_fprint() - describe the contents of a value to the specified file
 * return    : none
 * fp(in)    : file pointer.
 * value(in) : value container to print.
 */
void
db_value_fprint (FILE * fp, const DB_VALUE * value)
{
  CHECK_CONNECT_VOID ();

  if (fp != NULL && value != NULL)
    {
      db_fprint_value (fp, value);
    }
}

/*
 * db_type_to_db_domain() - see the note below.
 *
 * return : DB_DOMAIN of a primitive DB_TYPE, returns NULL otherwise
 * type(in) : a primitive DB_TYPE
 *
 * note:
 *   This function is used only in special cases where we need to get the
 *   DB_DOMAIN of a primitive DB_TYPE that has no domain parameters, or of a
 *   parameterized DB_TYPE with the default domain parameters.
 *
 *   For example, it can be used to get the DB_DOMAIN of primitive
 *   DB_TYPES like DB_TYPE_INTEGER, DB_TYPE_FLOAT, etc., or of
 *   DB_TYPE_NUMERIC(DB_DEFAULT_NUMERIC_PRECISION, DB_DEFAULT_NUMERIC_SCALE).
 *
 *   This function CANNOT be used to get the DB_DOMAIN of
 *   set/multiset/sequence and object DB_TYPEs.
 */
DB_DOMAIN *
db_type_to_db_domain (const DB_TYPE type)
{
  DB_DOMAIN *result = NULL;

  switch (type)
    {
    case DB_TYPE_INTEGER:
    case DB_TYPE_FLOAT:
    case DB_TYPE_DOUBLE:
    case DB_TYPE_TIME:
    case DB_TYPE_TIMESTAMP:
    case DB_TYPE_TIMESTAMPTZ:
    case DB_TYPE_TIMESTAMPLTZ:
    case DB_TYPE_DATETIME:
    case DB_TYPE_DATETIMETZ:
    case DB_TYPE_DATETIMELTZ:
    case DB_TYPE_DATE:
    case DB_TYPE_MONETARY:
    case DB_TYPE_SHORT:
    case DB_TYPE_BIGINT:
    case DB_TYPE_NUMERIC:
    case DB_TYPE_CHAR:
    case DB_TYPE_BIT:
    case DB_TYPE_VARCHAR:
    case DB_TYPE_VARBIT:
    case DB_TYPE_SET:
    case DB_TYPE_MULTISET:
    case DB_TYPE_SEQUENCE:
    case DB_TYPE_NULL:
    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
    case DB_TYPE_ENUMERATION:
    case DB_TYPE_ELO:
    case DB_TYPE_JSON:
      result = tp_domain_resolve_default (type);
      break;
    case DB_TYPE_SUB:
    case DB_TYPE_POINTER:
    case DB_TYPE_ERROR:
    case DB_TYPE_VOBJ:
    case DB_TYPE_OID:
    case DB_TYPE_OBJECT:
    case DB_TYPE_DB_VALUE:
    case DB_TYPE_VARIABLE:
    case DB_TYPE_RESULTSET:
    case DB_TYPE_MIDXKEY:
    case DB_TYPE_TABLE:
      result = NULL;
      break;

      /* NO DEFAULT CASE!!!!! ALL TYPES MUST GET HANDLED HERE! */
    default:
      assert (0);
      break;
    }

  return result;
}

/*
 * db_value_coerce()-coerces a DB_VALUE to another compatible DB_VALUE domain.
 * return       : error indicator.
 * src(in)      : a pointer to the original DB_VALUE.
 * dest(in/out) : a pointer to a place to put the coerced DB_VALUE.
 * desired_domain(in) : the desired domain of the coerced result.
 */
int
db_value_coerce (const DB_VALUE * src, DB_VALUE * dest, const DB_DOMAIN * desired_domain)
{
  TP_DOMAIN_STATUS status;
  int err = NO_ERROR;

  status = tp_value_cast_force (src, dest, desired_domain, false);
  if (status != DOMAIN_COMPATIBLE)
    {
      err = tp_domain_status_er_set (status, ARG_FILE_LINE, src, desired_domain);
    }

  return err;
}

/*
 * db_value_equal()- compare two values to see if they are equal.
 * return : non-zero if equal, zero if not equal
 * value1(in) : value container to compare.
 * value2(in) : value container to compare.
 *
 * note : this is a boolean test, the sign or magnitude of the non-zero return
 *        value has no meaning.
 */
int
db_value_equal (const DB_VALUE * value1, const DB_VALUE * value2)
{
  int retval;

  CHECK_CONNECT_ZERO ();

  /* this handles NULL arguments */
  retval = (tp_value_equal (value1, value2, 1));

  return (retval);
}

/*
 * db_set_compare() - This compares the two collection values.
 *    It will determine if the value1 is a subset or superset of value2.
 *    If either value is not a collection type, it will return DB_NE
 *    If both values are set types, a set comparison will be done.
 *    Otherwise a multiset comparison will be done.
 * return : DB_EQ        - values are equal
 *          DB_SUBSET    - value1 is subset of value2
 *          DB_SUPERSET  - value1 is superset of value2
 *          DB_NE        - values are not both collections.
 *          DB_UNK       - collections contain NULLs preventing
 *                         a more certain answer.
 *
 * value1(in): A db_value of some collection type.
 * value2(in): A db_value of some collection type.
 *
 */
int
db_set_compare (const DB_VALUE * value1, const DB_VALUE * value2)
{
  int retval;

  /* this handles NULL arguments */
  retval = (tp_set_compare (value1, value2, 1, 0));

  return (retval);
}

/*
 * db_value_compare() - Compares the two values for ordinal position
 *    It will attempt to coerce the two values to the most general
 *    of the two types passed in. Then a connonical comparison is done.
 *
 * return : DB_EQ  - values are equal
 *          DB_GT  - value1 is cannonicaly before value2
 *          DB_LT  - value1 is cannonicaly after value2
 *          DB_UNK - value is or contains NULLs preventing
 *                   a more certain answer
 */
int
db_value_compare (const DB_VALUE * value1, const DB_VALUE * value2)
{
  /* this handles NULL arguments */
  return tp_value_compare (value1, value2, 1, 0);
}

/*
 * db_get_currency_default() - This returns the value of the default currency
 *    identifier based on the current locale.  This was formerly defined with
 *    the variable DB_CURRENCY_DEFAULT but for the PC, we need to
 *    have this available through a function so it can be exported through
 *    the DLL.
 * return  : currency identifier.
 */
DB_CURRENCY
db_get_currency_default ()
{
  return lang_currency ();
}

int
db_get_deep_copy_of_json (const DB_JSON * src, DB_JSON * dst)
{
  char *raw_schema_body = NULL;
  JSON_DOC *doc_copy = NULL;

  CHECK_2ARGS_ERROR (src, dst);

  assert (dst->document == NULL && dst->schema_raw == NULL);

  raw_schema_body = db_private_strdup (NULL, src->schema_raw);

  doc_copy = db_json_get_copy_of_doc (src->document);

  dst->schema_raw = raw_schema_body;
  dst->document = doc_copy;

  return NO_ERROR;
}

int
db_init_db_json_pointers (DB_JSON * val)
{
  CHECK_1ARG_ERROR (val);

  val->schema_raw = NULL;
  val->document = NULL;

  return NO_ERROR;
}

/*
 * coerce_char_to_dbvalue() - Coerce the C character string into the
 *                       desired type and place in a DB_VALUE container.
 * return :
 *     C_TO_VALUE_NOERROR                - No errors occurred
 *     C_TO_VALUE_UNSUPPORTED_CONVERSION - The conversion to the db_value
 *                                         type is not supported
 * value(in/out): DB_VALUE container for result.  This also contains the DB
 *                type to convert to.
 * buf(in)      : Pointer to character buffer
 * buflen(in)   : Length of character buffer (size in bytes)
 *
 */
static int
coerce_char_to_dbvalue (DB_VALUE * value, char *buf, const int buflen)
{
  int status = C_TO_VALUE_NOERROR;
  DB_TYPE db_type = DB_VALUE_DOMAIN_TYPE (value);

  switch (db_type)
    {
    case DB_TYPE_NUMERIC:
      {
    DB_VALUE tmp_value;
    unsigned char new_num[DB_NUMERIC_BUF_SIZE];
    int desired_precision = DB_VALUE_PRECISION (value);
    int desired_scale = DB_VALUE_SCALE (value);

    /* string_to_num will coerce the string to a numeric, but will set the precision and scale based on the value
     * passed. Then we call num_to_num to coerce to the desired precision and scale. */

    if (numeric_coerce_string_to_num (buf, buflen, LANG_SYS_CODESET, &tmp_value) != NO_ERROR)
      {
        status = C_TO_VALUE_CONVERSION_ERROR;
      }
    else if (numeric_coerce_num_to_num
         (db_get_numeric (&tmp_value), DB_VALUE_PRECISION (&tmp_value),
          DB_VALUE_SCALE (&tmp_value), desired_precision, desired_scale, new_num) != NO_ERROR)
      {
        status = C_TO_VALUE_CONVERSION_ERROR;
      }
    else
      {
        /* Yes, I know that the precision and scale are already set, but this is neater than just assigning the
         * value. */
        db_make_numeric (value, new_num, desired_precision, desired_scale);
      }

    db_value_clear (&tmp_value);
      }
      break;
    default:
      assert (false);
      status = C_TO_VALUE_UNSUPPORTED_CONVERSION;
      break;
    }

  return status;
}

/*
 * DOMAIN ACCESSORS
 */

/*
 * db_domain_next() - This can be used to iterate through a list of domain
 *           descriptors returned by functions such as db_attribute_domain.
 * return : The next domain descriptor(or NULL if at end of list).
 * domain(in): domain descriptor.
 */
DB_DOMAIN *
db_domain_next (const DB_DOMAIN * domain)
{
  DB_DOMAIN *next = NULL;

  if (domain != NULL)
    {
      next = domain->next;
    }

  return (next);
}

/*
 * db_domain_type() - See the note below.
 * return    : type identifier constant.
 * domain(in): domain descriptor.
 *
 * note:
 *    Returns the basic type identifier for a domain descriptor.
 *    This will be a numeric value as defined by the DB_TYPE_ enumeration.
 *    IFF this value is DB_TYPE_OBJECT then the domain will have additional
 *    information in the "class" field that can be accessed with
 *    db_domain_class.  This will tell you the specific class that was
 *    defined for this domain.  If the class field is NULL, the domain is
 *    a generic object and can be a reference to any object.  IFF the domain
 *    type is DB_TYPE_SET, DB_TYPE_MULTISET, or DB_TYPE_SEQUENCE, there
 *    will be additional domain information in the "set" field of the domain
 *    descriptor that can be accessed with db_domain_set.  This will be
 *    an additional list of domain descriptors that define the domains of the
 *    elements of the set.
 */
DB_TYPE
db_domain_type (const DB_DOMAIN * domain)
{
  return TP_DOMAIN_TYPE (domain);
}

/*
 * db_domain_class() - see the note below.
 *
 * return     : a class pointer
 * domain(in) : domain descriptor
 * note:
 *    This can be used to get the specific domain class for a domain whose
 *    basic type is DB_TYPE_OBJECT.  This value may be NULL indicating that
 *    the domain is the general object domain and can reference any type of
 *    object.
 *    This should check to see if the domain class was dropped.  This won't
 *    happen in the ususal case because the domain list is filtered by
 *    db_attribute_domain and related functions which always serve as the
 *    sources for this list.  Filtering again here would slow it down
 *    even more.  If it is detected as deleted and we downgrade to
 *    "object", this could leave the containing domain list will multiple
 *    object domains.
 */
DB_OBJECT *
db_domain_class (const DB_DOMAIN * domain)
{
  DB_OBJECT *class_mop = NULL;

  if ((domain != NULL) && (domain->type == tp_Type_object))
    {
      class_mop = domain->class_mop;
    }

  return (class_mop);
}

/*
 * db_domain_set() - see the note below.
 * return : domain descriptor or NULL.
 * domain(in): domain descriptor.
 *
 * note:
 *    This can be used to get set domain information for a domain
 *    whose basic type is DB_TYPE_SET, DB_TYPE_MULTISET, or DB_TYPE_SEQUENCE
 *    This field will always be NULL for any other kind of basic type.
 *    This field may be NULL even for set types if there was no additional
 *    domain information specified when the attribute was defined.
 *    The returned domain list can be examined just like other domain
 *    descriptors using the db_domain functions.  In theory, domains
 *    could be fully hierarchical by containing nested sets.  Currently,
 *    this is not allowed by the schema manager but it may be allowed
 *    in the future.
 */
DB_DOMAIN *
db_domain_set (const DB_DOMAIN * domain)
{
  DB_DOMAIN *setdomain = NULL;

  if ((domain != NULL) && (pr_is_set_type (TP_DOMAIN_TYPE (domain)) || TP_DOMAIN_TYPE (domain) == DB_TYPE_MIDXKEY))
    {
      setdomain = domain->setdomain;
    }

  return (setdomain);
}

/*
 * db_domain_precision() - Get the precision of the given domain.
 * return    : precision of domain.
 * domain(in): domain descriptor.
 *
 */
int
db_domain_precision (const DB_DOMAIN * domain)
{
  int precision = 0;

  if (domain != NULL)
    {
      precision = domain->precision;
    }

  return (precision);
}

/*
 * db_domain_scale() - Get the scale of the given domain.
 * return    : scale of domain.
 * domain(in): domain descriptor.
 *
 */
int
db_domain_scale (const DB_DOMAIN * domain)
{
  int scale = 0;

  if (domain != NULL)
    {
      scale = domain->scale;
    }

  return (scale);
}

/*
 * db_domain_codeset() - Get the codeset of the given domain.
 * return    : codeset of domain.
 * domain(in): domain descriptor.
 */
int
db_domain_codeset (const DB_DOMAIN * domain)
{
  int codeset = 0;

  if (domain != NULL)
    {
      codeset = domain->codeset;
    }

  return (codeset);
}

/*
 * db_domain_collation_id() - Get the collation id of the given domain.
 * return    : codeset of domain.
 * domain(in): domain descriptor.
 */
int
db_domain_collation_id (const DB_DOMAIN * domain)
{
  int collation_id = 0;

  if (domain != NULL)
    {
      collation_id = domain->collation_id;
    }

  return (collation_id);
}

const char *
db_domain_raw_json_schema (const DB_DOMAIN * domain)
{
  if (domain == NULL || domain->json_validator == NULL)
    {
      return NULL;
    }

  return db_json_get_schema_raw_from_validator (domain->json_validator);
}

/*
 * db_string_put_cs_and_collation() - Set the charset and collation.
 * return      : error code
 * cs(in)      : codeset
 * collation_id(in): collation identifier
 */
int
db_string_put_cs_and_collation (DB_VALUE * value, const int codeset, const int collation_id)
{
  int error = NO_ERROR;

  CHECK_1ARG_ERROR (value);

  if (TP_IS_CHAR_TYPE (value->domain.general_info.type))
    {
      value->data.ch.info.codeset = (char) codeset;
      value->domain.char_info.collation_id = collation_id;
    }
  else
    {
      error = ER_QPROC_INVALID_DATATYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_DATATYPE, 0);
    }

  return error;
}

/*
 * db_enum_put_cs_and_collation() - Set the charset and collation.
 * return      : error code
 * cs(in)      : codeset
 * collation_id(in): collation identifier
 */
int
db_enum_put_cs_and_collation (DB_VALUE * value, const int codeset, const int collation_id)
{
  int error = NO_ERROR;

  CHECK_1ARG_ERROR (value);

  if (value->domain.general_info.type == DB_TYPE_ENUMERATION)
    {
      value->data.enumeration.str_val.info.codeset = (char) codeset;
      value->domain.char_info.collation_id = collation_id;
    }
  else
    {
      error = ER_QPROC_INVALID_DATATYPE;
      er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_QPROC_INVALID_DATATYPE, 0);
    }

  return error;
}

/*
 * vc_append_bytes(): append a string to string buffer
 *
 *   returns: on success, ptr to concatenated string. otherwise, NULL.
 *   old_string(IN/OUT): original string
 *   new_tail(IN): string to be appended
 *   new_tail_length(IN): length of the string to be appended
 *
 */
static VALCNV_BUFFER *
valcnv_append_bytes (VALCNV_BUFFER * buffer_p, const char *new_tail_p, const size_t new_tail_length)
{
  size_t old_length;

  if (new_tail_p == NULL)
    {
      return buffer_p;
    }
  else if (buffer_p == NULL)
    {
      buffer_p = (VALCNV_BUFFER *) malloc (sizeof (VALCNV_BUFFER));
      if (buffer_p == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (VALCNV_BUFFER));
      return NULL;
    }

      buffer_p->length = 0;
      buffer_p->bytes = NULL;
    }

  old_length = buffer_p->length;
  buffer_p->length += new_tail_length;

  buffer_p->bytes = (unsigned char *) realloc (buffer_p->bytes, buffer_p->length);
  if (buffer_p->bytes == NULL)
    {
      er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, buffer_p->length);
      return NULL;
    }

  memcpy (&buffer_p->bytes[old_length], new_tail_p, new_tail_length);
  return buffer_p;
}

/*
 * vc_append_string(): append a string to string buffer
 *
 *   returns: on success, ptr to concatenated string. otherwise, NULL.
 *   old_string(IN/OUT): original string
 *   new_tail(IN): string to be appended
 *
 */
static VALCNV_BUFFER *
valcnv_append_string (VALCNV_BUFFER * buffer_p, const char *new_tail_p)
{
  return valcnv_append_bytes (buffer_p, new_tail_p, strlen (new_tail_p));
}

/*
 * vc_float_to_string(): append float value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf(IN/OUT): buffer
 *   value(IN): floating point value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_float_to_string (VALCNV_BUFFER * buffer_p, const float value)
{
  char tbuf[24];

  sprintf (tbuf, "%.17g", value);

#if defined(HPUX)
  /* workaround for HP's broken printf */
  if (strstr (tbuf, "++") || strstr (tbuf, "--"))
#else /* HPUX */
  if (strstr (tbuf, "Inf"))
#endif /* HPUX */
    {
      sprintf (tbuf, "%.17g", (value > 0 ? FLT_MAX : -FLT_MAX));
    }

  return valcnv_append_string (buffer_p, tbuf);
}

/*
 * vc_double_to_string(): append double value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf : buffer
 *   value(IN): double value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_double_to_string (VALCNV_BUFFER * buffer_p, const double value)
{
  char tbuf[24];

  sprintf (tbuf, "%.17g", value);

#if defined(HPUX)
  /* workaround for HP's broken printf */
  if (strstr (tbuf, "++") || strstr (tbuf, "--"))
#else /* HPUX */
  if (strstr (tbuf, "Inf"))
#endif /* HPUX */
    {
      sprintf (tbuf, "%.17g", (value > 0 ? DBL_MAX : -DBL_MAX));
    }

  return valcnv_append_string (buffer_p, tbuf);
}

/*
 * vc_bit_to_string(): append bit value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf(IN/OUT): buffer
 *   value(IN): BIT value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_bit_to_string (VALCNV_BUFFER * buffer_p, const DB_VALUE * value_p)
{
  const unsigned char *bit_string_p;
  int nibble_len, nibbles, count;
  char tbuf[10];

  bit_string_p = REINTERPRET_CAST (const unsigned char *, db_get_string (value_p));
  nibble_len = (db_get_string_length (value_p) + 3) / 4;

  for (nibbles = 0, count = 0; nibbles < nibble_len - 1; count++, nibbles += 2)
    {
      sprintf (tbuf, "%02x", bit_string_p[count]);
      tbuf[2] = '\0';
      buffer_p = valcnv_append_string (buffer_p, tbuf);
      if (buffer_p == NULL)
    {
      return NULL;
    }
    }

  if (nibbles < nibble_len)
    {
      sprintf (tbuf, "%1x", bit_string_p[count]);
      tbuf[1] = '\0';
      buffer_p = valcnv_append_string (buffer_p, tbuf);
      if (buffer_p == NULL)
    {
      return NULL;
    }
    }

  return buffer_p;
}

/*
 * vc_set_to_string(): append set value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf(IN/OUT): buffer
 *   set(IN): SET value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_set_to_string (VALCNV_BUFFER * buffer_p, DB_SET * set_p)
{
  DB_VALUE value;
  int err, size, max_n, i;

  if (set_p == NULL)
    {
      return buffer_p;
    }

  buffer_p = valcnv_append_string (buffer_p, "{");
  if (buffer_p == NULL)
    {
      return NULL;
    }

  size = set_size (set_p);
  if (valcnv_Max_set_elements == 0)
    {
      max_n = size;
    }
  else
    {
      max_n = MIN (size, valcnv_Max_set_elements);
    }

  for (i = 0; i < max_n; i++)
    {
      err = set_get_element (set_p, i, &value);
      if (err < 0)
    {
      return NULL;
    }

      buffer_p = valcnv_convert_db_value_to_string (buffer_p, &value);
      pr_clear_value (&value);
      if (i < size - 1)
    {
      buffer_p = valcnv_append_string (buffer_p, ", ");
      if (buffer_p == NULL)
        {
          return NULL;
        }
    }
    }

  if (i < size)
    {
      buffer_p = valcnv_append_string (buffer_p, "...");
      if (buffer_p == NULL)
    {
      return NULL;
    }
    }

  buffer_p = valcnv_append_string (buffer_p, "}");
  if (buffer_p == NULL)
    {
      return NULL;
    }

  return buffer_p;
}

/*
 * vc_money_to_string(): append monetary value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   value(IN): monetary value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_money_to_string (const double value)
{
  char cbuf[LDBL_MAX_10_EXP + 20];  /* 20 == floating fudge factor */

  sprintf (cbuf, "%.2f", value);

#if defined(HPUX)
  /* workaround for HP's broken printf */
  if (strstr (cbuf, "++") || strstr (cbuf, "--"))
#else /* HPUX */
  if (strstr (cbuf, "Inf"))
#endif /* HPUX */
    {
      sprintf (cbuf, "%.2f", (value > 0 ? DBL_MAX : -DBL_MAX));
    }

  return valcnv_append_string (NULL, cbuf);
}

/*
 * vc_data_to_string(): append a value to string buffer
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf(IN/OUT): buffer
 *   value(IN): a value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_data_to_string (VALCNV_BUFFER * buffer_p, const DB_VALUE * value_p)
{
  OID *oid_p;
  DB_SET *set_p;
  DB_ELO *elo_p;
  const char *src_p, *end_p, *p;
  ptrdiff_t len;

  DB_MONETARY *money_p;
  VALCNV_BUFFER *money_string_p;
  const char *currency_symbol_p;
  double amount;
  DB_VALUE dbval;

  char line[1025];

  int cnt;

  if (DB_IS_NULL (value_p))
    {
      buffer_p = valcnv_append_string (buffer_p, "NULL");
    }
  else
    {
      switch (DB_VALUE_TYPE (value_p))
    {
    case DB_TYPE_INTEGER:
      sprintf (line, "%d", db_get_int (value_p));
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_BIGINT:
      sprintf (line, "%lld", (long long) db_get_bigint (value_p));
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_SHORT:
      sprintf (line, "%d", (int) db_get_short (value_p));
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_FLOAT:
      buffer_p = valcnv_convert_float_to_string (buffer_p, db_get_float (value_p));
      break;

    case DB_TYPE_DOUBLE:
      buffer_p = valcnv_convert_double_to_string (buffer_p, db_get_double (value_p));
      break;

    case DB_TYPE_NUMERIC:
      buffer_p = valcnv_append_string (buffer_p, numeric_db_value_print (value_p, line));
      break;

    case DB_TYPE_BIT:
    case DB_TYPE_VARBIT:
      buffer_p = valcnv_convert_bit_to_string (buffer_p, value_p);
      break;

    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
      src_p = db_get_string (value_p);

      if (src_p != NULL && db_get_string_size (value_p) == 0)
        {
          buffer_p = valcnv_append_string (buffer_p, "");
          return buffer_p;
        }

      end_p = src_p + db_get_string_size (value_p);
      while (src_p < end_p)
        {
          for (p = src_p; p < end_p && *p != '\''; p++)
        {
          ;
        }

          if (p < end_p)
        {
          len = p - src_p + 1;
          buffer_p = valcnv_append_bytes (buffer_p, src_p, len);
          if (buffer_p == NULL)
            {
              return NULL;
            }

          buffer_p = valcnv_append_string (buffer_p, "'");
          if (buffer_p == NULL)
            {
              return NULL;
            }
        }
          else
        {
          buffer_p = valcnv_append_bytes (buffer_p, src_p, end_p - src_p);
          if (buffer_p == NULL)
            {
              return NULL;
            }
        }

          src_p = p + 1;
        }
      break;

    case DB_TYPE_OID:
      oid_p = (OID *) db_get_oid (value_p);

      sprintf (line, "%d", (int) oid_p->volid);
      buffer_p = valcnv_append_string (buffer_p, line);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, "|");
      if (buffer_p == NULL)
        {
          return NULL;
        }

      sprintf (line, "%d", (int) oid_p->pageid);
      buffer_p = valcnv_append_string (buffer_p, line);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, "|");
      if (buffer_p == NULL)
        {
          return NULL;
        }

      sprintf (line, "%d", (int) oid_p->slotid);
      buffer_p = valcnv_append_string (buffer_p, line);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      break;

    case DB_TYPE_SET:
    case DB_TYPE_MULTISET:
    case DB_TYPE_SEQUENCE:
      set_p = db_get_set (value_p);
      if (set_p == NULL)
        {
          buffer_p = valcnv_append_string (buffer_p, "NULL");
        }
      else
        {
          return valcnv_convert_set_to_string (buffer_p, set_p);
        }

      break;

    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
      elo_p = db_get_elo (value_p);
      if (elo_p == NULL)
        {
          buffer_p = valcnv_append_string (buffer_p, "NULL");
        }
      else
        {
          if (elo_p->type == ELO_FBO)
        {
          assert (elo_p->locator != NULL);
          buffer_p = valcnv_append_string (buffer_p, elo_p->locator);
        }
          else      /* ELO_LO */
        {
          /* should not happen for now */
          assert (0);
        }
        }
      break;

    case DB_TYPE_TIME:
      cnt = db_time_to_string (line, VALCNV_TOO_BIG_TO_MATTER, db_get_time (value_p));
      if (cnt == 0)
        {
          return NULL;
        }
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_TIMESTAMP:
      cnt = db_timestamp_to_string (line, VALCNV_TOO_BIG_TO_MATTER, db_get_timestamp (value_p));
      if (cnt == 0)
        {
          return NULL;
        }
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_TIMESTAMPTZ:
      {
        DB_TIMESTAMPTZ *ts_tz = db_get_timestamptz (value_p);

        cnt = db_timestamptz_to_string (line, VALCNV_TOO_BIG_TO_MATTER, &(ts_tz->timestamp), &(ts_tz->tz_id));
        if (cnt == 0)
          {
        return NULL;
          }
        buffer_p = valcnv_append_string (buffer_p, line);
      }
      break;

    case DB_TYPE_TIMESTAMPLTZ:
      {
        TZ_ID tz_id;
        DB_TIMESTAMP *utime;

        utime = db_get_timestamp (value_p);
        if (tz_create_session_tzid_for_timestamp (utime, &tz_id) != NO_ERROR)
          {
        return NULL;
          }
        cnt = db_timestamptz_to_string (line, VALCNV_TOO_BIG_TO_MATTER, utime, &tz_id);
        if (cnt == 0)
          {
        return NULL;
          }
        buffer_p = valcnv_append_string (buffer_p, line);
      }
      break;

    case DB_TYPE_DATETIME:
      cnt = db_datetime_to_string (line, VALCNV_TOO_BIG_TO_MATTER, db_get_datetime (value_p));
      if (cnt == 0)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_DATETIMETZ:
      {
        DB_DATETIMETZ *dt_tz = db_get_datetimetz (value_p);

        cnt = db_datetimetz_to_string (line, VALCNV_TOO_BIG_TO_MATTER, &(dt_tz->datetime), &(dt_tz->tz_id));
        if (cnt == 0)
          {
        return NULL;
          }

        buffer_p = valcnv_append_string (buffer_p, line);
      }
      break;

    case DB_TYPE_DATETIMELTZ:
      {
        TZ_ID tz_id;
        DB_DATETIME *dt;

        dt = db_get_datetime (value_p);
        if (tz_create_session_tzid_for_datetime (dt, true, &tz_id) != NO_ERROR)
          {
        return NULL;
          }

        cnt = db_datetimetz_to_string (line, VALCNV_TOO_BIG_TO_MATTER, dt, &tz_id);
        if (cnt == 0)
          {
        return NULL;
          }

        buffer_p = valcnv_append_string (buffer_p, line);
      }
      break;

    case DB_TYPE_DATE:
      cnt = db_date_to_string (line, VALCNV_TOO_BIG_TO_MATTER, db_get_date (value_p));
      if (cnt == 0)
        {
          return NULL;
        }
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_MONETARY:
      money_p = db_get_monetary (value_p);
      OR_MOVE_DOUBLE (&money_p->amount, &amount);
      money_string_p = valcnv_convert_money_to_string (amount);
      if (money_string_p == NULL)
        {
          return NULL;
        }

      currency_symbol_p = lang_currency_symbol (money_p->type);
      strcpy (line, currency_symbol_p);
      strncpy (line + strlen (currency_symbol_p), (char *) money_string_p->bytes, money_string_p->length);
      line[strlen (currency_symbol_p) + money_string_p->length] = '\0';

      free_and_init (money_string_p->bytes);
      free_and_init (money_string_p);
      buffer_p = valcnv_append_string (buffer_p, line);
      break;

    case DB_TYPE_ENUMERATION:
      if (db_get_enum_short (value_p) == 0 && db_get_enum_string (value_p) == NULL)
        {
          /* ENUM special error value */
          db_value_domain_default (&dbval, DB_TYPE_VARCHAR,
                       DB_DEFAULT_PRECISION, 0, LANG_SYS_CODESET, LANG_SYS_COLLATION, NULL);
          buffer_p = valcnv_convert_data_to_string (buffer_p, &dbval);
        }
      else if (db_get_enum_string_size (value_p) > 0)
        {
          db_make_string (&dbval, db_get_enum_string (value_p));

          buffer_p = valcnv_convert_data_to_string (buffer_p, &dbval);
        }
      break;

    default:
      break;
    }
    }

  return buffer_p;
}

/*
 * vc_db_value_to_string(): append a value to string buffer with a type prefix
 *
 *   returns: on success, ptr to converted string. otherwise, NULL.
 *   buf(IN/OUT): buffer
 *   value(IN): a value which is to be converted
 *
 */
static VALCNV_BUFFER *
valcnv_convert_db_value_to_string (VALCNV_BUFFER * buffer_p, const DB_VALUE * value_p)
{
  if (DB_IS_NULL (value_p))
    {
      buffer_p = valcnv_append_string (buffer_p, "NULL");
    }
  else
    {
      switch (DB_VALUE_TYPE (value_p))
    {
    case DB_TYPE_BIT:
    case DB_TYPE_VARBIT:
      buffer_p = valcnv_append_string (buffer_p, "X'");
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_convert_data_to_string (buffer_p, value_p);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, "'");
      break;

    case DB_TYPE_BLOB:
    case DB_TYPE_CLOB:
      if (DB_VALUE_TYPE (value_p) == DB_TYPE_BLOB)
        {
          buffer_p = valcnv_append_string (buffer_p, "BLOB'");
        }
      else
        {
          buffer_p = valcnv_append_string (buffer_p, "CLOB'");
        }

      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_convert_data_to_string (buffer_p, value_p);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, "'");
      break;

    case DB_TYPE_ENUMERATION:
      buffer_p = valcnv_append_string (buffer_p, "'");
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_convert_data_to_string (buffer_p, value_p);
      if (buffer_p == NULL)
        {
          return NULL;
        }

      buffer_p = valcnv_append_string (buffer_p, "'");
      break;

    default:
      buffer_p = valcnv_convert_data_to_string (buffer_p, value_p);
      break;
    }
    }

  return buffer_p;
}

/*
 * valcnv_convert_value_to_string(): convert a value to a string type value
 *
 *   returns: on success, NO_ERROR. otherwise, ER_FAILED.
 *   value(IN/OUT): a value which is to be converted to string
 *                  Note that the value is cleaned up during conversion.
 *
 */
int
valcnv_convert_value_to_string (DB_VALUE * value_p)
{
  VALCNV_BUFFER buffer = { 0, NULL };
  VALCNV_BUFFER *buf_p;
  DB_VALUE src_value;

  if (!DB_IS_NULL (value_p))
    {
      buf_p = &buffer;
      buf_p = valcnv_convert_db_value_to_string (buf_p, value_p);
      if (buf_p == NULL)
    {
      return ER_FAILED;
    }

      db_make_varchar (&src_value, DB_MAX_STRING_LENGTH, REINTERPRET_CAST (char *, buf_p->bytes),
               CAST_STRLEN (buf_p->length), LANG_SYS_CODESET, LANG_SYS_COLLATION);

      pr_clear_value (value_p);
      tp_String.setval (value_p, &src_value, true);

      pr_clear_value (&src_value);
      free_and_init (buf_p->bytes);
    }

  return NO_ERROR;
}

#if !defined(SERVER_MODE)
int
db_get_connect_status (void)
{
  return db_Connect_status;
}

void
db_set_connect_status (int status)
{
  db_Connect_status = status;
}
#endif

/*
 * db_default_expression_string() -
 * return : string opcode of default expression
 * default_expr_type(in):
 */
const char *
db_default_expression_string (DB_DEFAULT_EXPR_TYPE default_expr_type)
{
  switch (default_expr_type)
    {
    case DB_DEFAULT_NONE:
      return NULL;
    case DB_DEFAULT_SYSDATE:
      return "SYS_DATE";
    case DB_DEFAULT_SYSDATETIME:
      return "SYS_DATETIME";
    case DB_DEFAULT_SYSTIMESTAMP:
      return "SYS_TIMESTAMP";
    case DB_DEFAULT_UNIX_TIMESTAMP:
      return "UNIX_TIMESTAMP()";
    case DB_DEFAULT_USER:
      return "USER()";
    case DB_DEFAULT_CURR_USER:
      return "CURRENT_USER";
    case DB_DEFAULT_CURRENTDATETIME:
      return "CURRENT_DATETIME";
    case DB_DEFAULT_CURRENTTIMESTAMP:
      return "CURRENT_TIMESTAMP";
    case DB_DEFAULT_CURRENTTIME:
      return "CURRENT_TIME";
    case DB_DEFAULT_CURRENTDATE:
      return "CURRENT_DATE";
    case DB_DEFAULT_SYSTIME:
      return "SYS_TIME";
    default:
      return NULL;
    }
}

int
db_convert_json_into_scalar (const DB_VALUE * src, DB_VALUE * dest)
{
  CHECK_2ARGS_ERROR (src, dest);
  JSON_DOC *doc = db_get_json_document (src);

  assert (doc != NULL);

  switch (db_json_get_type (doc))
    {
    case DB_JSON_STRING:
      {
    const char *str = db_json_get_string_from_document (doc);
    int error_code = db_make_string (dest, str);
    if (error_code != NO_ERROR)
      {
        ASSERT_ERROR ();
        return error_code;
      }
    break;
      }
    case DB_JSON_INT:
      {
    int val = db_json_get_int_from_document (doc);
    db_make_int (dest, val);
    break;
      }
    case DB_JSON_BIGINT:
      {
    int64_t val = db_json_get_bigint_from_document (doc);
    db_make_bigint (dest, val);
    break;
      }
    case DB_JSON_DOUBLE:
      {
    double val = db_json_get_double_from_document (doc);
    db_make_double (dest, val);
    break;
      }
    case DB_JSON_BOOL:
      {
    char *str = db_json_get_bool_as_str_from_document (doc);
    int error_code = db_make_string (dest, str);
    if (error_code != NO_ERROR)
      {
        ASSERT_ERROR ();
        return error_code;
      }
    dest->need_clear = true;
    break;
      }
    case DB_JSON_NULL:
      db_make_null (dest);
      break;
    default:
      assert (false);
      return ER_FAILED;
    }

  return NO_ERROR;
}

bool
db_is_json_value_type (DB_TYPE type)
{
  switch (type)
    {
    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
    case DB_TYPE_NULL:
    case DB_TYPE_SHORT:
    case DB_TYPE_INTEGER:
    case DB_TYPE_DOUBLE:
    case DB_TYPE_JSON:
    case DB_TYPE_NUMERIC:
    case DB_TYPE_BIGINT:
    case DB_TYPE_ENUMERATION:
      return true;
    default:
      return false;
    }
}

bool
db_is_json_doc_type (DB_TYPE type)
{
  switch (type)
    {
    case DB_TYPE_CHAR:
    case DB_TYPE_VARCHAR:
    case DB_TYPE_JSON:
      return true;
    default:
      return false;
    }
}

char *
db_get_json_raw_body (const DB_VALUE * value)
{
  return db_json_get_json_body_from_document (*value->data.json.document);
}

/*
 * db_value_is_corrupted(): Check whether the db_value is corrupted
 *
 *   returns: true if corrupted, false otherwise.
 *   value(in): the value to check
 */
bool
db_value_is_corrupted (const DB_VALUE * value)
{
  if (value == NULL || DB_IS_NULL (value))
    {
      return false;
    }

  switch (value->domain.general_info.type)
    {
    case DB_TYPE_NUMERIC:
      if (IS_INVALID_PRECISION (value->domain.numeric_info.precision, DB_MAX_NUMERIC_PRECISION))
    {
      return true;
    }
      break;

    case DB_TYPE_BIT:
      if (IS_INVALID_PRECISION (value->domain.char_info.length, DB_MAX_BIT_PRECISION))
    {
      return true;
    }
      break;

    case DB_TYPE_VARBIT:
      if (IS_INVALID_PRECISION (value->domain.char_info.length, DB_MAX_VARBIT_PRECISION))
    {
      return true;
    }
      break;

    case DB_TYPE_CHAR:
      if (IS_INVALID_PRECISION (value->domain.char_info.length, DB_MAX_CHAR_PRECISION))
    {
      return true;
    }
      break;

    case DB_TYPE_VARCHAR:
      if (IS_INVALID_PRECISION (value->domain.char_info.length, DB_MAX_VARCHAR_PRECISION))
    {
      return true;
    }
      break;

    default:
      break;
    }

  return false;
}