File object_primitive.c¶
File List > cubrid > src > object > object_primitive.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.
*
*/
/*
* object_primitive.c - This file contains code for handling the values of
* primitive types in memory and for conversion between
* the disk representation.
*/
#ident "$Id$"
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "object_primitive.h"
#include "area_alloc.h"
#include "db_value_printer.hpp"
#include "db_json.hpp"
#include "elo.h"
#include "error_manager.h"
#include "file_io.h"
#include "compressor.hpp"
#include "mem_block.hpp"
#include "object_representation.h"
#include "set_object.h"
#include "string_buffer.hpp"
#include "string_opfunc.h"
#include "system_parameter.h"
#include "tz_support.h"
#include <utility>
#if !defined (SERVER_MODE)
#include "work_space.h"
#include "virtual_object.h"
#include "transform_cl.h"
#include "dbi.h"
#endif /* !defined (SERVER_MODE) */
#include "dbtype.h"
#include "memory_private_allocator.hpp"
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
#if defined (SUPPRESS_STRLEN_WARNING)
#define strlen(s1) ((int) strlen(s1))
#endif /* defined (SUPPRESS_STRLEN_WARNING) */
#if !defined(SERVER_MODE)
extern unsigned int db_on_server;
#endif
#define MR_CMP(d1, d2) \
((d1) < (d2) ? DB_LT : (d1) > (d2) ? DB_GT : DB_EQ)
#define MR_CMP_RETURN_CODE(c) \
((c) < 0 ? DB_LT : (c) > 0 ? DB_GT : DB_EQ)
/*
* MR_OID_SIZE
* Hack so we don't have to conditionalize the type vector.
* On the server we don't have the structure definition for this.
*/
#if !defined (SERVER_MODE)
#define MR_OID_SIZE sizeof(WS_MEMOID)
#else
#define MR_OID_SIZE 0
#endif
#define VALUE_AREA_COUNT 1024
/*
* PR_OID_PROMOTION_DEFAULT
*
* It is intended to allow some control over whether or not OIDs read
* by "readval" are automatically promoted to MOPs or not. This
* is used to prevent cluttering up the workspace with MOPs when we
* don't really need them. When this is enabled, callers of "readval"
* had better be prepared to see DB_VALUE structures containing unswizzled
* OIDs rather than MOPs. Not intended for use by by real applications.
* Think about this more, this may also be the mechanism by which the server
* can control reading of object values.
*
* Note that this makes sense only for the "readval" function, the "readmem
* function must be building a workspace instance memory representation
* and oid promotion cannot be controlled there.
*
*/
#if defined (SERVER_MODE)
#define PR_INHIBIT_OID_PROMOTION_DEFAULT 1
#else
#define PR_INHIBIT_OID_PROMOTION_DEFAULT 0
#endif
/*
* These are currently fixed length widets of length DB_NUMERIC_BUF_SIZE.
* Ultimately they may be of variable size based on the precision and scale,
* in antipication of that move, use the followign function for copying.
*/
#define OR_NUMERIC_SIZE(precision) DB_NUMERIC_BUF_SIZE
#define MR_NUMERIC_SIZE(precision) DB_NUMERIC_BUF_SIZE
#define STR_SIZE(prec, codeset) \
(((codeset) == INTL_CODESET_RAW_BITS) ? ((prec+7)/8) : \
INTL_CODESET_MULT (codeset) * (prec))
#define BITS_IN_BYTE 8
#define BITS_TO_BYTES(bit_cnt) (((bit_cnt) + 7) / 8)
#define DB_DOMAIN_INIT_CHAR(value, precision) \
do { \
(value)->domain.general_info.type = DB_TYPE_CHAR; \
(value)->domain.general_info.is_null = 1; \
(value)->domain.char_info.length = \
(precision) == DB_DEFAULT_PRECISION ? \
TP_FLOATING_PRECISION_VALUE : (precision); \
(value)->need_clear = false; \
(value)->data.ch.info.codeset = LANG_SYS_CODESET; \
(value)->domain.char_info.collation_id = LANG_SYS_COLLATION; \
} while (0)
#define IS_FLOATING_PRECISION(prec) \
((prec) == TP_FLOATING_PRECISION_VALUE)
// *INDENT-OFF*
pr_type::pr_type (const char * name_arg, DB_TYPE id_arg, int varp_arg, int size_arg, int disksize_arg, int align_arg,
initmem_function_type initmem_f_arg, initval_function_type initval_f_arg,
setmem_function_type setmem_f_arg, getmem_function_type getmem_f_arg,
setval_function_type setval_f_arg, data_lengthmem_function_type data_lengthmem_f_arg,
data_lengthval_function_type data_lengthval_f_arg, data_writemem_function_type data_writemem_f_arg,
data_readmem_function_type data_readmem_f_arg, data_writeval_function_type data_writeval_f_arg,
data_readval_function_type data_readval_f_arg, index_lengthmem_function_type index_lengthmem_f_arg,
index_lengthval_function_type index_lengthval_f_arg,
index_writeval_function_type index_writeval_f_arg, index_readval_function_type index_readval_f_arg,
index_cmpdisk_function_type index_cmpdisk_f_arg, freemem_function_type freemem_f_arg,
data_cmpdisk_function_type data_cmpdisk_f_arg, cmpval_function_type cmpval_f_arg)
: name {name_arg}
, id {id_arg}
, variable_p {varp_arg}
, size {size_arg}
, disksize {disksize_arg}
, alignment {align_arg}
, f_initmem {initmem_f_arg}
, f_initval {initval_f_arg}
, f_setmem {setmem_f_arg}
, f_getmem {getmem_f_arg}
, f_setval {setval_f_arg}
, f_data_lengthmem {data_lengthmem_f_arg}
, f_data_lengthval {data_lengthval_f_arg}
, f_data_writemem {data_writemem_f_arg}
, f_data_readmem {data_readmem_f_arg}
, f_data_writeval {data_writeval_f_arg}
, f_data_readval {data_readval_f_arg}
, f_index_lengthmem {index_lengthmem_f_arg}
, f_index_lengthval {index_lengthval_f_arg}
, f_index_writeval {index_writeval_f_arg}
, f_index_readval {index_readval_f_arg}
, f_index_cmpdisk {index_cmpdisk_f_arg}
, f_freemem {freemem_f_arg}
, f_data_cmpdisk {data_cmpdisk_f_arg}
, f_cmpval {cmpval_f_arg}
{
}
void
pr_type::set_data_cmpdisk_function (data_cmpdisk_function_type data_cmpdisk_arg)
{
f_data_cmpdisk = data_cmpdisk_arg;
}
pr_type::data_cmpdisk_function_type
pr_type::get_data_cmpdisk_function () const
{
return f_data_cmpdisk;
}
void
pr_type::set_cmpval_function (cmpval_function_type cmpval_arg)
{
f_cmpval = cmpval_arg;
}
pr_type::cmpval_function_type
pr_type::get_cmpval_function () const
{
return f_cmpval;
}
// *INDENT-ON*
static void mr_initmem_string (void *mem, TP_DOMAIN * domain);
static int mr_setmem_string (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_string (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_string (void *memptr, TP_DOMAIN * domain, int disk);
static int mr_index_lengthmem_string (void *memptr, TP_DOMAIN * domain);
static void mr_data_writemem_string (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_string (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static void mr_freemem_string (void *memptr);
static void mr_initval_string (DB_VALUE * value, int precision, int scale);
static int mr_setval_string (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_string (DB_VALUE * value, int disk);
static int mr_data_writeval_string (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_string (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_lengthval_string (DB_VALUE * value);
static int mr_index_writeval_string (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_string (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_lengthval_string_internal (DB_VALUE * value, int disk, int align);
static int mr_writeval_string_internal (OR_BUF * buf, DB_VALUE * value, int align);
static int mr_readval_string_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len, int align);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_string (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_string (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_string (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
#if defined (ENABLE_UNUSED_FUNCTION)
static int mr_cmpval_string2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order,
int *start_colp);
#endif
static void mr_initmem_char (void *memptr, TP_DOMAIN * domain);
static int mr_setmem_char (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_char (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_char (void *memptr, TP_DOMAIN * domain, int disk);
static int mr_index_lengthmem_char (void *memptr, TP_DOMAIN * domain);
static void mr_data_writemem_char (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_char (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_freemem_char (void *memptr);
static void mr_initval_char (DB_VALUE * value, int precision, int scale);
static int mr_setval_char (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_char (DB_VALUE * value, int disk);
static int mr_data_writeval_char (OR_BUF * buf, DB_VALUE * value);
static int mr_writeval_char_internal (OR_BUF * buf, DB_VALUE * value, int align);
static int mr_data_readval_char (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_readval_char_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len, int align);
static int mr_index_lengthval_char (DB_VALUE * value);
static int mr_index_writeval_char (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_char (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_char (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_char (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_char (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static DB_VALUE_COMPARE_RESULT mr_cmpdisk_char_internal (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp, int align);
#if defined (ENABLE_UNUSED_FUNCTION)
static int mr_cmpval_char2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order,
int *start_colp);
#endif
static void mr_initmem_bit (void *memptr, TP_DOMAIN * domain);
static int mr_setmem_bit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_bit (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_bit (void *memptr, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_bit (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_bit (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_freemem_bit (void *memptr);
static void mr_initval_bit (DB_VALUE * value, int precision, int scale);
static int mr_setval_bit (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_bit (DB_VALUE * value, int disk);
static int mr_data_writeval_bit (OR_BUF * buf, DB_VALUE * value);
static int mr_writeval_bit_internal (OR_BUF * buf, DB_VALUE * value, int align);
static int mr_data_readval_bit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_readval_bit_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len, int align);
static int mr_index_lengthmem_bit (void *memptr, TP_DOMAIN * domain);
static int mr_index_lengthval_bit (DB_VALUE * value);
static int mr_index_writeval_bit (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_bit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_bit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_bit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpdisk_bit_internal (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp, int align);
static DB_VALUE_COMPARE_RESULT mr_cmpval_bit (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static DB_VALUE_COMPARE_RESULT mr_cmpval_bit2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion,
int total_order, int *start_colp);
static void mr_initmem_varbit (void *mem, TP_DOMAIN * domain);
static int mr_setmem_varbit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_varbit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_varbit (void *memptr, TP_DOMAIN * domain, int disk);
static int mr_index_lengthmem_varbit (void *memptr, TP_DOMAIN * domain);
static void mr_data_writemem_varbit (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_varbit (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static void mr_freemem_varbit (void *memptr);
static void mr_initval_varbit (DB_VALUE * value, int precision, int scale);
static int mr_setval_varbit (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_varbit (DB_VALUE * value, int disk);
static int mr_data_writeval_varbit (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_varbit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_lengthval_varbit (DB_VALUE * value);
static int mr_index_writeval_varbit (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_varbit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_lengthval_varbit_internal (DB_VALUE * value, int disk, int align);
static int mr_writeval_varbit_internal (OR_BUF * buf, DB_VALUE * value, int align);
static int mr_readval_varbit_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len, int align);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_varbit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_varbit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_varbit (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static DB_VALUE_COMPARE_RESULT mr_cmpval_varbit2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion,
int total_order, int *start_colp);
static void mr_initmem_null (void *mem, TP_DOMAIN * domain);
static int mr_setmem_null (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_null (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_null (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_null (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static void mr_initval_null (DB_VALUE * value, int precision, int scale);
static int mr_setval_null (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_null (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_null (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_null (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_null (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_int (void *mem, TP_DOMAIN * domain);
static int mr_setmem_int (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_int (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_int (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_int (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_int (DB_VALUE * value, int precision, int scale);
static int mr_setval_int (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_int (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_int (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static int mr_index_writeval_int (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_int (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_int (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_int (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_int (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_short (void *mem, TP_DOMAIN * domain);
static int mr_setmem_short (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_short (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_short (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_short (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_short (DB_VALUE * value, int precision, int scale);
static int mr_setval_short (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_short (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_short (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_short (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_short (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_short (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_short (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_short (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_bigint (void *mem, TP_DOMAIN * domain);
static int mr_setmem_bigint (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_bigint (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_bigint (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_bigint (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_bigint (DB_VALUE * value, int precision, int scale);
static int mr_setval_bigint (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_bigint (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_bigint (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_bigint (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_bigint (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_bigint (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_bigint (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_bigint (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_float (void *mem, TP_DOMAIN * domain);
static int mr_setmem_float (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_float (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_float (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_float (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_float (DB_VALUE * value, int precision, int scale);
static int mr_setval_float (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_float (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_float (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_float (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_float (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_float (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_float (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_float (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_double (void *mem, TP_DOMAIN * domain);
static int mr_setmem_double (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_double (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_double (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_double (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_double (DB_VALUE * value, int precision, int scale);
static int mr_setval_double (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_double (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_double (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_double (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_double (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_double (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_double (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_double (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_time (void *mem, TP_DOMAIN * domain);
static int mr_setmem_time (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_time (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_time (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_time (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_time (DB_VALUE * value, int precision, int scale);
static int mr_setval_time (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_time (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_time (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_time (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_time (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_time (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_time (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_time (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_utime (void *mem, TP_DOMAIN * domain);
static int mr_setmem_utime (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_utime (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_getmem_timestampltz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_utime (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_utime (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_utime (DB_VALUE * value, int precision, int scale);
static void mr_initval_timestampltz (DB_VALUE * value, int precision, int scale);
static int mr_setval_utime (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_setval_timestampltz (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_utime (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_utime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_data_readval_timestampltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_utime (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_utime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_readval_timestampltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_utime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_utime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_utime (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_timestamptz (void *mem, TP_DOMAIN * domain);
static int mr_setmem_timestamptz (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_timestamptz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_timestamptz (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_timestamptz (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_timestamptz (DB_VALUE * value, int precision, int scale);
static int mr_setval_timestamptz (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_timestamptz (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_timestamptz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_timestamptz (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_timestamptz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_timestamptz (void *mem1, void *mem2, TP_DOMAIN * domain,
int do_coercion, int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_timestamptz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_timestamptz (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initmem_datetime (void *memptr, TP_DOMAIN * domain);
static void mr_initval_datetime (DB_VALUE * value, int precision, int scale);
static void mr_initval_datetimeltz (DB_VALUE * value, int precision, int scale);
static int mr_setmem_datetime (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_datetime (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_getmem_datetimeltz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_datetime (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_setval_datetimeltz (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static void mr_data_writemem_datetime (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_datetime (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static int mr_data_writeval_datetime (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_datetime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_data_readval_datetimeltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_datetime (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_datetime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_readval_datetimeltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_datetime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_datetime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_datetime (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initmem_datetimetz (void *memptr, TP_DOMAIN * domain);
static void mr_initval_datetimetz (DB_VALUE * value, int precision, int scale);
static int mr_setmem_datetimetz (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_datetimetz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_datetimetz (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static void mr_data_writemem_datetimetz (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_datetimetz (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static int mr_data_writeval_datetimetz (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_datetimetz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_datetimetz (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_datetimetz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_datetimetz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_datetimetz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_datetimetz (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initmem_money (void *memptr, TP_DOMAIN * domain);
static int mr_setmem_money (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_money (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_money (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_money (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_money (DB_VALUE * value, int precision, int scale);
static int mr_setval_money (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_money (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_money (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_money (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_money (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_money (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_money (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_money (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_date (void *mem, TP_DOMAIN * domain);
static int mr_setmem_date (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_date (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_date (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_date (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_date (DB_VALUE * value, int precision, int scale);
static int mr_setval_date (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_date (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_date (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_date (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_date (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_date (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_date (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_date (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_null_oid (OID * oid);
static void mr_initmem_object (void *mem, TP_DOMAIN * domain);
static void mr_initval_object (DB_VALUE * value, int precision, int scale);
static int mr_setmem_object (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_object (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_object (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_object (DB_VALUE * value, int disk);
static void mr_data_writemem_object (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_object (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_data_writeval_object (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_object (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_writeval_object (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_object (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_object (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_object (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_object (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_elo (void *memptr, TP_DOMAIN * domain);
static void mr_initval_elo (DB_VALUE * value, int precision, int scale);
static int mr_setmem_elo (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_setval_elo (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_elo (void *memptr, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_elo (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_elo (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_getmem_elo (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int getmem_elo_with_type (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy, DB_TYPE type);
static void peekmem_elo (OR_BUF * buf, DB_ELO * elo);
static int mr_data_lengthval_elo (DB_VALUE * value, int disk);
static int mr_data_writeval_elo (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_elo (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static int setval_elo_with_type (DB_VALUE * dest, const DB_VALUE * src, bool copy, DB_TYPE type);
static int readval_elo_with_type (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len, DB_TYPE type);
static void mr_freemem_elo (void *memptr);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_elo (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_elo (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initval_blob (DB_VALUE * value, int precision, int scale);
static int mr_getmem_blob (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_blob (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_readval_blob (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static void mr_initval_clob (DB_VALUE * value, int precision, int scale);
static int mr_getmem_clob (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_clob (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_readval_clob (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static void mr_initval_variable (DB_VALUE * value, int precision, int scale);
static int mr_setval_variable (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_variable (DB_VALUE * value, int disk);
static int mr_data_writeval_variable (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_variable (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_variable (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_variable (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initmem_sub (void *mem, TP_DOMAIN * domain);
static void mr_initval_sub (DB_VALUE * value, int precision, int scale);
static int mr_setmem_sub (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_sub (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_sub (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_sub (void *mem, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_sub (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_sub (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static int mr_data_lengthval_sub (DB_VALUE * value, int disk);
static int mr_data_writeval_sub (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_sub (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_sub (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_sub (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_ptr (void *memptr, TP_DOMAIN * domain);
static void mr_initval_ptr (DB_VALUE * value, int precision, int scale);
static int mr_setmem_ptr (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_ptr (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_ptr (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_ptr (void *memptr, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_ptr (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_ptr (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_data_lengthval_ptr (DB_VALUE * value, int disk);
static int mr_data_writeval_ptr (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_ptr (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_ptr (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_ptr (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_error (void *memptr, TP_DOMAIN * domain);
static void mr_initval_error (DB_VALUE * value, int precision, int scale);
static int mr_setmem_error (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_error (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_error (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_error (void *memptr, TP_DOMAIN * domain, int disk);
static int mr_data_lengthval_error (DB_VALUE * value, int disk);
static void mr_data_writemem_error (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_error (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_data_writeval_error (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_error (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_error (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_error (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_oid (void *memptr, TP_DOMAIN * domain);
static void mr_initval_oid (DB_VALUE * value, int precision, int scale);
static int mr_setmem_oid (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_oid (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_oid (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static void mr_data_writemem_oid (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_oid (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_data_writeval_oid (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_oid (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static int mr_index_writeval_oid (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_oid (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_oid (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_oid (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_oid (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_set (void *memptr, TP_DOMAIN * domain);
static void mr_initval_set (DB_VALUE * value, int precision, int scale);
static int mr_setmem_set (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_set (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_set_internal (DB_VALUE * dest, const DB_VALUE * src, bool copy, DB_TYPE set_type);
static int mr_setval_set (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_set (void *memptr, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_set (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_set (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static int mr_data_lengthval_set (DB_VALUE * value, int disk);
static int mr_data_writeval_set (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_set (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len);
static void mr_freemem_set (void *memptr);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_set (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_set (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initval_multiset (DB_VALUE * value, int precision, int scale);
static int mr_getmem_multiset (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_multiset (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static void mr_initval_sequence (DB_VALUE * value, int precision, int scale);
static int mr_getmem_sequence (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_sequence (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_sequence (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_sequence (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initval_midxkey (DB_VALUE * value, int precision, int scale);
static int mr_setval_midxkey (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthmem_midxkey (void *memptr, TP_DOMAIN * domain, int disk);
static int mr_index_lengthmem_midxkey (void *memptr, TP_DOMAIN * domain);
static int mr_data_lengthval_midxkey (DB_VALUE * value, int disk);
static int mr_index_lengthval_midxkey (DB_VALUE * value);
static int mr_data_writeval_midxkey (OR_BUF * buf, DB_VALUE * value);
static int mr_index_writeval_midxkey (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_midxkey (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_readval_midxkey (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT pr_midxkey_compare_element (char *mem1, char *mem2, TP_DOMAIN * dom1, TP_DOMAIN * dom2,
int do_coercion, int total_order);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_midxkey (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_midxkey (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_midxkey (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initval_vobj (DB_VALUE * value, int precision, int scale);
static int mr_setval_vobj (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_readval_vobj (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_vobj (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_vobj (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
static void mr_initmem_numeric (void *memptr, TP_DOMAIN * domain);
static int mr_setmem_numeric (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_numeric (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_numeric (void *mem, TP_DOMAIN * domain, int disk);
static int mr_index_lengthmem_numeric (void *mem, TP_DOMAIN * domain);
static void mr_data_writemem_numeric (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_numeric (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_numeric (DB_VALUE * value, int precision, int scale);
static int mr_setval_numeric (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_numeric (DB_VALUE * value, int disk);
static int mr_data_writeval_numeric (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_numeric (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_index_lengthval_numeric (DB_VALUE * value);
static int mr_index_writeval_numeric (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_numeric (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_numeric (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_numeric (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_numeric (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static void mr_initmem_resultset (void *mem, TP_DOMAIN * domain);
static int mr_setmem_resultset (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_resultset (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static void mr_data_writemem_resultset (OR_BUF * buf, void *mem, TP_DOMAIN * domain);
static void mr_data_readmem_resultset (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static void mr_initval_resultset (DB_VALUE * value, int precision, int scale);
static int mr_setval_resultset (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_writeval_resultset (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_resultset (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_resultset (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_resultset (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static int pr_midxkey_get_vals_size (TP_DOMAIN * domains, DB_VALUE * dbvals, int total);
static int pr_midxkey_get_element_internal (const DB_MIDXKEY * midxkey, int index, DB_VALUE * value, bool copy,
int *prev_indexp, char **prev_ptrp);
static void mr_initmem_enumeration (void *mem, TP_DOMAIN * domain);
static void mr_initval_enumeration (DB_VALUE * value, int precision, int scale);
static int mr_setmem_enumeration (void *mem, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_enumeration (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_setval_enumeration (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static void mr_data_writemem_enumeration (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_enumeration (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size);
static int mr_setval_enumeration_internal (DB_VALUE * value, TP_DOMAIN * domain, unsigned short index, int size,
bool copy, char *copy_buf, int copy_buf_len);
static int mr_data_readval_enumeration (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int mr_data_writeval_enumeration (OR_BUF * buf, DB_VALUE * value);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_enumeration (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_enumeration (DB_VALUE * value1, DB_VALUE * value2, int do_coercion,
int total_order, int *start_colp, int collation);
static DB_VALUE_COMPARE_RESULT mr_index_cmpdisk_enumeration (void *mem1, void *mem2, TP_DOMAIN * domain,
int do_coercion, int total_order, int *start_colp);
static int mr_index_writeval_enumeration (OR_BUF * buf, DB_VALUE * value);
static int mr_index_readval_enumeration (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static int pr_write_compressed_string_to_buffer (OR_BUF * buf, const char *compressed_string, int compressed_length,
int decompressed_length, int alignment);
static int pr_write_uncompressed_string_to_buffer (OR_BUF * buf, const char *string, int size, int align);
static void mr_initmem_json (void *mem, TP_DOMAIN * domain);
static int mr_setmem_json (void *memptr, TP_DOMAIN * domain, DB_VALUE * value);
static int mr_getmem_json (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy);
static int mr_data_lengthmem_json (void *memptr, TP_DOMAIN * domain, int disk);
static void mr_data_writemem_json (OR_BUF * buf, void *memptr, TP_DOMAIN * domain);
static void mr_data_readmem_json (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size);
static void mr_freemem_json (void *memptr);
static void mr_initval_json (DB_VALUE * value, int precision, int scale);
static int mr_setval_json (DB_VALUE * dest, const DB_VALUE * src, bool copy);
static int mr_data_lengthval_json (DB_VALUE * value, int disk);
static int mr_data_writeval_json (OR_BUF * buf, DB_VALUE * value);
static int mr_data_readval_json (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy,
char *copy_buf, int copy_buf_len);
static DB_VALUE_COMPARE_RESULT mr_data_cmpdisk_json (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion,
int total_order, int *start_colp);
static DB_VALUE_COMPARE_RESULT mr_cmpval_json (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order,
int *start_colp, int collation);
/*
* Value_area
* Area used for allocation of value containers that may be given out
* to database applications.
*/
static AREA *Value_area = NULL;
int pr_Inhibit_oid_promotion = PR_INHIBIT_OID_PROMOTION_DEFAULT;
int pr_Enable_string_compression = true;
const PR_TYPE tp_Null = {
"*NULL*", DB_TYPE_NULL, 0, 0, 0, 0,
mr_initmem_null,
mr_initval_null,
mr_setmem_null,
mr_getmem_null,
mr_setval_null,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_null,
mr_data_readmem_null,
mr_data_writeval_null,
mr_data_readval_null,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freemem */
mr_data_cmpdisk_null,
mr_cmpval_null
};
const PR_TYPE *tp_Type_null = &tp_Null;
const PR_TYPE tp_Integer = {
"integer", DB_TYPE_INTEGER, 0, sizeof (int), sizeof (int), 4,
mr_initmem_int,
mr_initval_int,
mr_setmem_int,
mr_getmem_int,
mr_setval_int,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_int,
mr_data_readmem_int,
mr_data_writeval_int,
mr_data_readval_int,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
mr_index_writeval_int,
mr_index_readval_int,
mr_index_cmpdisk_int,
NULL, /* freemem */
mr_data_cmpdisk_int,
mr_cmpval_int
};
const PR_TYPE *tp_Type_integer = &tp_Integer;
const PR_TYPE tp_Short = {
"smallint", DB_TYPE_SHORT, 0, sizeof (short), sizeof (short), 2,
mr_initmem_short,
mr_initval_short,
mr_setmem_short,
mr_getmem_short,
mr_setval_short,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_short,
mr_data_readmem_short,
mr_data_writeval_short,
mr_data_readval_short,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
mr_index_writeval_short,
mr_index_readval_short,
mr_index_cmpdisk_short,
NULL, /* freemem */
mr_data_cmpdisk_short,
mr_cmpval_short
};
const PR_TYPE *tp_Type_short = &tp_Short;
const PR_TYPE tp_Bigint = {
"bigint", DB_TYPE_BIGINT, 0, sizeof (DB_BIGINT), sizeof (DB_BIGINT), 4,
mr_initmem_bigint,
mr_initval_bigint,
mr_setmem_bigint,
mr_getmem_bigint,
mr_setval_bigint,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_bigint,
mr_data_readmem_bigint,
mr_data_writeval_bigint,
mr_data_readval_bigint,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
mr_index_writeval_bigint,
mr_index_readval_bigint,
mr_index_cmpdisk_bigint,
NULL, /* freemem */
mr_data_cmpdisk_bigint,
mr_cmpval_bigint
};
const PR_TYPE *tp_Type_bigint = &tp_Bigint;
const PR_TYPE tp_Float = {
"float", DB_TYPE_FLOAT, 0, sizeof (float), sizeof (float), 4,
mr_initmem_float,
mr_initval_float,
mr_setmem_float,
mr_getmem_float,
mr_setval_float,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_float,
mr_data_readmem_float,
mr_data_writeval_float,
mr_data_readval_float,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
mr_index_writeval_float,
mr_index_readval_float,
mr_index_cmpdisk_float,
NULL, /* freemem */
mr_data_cmpdisk_float,
mr_cmpval_float
};
const PR_TYPE *tp_Type_float = &tp_Float;
const PR_TYPE tp_Double = {
"double", DB_TYPE_DOUBLE, 0, sizeof (double), sizeof (double), 4,
mr_initmem_double,
mr_initval_double,
mr_setmem_double,
mr_getmem_double,
mr_setval_double,
NULL, /* data_lengthmem */
NULL, /* data_lenghtval */
mr_data_writemem_double,
mr_data_readmem_double,
mr_data_writeval_double,
mr_data_readval_double,
NULL, /* index_lenghtmem */
NULL, /* index_lenghtval */
mr_index_writeval_double,
mr_index_readval_double,
mr_index_cmpdisk_double,
NULL, /* freemem */
mr_data_cmpdisk_double,
mr_cmpval_double
};
const PR_TYPE *tp_Type_double = &tp_Double;
const PR_TYPE tp_Time = {
"time", DB_TYPE_TIME, 0, sizeof (DB_TIME), OR_TIME_SIZE, 4,
mr_initmem_time,
mr_initval_time,
mr_setmem_time,
mr_getmem_time,
mr_setval_time,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_time,
mr_data_readmem_time,
mr_data_writeval_time,
mr_data_readval_time,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_time,
mr_index_readval_time,
mr_index_cmpdisk_time,
NULL, /* freemem */
mr_data_cmpdisk_time,
mr_cmpval_time
};
const PR_TYPE *tp_Type_time = &tp_Time;
const PR_TYPE tp_Utime = {
"timestamp", DB_TYPE_TIMESTAMP, 0, sizeof (DB_UTIME), OR_UTIME_SIZE, 4,
mr_initmem_utime,
mr_initval_utime,
mr_setmem_utime,
mr_getmem_utime,
mr_setval_utime,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_utime,
mr_data_readmem_utime,
mr_data_writeval_utime,
mr_data_readval_utime,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_utime,
mr_index_readval_utime,
mr_index_cmpdisk_utime,
NULL, /* freemem */
mr_data_cmpdisk_utime,
mr_cmpval_utime
};
const PR_TYPE *tp_Type_utime = &tp_Utime;
const PR_TYPE tp_Timestamptz = {
"timestamptz", DB_TYPE_TIMESTAMPTZ, 0, sizeof (DB_TIMESTAMPTZ), OR_TIMESTAMPTZ_SIZE, 4,
mr_initmem_timestamptz,
mr_initval_timestamptz,
mr_setmem_timestamptz,
mr_getmem_timestamptz,
mr_setval_timestamptz,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_timestamptz,
mr_data_readmem_timestamptz,
mr_data_writeval_timestamptz,
mr_data_readval_timestamptz,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_timestamptz,
mr_index_readval_timestamptz,
mr_index_cmpdisk_timestamptz,
NULL, /* freemem */
mr_data_cmpdisk_timestamptz,
mr_cmpval_timestamptz
};
const PR_TYPE *tp_Type_Timestamptz = &tp_Timestamptz;
/* timestamp with locale time zone has the same storage and primitives as
* (simple) timestamp */
const PR_TYPE tp_Timestampltz = {
"timestampltz", DB_TYPE_TIMESTAMPLTZ, 0, sizeof (DB_UTIME), OR_UTIME_SIZE, 4,
mr_initmem_utime,
mr_initval_timestampltz,
mr_setmem_utime,
mr_getmem_timestampltz,
mr_setval_timestampltz,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_utime,
mr_data_readmem_utime,
mr_data_writeval_utime,
mr_data_readval_timestampltz,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_utime,
mr_index_readval_timestampltz,
mr_index_cmpdisk_utime,
NULL, /* freemem */
mr_data_cmpdisk_utime,
mr_cmpval_utime
};
const PR_TYPE tp_Datetime = {
"datetime", DB_TYPE_DATETIME, 0, sizeof (DB_DATETIME), OR_DATETIME_SIZE, 4,
mr_initmem_datetime,
mr_initval_datetime,
mr_setmem_datetime,
mr_getmem_datetime,
mr_setval_datetime,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_datetime,
mr_data_readmem_datetime,
mr_data_writeval_datetime,
mr_data_readval_datetime,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_datetime,
mr_index_readval_datetime,
mr_index_cmpdisk_datetime,
NULL, /* freemem */
mr_data_cmpdisk_datetime,
mr_cmpval_datetime
};
const PR_TYPE *tp_Type_datetime = &tp_Datetime;
const PR_TYPE tp_Datetimetz = {
"datetimetz", DB_TYPE_DATETIMETZ, 0, sizeof (DB_DATETIMETZ), OR_DATETIMETZ_SIZE, 4,
mr_initmem_datetimetz,
mr_initval_datetimetz,
mr_setmem_datetimetz,
mr_getmem_datetimetz,
mr_setval_datetimetz,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_datetimetz,
mr_data_readmem_datetimetz,
mr_data_writeval_datetimetz,
mr_data_readval_datetimetz,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_datetimetz,
mr_index_readval_datetimetz,
mr_index_cmpdisk_datetimetz,
NULL, /* freemem */
mr_data_cmpdisk_datetimetz,
mr_cmpval_datetimetz
};
const PR_TYPE *tp_Type_Datetimetz = &tp_Datetimetz;
/* datetime with locale time zone has the same storage and primitives as
* (simple) datetime */
const PR_TYPE tp_Datetimeltz = {
"datetimeltz", DB_TYPE_DATETIMELTZ, 0, sizeof (DB_DATETIME), OR_DATETIME_SIZE, 4,
mr_initmem_datetime,
mr_initval_datetimeltz,
mr_setmem_datetime,
mr_getmem_datetimeltz,
mr_setval_datetimeltz,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_datetime,
mr_data_readmem_datetime,
mr_data_writeval_datetime,
mr_data_readval_datetimeltz,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_datetime,
mr_index_readval_datetimeltz,
mr_index_cmpdisk_datetime,
NULL, /* freemem */
mr_data_cmpdisk_datetime,
mr_cmpval_datetime
};
const PR_TYPE *tp_Type_datetimeltz = &tp_Datetimeltz;
const PR_TYPE tp_Monetary = {
"monetary", DB_TYPE_MONETARY, 0, sizeof (DB_MONETARY), OR_MONETARY_SIZE, 4,
mr_initmem_money,
mr_initval_money,
mr_setmem_money,
mr_getmem_money,
mr_setval_money,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_money,
mr_data_readmem_money,
mr_data_writeval_money,
mr_data_readval_money,
NULL, /* index_lenghmem */
NULL, /* index_lenghval */
mr_index_writeval_money,
mr_index_readval_money,
mr_index_cmpdisk_money,
NULL, /* freemem */
mr_data_cmpdisk_money,
mr_cmpval_money
};
const PR_TYPE *tp_Type_monetary = &tp_Monetary;
const PR_TYPE tp_Date = {
"date", DB_TYPE_DATE, 0, sizeof (DB_DATE), OR_DATE_SIZE, 4,
mr_initmem_date,
mr_initval_date,
mr_setmem_date,
mr_getmem_date,
mr_setval_date,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_date,
mr_data_readmem_date,
mr_data_writeval_date,
mr_data_readval_date,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_index_writeval_date,
mr_index_readval_date,
mr_index_cmpdisk_date,
NULL, /* freemem */
mr_data_cmpdisk_date,
mr_cmpval_date
};
const PR_TYPE *tp_Type_date = &tp_Date;
/*
* tp_Object
*
* ALERT!!! We set the alignment for OIDs to 8 even though they only have an
* int and two shorts. This is done because the WS_MEMOID has a pointer
* following the OID and it must be on an 8 byte boundary for the Alpha boxes.
*/
const PR_TYPE tp_Object = {
"object", DB_TYPE_OBJECT, 0, MR_OID_SIZE, OR_OID_SIZE, 4,
mr_initmem_object,
mr_initval_object,
mr_setmem_object,
mr_getmem_object,
mr_setval_object,
NULL, /* data_lengthmem */
mr_data_lengthval_object,
mr_data_writemem_object,
mr_data_readmem_object,
mr_data_writeval_object,
mr_data_readval_object,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_index_writeval_object,
mr_index_readval_object,
mr_index_cmpdisk_object,
NULL, /* freemem */
mr_data_cmpdisk_object,
mr_cmpval_object
};
const PR_TYPE *tp_Type_object = &tp_Object;
const PR_TYPE tp_Elo = { /* todo: remove me */
"*elo*", DB_TYPE_ELO, 1, sizeof (DB_ELO *), 0, 8,
mr_initmem_elo,
mr_initval_elo,
mr_setmem_elo,
mr_getmem_elo,
mr_setval_elo,
mr_data_lengthmem_elo,
mr_data_lengthval_elo,
mr_data_writemem_elo,
mr_data_readmem_elo,
mr_data_writeval_elo,
mr_data_readval_elo,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_elo,
mr_data_cmpdisk_elo,
mr_cmpval_elo
};
const PR_TYPE *tp_Type_elo = &tp_Elo;
const PR_TYPE tp_Blob = {
"blob", DB_TYPE_BLOB, 1, sizeof (DB_ELO *), 0, 8,
mr_initmem_elo,
mr_initval_blob,
mr_setmem_elo,
mr_getmem_blob,
mr_setval_blob,
mr_data_lengthmem_elo,
mr_data_lengthval_elo,
mr_data_writemem_elo,
mr_data_readmem_elo,
mr_data_writeval_elo,
mr_data_readval_blob,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_elo,
mr_data_cmpdisk_elo,
mr_cmpval_elo
};
const PR_TYPE *tp_Type_blob = &tp_Blob;
const PR_TYPE tp_Clob = {
"clob", DB_TYPE_CLOB, 1, sizeof (DB_ELO *), 0, 8,
mr_initmem_elo,
mr_initval_clob,
mr_setmem_elo,
mr_getmem_clob,
mr_setval_clob,
mr_data_lengthmem_elo,
mr_data_lengthval_elo,
mr_data_writemem_elo,
mr_data_readmem_elo,
mr_data_writeval_elo,
mr_data_readval_clob,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_elo,
mr_data_cmpdisk_elo,
mr_cmpval_elo
};
const PR_TYPE *tp_Type_clob = &tp_Clob;
const PR_TYPE tp_Variable = {
"*variable*", DB_TYPE_VARIABLE, 1, sizeof (DB_VALUE), 0, 4,
NULL, /* initmem */
mr_initval_variable,
NULL, /* setmem */
NULL, /* getmem */
mr_setval_variable,
NULL, /* data_lengthmem */
mr_data_lengthval_variable,
NULL, /* data_writemem */
NULL, /* data_readmem */
mr_data_writeval_variable,
mr_data_readval_variable,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freemem */
mr_data_cmpdisk_variable,
mr_cmpval_variable
};
const PR_TYPE *tp_Type_variable = &tp_Variable;
const PR_TYPE tp_Substructure = {
"*substructure*", DB_TYPE_SUB, 1, sizeof (void *), 0, 8,
mr_initmem_sub,
mr_initval_sub,
mr_setmem_sub,
mr_getmem_sub,
mr_setval_sub,
mr_data_lengthmem_sub,
mr_data_lengthval_sub,
mr_data_writemem_sub,
mr_data_readmem_sub,
mr_data_writeval_sub,
mr_data_readval_sub,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freemem */
mr_data_cmpdisk_sub,
mr_cmpval_sub
};
const PR_TYPE *tp_Type_substructure = &tp_Substructure;
const PR_TYPE tp_Pointer = {
"*pointer*", DB_TYPE_POINTER, 0, sizeof (void *), 0, 4,
mr_initmem_ptr,
mr_initval_ptr,
mr_setmem_ptr,
mr_getmem_ptr,
mr_setval_ptr,
mr_data_lengthmem_ptr,
mr_data_lengthval_ptr,
mr_data_writemem_ptr,
mr_data_readmem_ptr,
mr_data_writeval_ptr,
mr_data_readval_ptr,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freeemem */
mr_data_cmpdisk_ptr,
mr_cmpval_ptr
};
const PR_TYPE *tp_Type_pointer = &tp_Pointer;
const PR_TYPE tp_Error = {
"*error*", DB_TYPE_ERROR, 0, sizeof (int), 0, 4,
mr_initmem_error,
mr_initval_error,
mr_setmem_error,
mr_getmem_error,
mr_setval_error,
mr_data_lengthmem_error,
mr_data_lengthval_error,
mr_data_writemem_error,
mr_data_readmem_error,
mr_data_writeval_error,
mr_data_readval_error,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freemem */
mr_data_cmpdisk_error,
mr_cmpval_error
};
const PR_TYPE *tp_Type_error = &tp_Error;
/*
* tp_Oid
*
* ALERT!!! We set the alignment for OIDs to 8 even though they only have an
* int and two shorts. This is done because the WS_MEMOID has a pointer
* following the OID and it must be on an 8 byte boundary for the Alpha boxes.
*/
const PR_TYPE tp_Oid = {
"*oid*", DB_TYPE_OID, 0, sizeof (OID), OR_OID_SIZE, 4,
mr_initmem_oid,
mr_initval_oid,
mr_setmem_oid,
mr_getmem_oid,
mr_setval_oid,
NULL, /* lengthmem */
NULL, /* lengthval */
mr_data_writemem_oid,
mr_data_readmem_oid,
mr_data_writeval_oid,
mr_data_readval_oid,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
mr_index_writeval_oid,
mr_index_readval_oid,
mr_index_cmpdisk_oid,
NULL, /* freemem */
mr_data_cmpdisk_oid,
mr_cmpval_oid
};
const PR_TYPE *tp_Type_oid = &tp_Oid;
const PR_TYPE tp_Set = {
"set", DB_TYPE_SET, 1, sizeof (SETOBJ *), 0, 4,
mr_initmem_set,
mr_initval_set,
mr_setmem_set,
mr_getmem_set,
mr_setval_set,
mr_data_lengthmem_set,
mr_data_lengthval_set,
mr_data_writemem_set,
mr_data_readmem_set,
mr_data_writeval_set,
mr_data_readval_set,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_set,
mr_data_cmpdisk_set,
mr_cmpval_set
};
const PR_TYPE *tp_Type_set = &tp_Set;
const PR_TYPE tp_Multiset = {
"multiset", DB_TYPE_MULTISET, 1, sizeof (SETOBJ *), 0, 4,
mr_initmem_set,
mr_initval_multiset,
mr_setmem_set,
mr_getmem_multiset,
mr_setval_multiset,
mr_data_lengthmem_set,
mr_data_lengthval_set,
mr_data_writemem_set,
mr_data_readmem_set,
mr_data_writeval_set,
mr_data_readval_set,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_set,
mr_data_cmpdisk_set,
mr_cmpval_set
};
const PR_TYPE *tp_Type_multiset = &tp_Multiset;
const PR_TYPE tp_Sequence = {
"sequence", DB_TYPE_SEQUENCE, 1, sizeof (SETOBJ *), 0, 4,
mr_initmem_set,
mr_initval_sequence,
mr_setmem_set,
mr_getmem_sequence,
mr_setval_sequence,
mr_data_lengthmem_set,
mr_data_lengthval_set,
mr_data_writemem_set,
mr_data_readmem_set,
mr_data_writeval_set,
mr_data_readval_set,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_set,
mr_data_cmpdisk_sequence,
mr_cmpval_sequence
};
const PR_TYPE *tp_Type_sequence = &tp_Sequence;
const PR_TYPE tp_Midxkey = {
"midxkey", DB_TYPE_MIDXKEY, 1, 0, 0, 1,
NULL, /* initmem */
mr_initval_midxkey,
NULL, /* setmem */
NULL, /* getmem_midxkey */
mr_setval_midxkey,
mr_data_lengthmem_midxkey,
mr_data_lengthval_midxkey,
NULL, /* data_writemem */
NULL, /* data_readmem */
mr_data_writeval_midxkey,
mr_data_readval_midxkey,
mr_index_lengthmem_midxkey,
mr_index_lengthval_midxkey,
mr_index_writeval_midxkey,
mr_index_readval_midxkey,
mr_index_cmpdisk_midxkey,
NULL, /* freemem */
mr_data_cmpdisk_midxkey,
mr_cmpval_midxkey
};
const PR_TYPE *tp_Type_midxkey = &tp_Midxkey;
const PR_TYPE tp_Vobj = {
"*vobj*", DB_TYPE_VOBJ, 1, sizeof (SETOBJ *), 0, 8,
mr_initmem_set,
mr_initval_vobj,
mr_setmem_set,
mr_getmem_sequence,
mr_setval_vobj,
mr_data_lengthmem_set,
mr_data_lengthval_set,
mr_data_writemem_set,
mr_data_readmem_set,
mr_data_writeval_set,
mr_data_readval_vobj,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_set,
mr_data_cmpdisk_vobj,
mr_cmpval_vobj
};
const PR_TYPE *tp_Type_vobj = &tp_Vobj;
const PR_TYPE tp_Numeric = {
"numeric", DB_TYPE_NUMERIC, 0, 0, 0, 1,
mr_initmem_numeric,
mr_initval_numeric,
mr_setmem_numeric,
mr_getmem_numeric,
mr_setval_numeric,
mr_data_lengthmem_numeric,
mr_data_lengthval_numeric,
mr_data_writemem_numeric,
mr_data_readmem_numeric,
mr_data_writeval_numeric,
mr_data_readval_numeric,
mr_index_lengthmem_numeric,
mr_index_lengthval_numeric,
mr_index_writeval_numeric,
mr_index_readval_numeric,
mr_index_cmpdisk_numeric,
NULL, /* freemem */
mr_data_cmpdisk_numeric,
mr_cmpval_numeric
};
const PR_TYPE *tp_Type_numeric = &tp_Numeric;
const PR_TYPE tp_Enumeration = {
"enum", DB_TYPE_ENUMERATION, 0, sizeof (unsigned short), sizeof (unsigned short), sizeof (unsigned short),
mr_initmem_enumeration,
mr_initval_enumeration,
mr_setmem_enumeration,
mr_getmem_enumeration,
mr_setval_enumeration,
NULL, /* use disksize */
NULL, /* use_disksize */
mr_data_writemem_enumeration,
mr_data_readmem_enumeration,
mr_data_writeval_enumeration,
mr_data_readval_enumeration,
NULL, /* use disksize */
NULL, /* use disksize */
mr_index_writeval_enumeration,
mr_index_readval_enumeration,
mr_index_cmpdisk_enumeration,
NULL, /* free mem not deeded for short */
mr_data_cmpdisk_enumeration,
mr_cmpval_enumeration
};
const PR_TYPE *tp_Type_enumeration = &tp_Enumeration;
/*
* tp_Type_id_map
* This quickly maps a type identifier to a type structure.
* This is dependent on the ordering of the DB_TYPE union so take
* care when modifying either of these. It would be safer to build
* this at run time.
*/
#define tp_NChar tp_Char
#define tp_VarNChar tp_String
const PR_TYPE *tp_Type_id_map[] = {
&tp_Null,
&tp_Integer,
&tp_Float,
&tp_Double,
&tp_String,
&tp_Object,
&tp_Set,
&tp_Multiset,
&tp_Sequence,
&tp_Elo,
&tp_Time,
&tp_Utime,
&tp_Date,
&tp_Monetary,
&tp_Variable,
&tp_Substructure,
&tp_Pointer,
&tp_Error,
&tp_Short,
&tp_Vobj,
&tp_Oid,
&tp_Null, /* place holder for DB_TYPE_DB_VALUE */
&tp_Numeric,
&tp_Bit,
&tp_VarBit,
&tp_Char,
/* TODO:
* DB_TYPE_NCHAR and DB_TYPE_VARNCHAR will no longer be used(NCHAR was deprecated).
* However, to maintain compatibility with previous versions, the enum list will be preserved.
*/
&tp_NChar,
&tp_VarNChar,
&tp_ResultSet,
&tp_Midxkey,
&tp_Null,
&tp_Bigint,
&tp_Datetime,
&tp_Blob,
&tp_Clob,
&tp_Enumeration,
&tp_Timestamptz,
&tp_Timestampltz,
&tp_Datetimetz,
&tp_Datetimeltz,
&tp_Json,
};
const PR_TYPE tp_ResultSet = {
"resultset", DB_TYPE_RESULTSET, 0, sizeof (DB_RESULTSET), sizeof (DB_RESULTSET), 4,
mr_initmem_resultset,
mr_initval_resultset,
mr_setmem_resultset,
mr_getmem_resultset,
mr_setval_resultset,
NULL, /* data_lengthmem */
NULL, /* data_lengthval */
mr_data_writemem_resultset,
mr_data_readmem_resultset,
mr_data_writeval_resultset,
mr_data_readval_resultset,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
NULL, /* freemem */
mr_data_cmpdisk_resultset,
mr_cmpval_resultset
};
const PR_TYPE *tp_Type_resultset = &tp_ResultSet;
/*
* DB_VALUE MAINTENANCE
*/
/*
* pr_area_init - Initialize the area for allocation of value containers.
* return: NO_ERROR or error code.
* Note:
* This must be called at a suitable point in system initialization.
*/
int
pr_area_init (void)
{
Value_area = area_create ("Value containers", sizeof (DB_VALUE), VALUE_AREA_COUNT);
if (Value_area == NULL)
{
assert (er_errid () != NO_ERROR);
return er_errid ();
}
return NO_ERROR;
}
/*
* pr_area_final - Finalize the area for allocation of value containers.
* return: none.
*/
void
pr_area_final (void)
{
if (Value_area != NULL)
{
area_destroy (Value_area);
Value_area = NULL;
}
}
/*
* pr_make_value - create an internal value container
* return: new value container
* Note:
* The value is allocated within the main workspace blocks so that
* it will not serve as a root for the garbage collector.
*/
DB_VALUE *
pr_make_value (void)
{
DB_VALUE *value;
value = (DB_VALUE *) db_private_alloc (NULL, sizeof (DB_VALUE));
if (value != NULL)
{
db_value_domain_init (value, DB_TYPE_NULL, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
return value;
}
/*
* pr_make_ext_value - creates an external value container suitable for
* passing beyond the interface layer to application programs.
* return: new value container
* Note:
* It is allocated in the special Value_area so that it will serve as
* a root to the garbage collector if the value contains a MOP.
*/
DB_VALUE *
pr_make_ext_value (void)
{
DB_VALUE *value;
value = (DB_VALUE *) area_alloc (Value_area);
if (value != NULL)
{
db_value_domain_init (value, DB_TYPE_NULL, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
return value;
}
/*
* pr_clear_value - clear an internal or external DB_VALUE and
* initialize it to the NULL state.
* return: NO_ERROR
* value(in/out): value to initialize
* Note:
* Any external allocations (strings, sets, etc) will be freed.
*
* There is too much type specific stuff in here. We need to create a
* "freeval" type vector function to do this work.
*/
int
pr_clear_value (DB_VALUE * value)
{
char *midxkey_buf = NULL;
const char *char_medium_buf = NULL;
bool need_clear;
DB_TYPE db_type;
static bool oracle_style_empty_string = prm_get_bool_value (PRM_ID_ORACLE_STYLE_EMPTY_STRING);
if (value == NULL)
{
return NO_ERROR; /* do nothing */
}
db_type = DB_VALUE_DOMAIN_TYPE (value);
need_clear = true;
if (DB_IS_NULL (value))
{
need_clear = false;
if (value->need_clear)
{
if (oracle_style_empty_string)
{ /* need to check */
if ((QSTR_IS_ANY_CHAR_OR_BIT (db_type) && value->data.ch.medium.buf != NULL)
|| db_type == DB_TYPE_ENUMERATION)
{
need_clear = true; /* need to free Empty-string */
}
}
}
}
if (need_clear == false)
{
return NO_ERROR; /* do nothing */
}
switch (db_type)
{
case DB_TYPE_JSON:
if (value->need_clear)
{
if (value->data.json.document != NULL)
{
db_json_delete_doc (value->data.json.document);
value->data.json.document = NULL;
}
if (value->data.json.schema_raw != NULL)
{
db_private_free (NULL, const_cast < char *>(value->data.json.schema_raw));
value->data.json.schema_raw = NULL;
}
}
else
{
value->data.json.document = NULL;
value->data.json.schema_raw = NULL;
}
break;
case DB_TYPE_OBJECT:
/* we need to be sure to NULL the object pointer so that this db_value does not cause garbage collection problems
* by retaining an object pointer. */
value->data.op = NULL;
break;
case DB_TYPE_SET:
case DB_TYPE_MULTISET:
case DB_TYPE_SEQUENCE:
case DB_TYPE_VOBJ:
set_free (db_get_set (value));
value->data.set = NULL;
break;
case DB_TYPE_MIDXKEY:
midxkey_buf = value->data.midxkey.buf;
if (midxkey_buf != NULL)
{
if (value->need_clear)
{
db_private_free_and_init (NULL, midxkey_buf);
}
/*
* Ack, phfffft!!! why should we have to know about the
* internals here?
*/
value->data.midxkey.buf = NULL;
}
break;
case DB_TYPE_VARCHAR:
case DB_TYPE_CHAR:
case DB_TYPE_BIT:
case DB_TYPE_VARBIT:
char_medium_buf = value->data.ch.medium.buf;
if (char_medium_buf != NULL)
{
if (value->need_clear)
{
// here is safe to const_cast since the ownership was handed over by setting need_clear flag to true
char *temp = CONST_CAST (char *, char_medium_buf);
db_private_free_and_init (NULL, temp);
}
/*
* Ack, phfffft!!! why should we have to know about the
* internals here?
*/
value->data.ch.medium.buf = NULL;
}
/* Clear the compressed string since we are here for DB_TYPE_VARCHAR. */
if (db_type == DB_TYPE_VARCHAR)
{
char *compressed_str = DB_GET_COMPRESSED_STRING (value);
if (compressed_str != NULL)
{
if (value->data.ch.info.compressed_need_clear != 0)
{
// here is safe to const_cast since the ownership was handed over by setting need_clear flag to true
db_private_free_and_init (NULL, compressed_str);
}
}
db_set_compressed_string (value, NULL, DB_NOT_YET_COMPRESSED, false);
}
else if (db_type == DB_TYPE_CHAR)
{
assert (value->data.ch.info.compressed_need_clear == 0);
char *compressed_str = value->data.ch.medium.compressed_buf;
if (compressed_str != NULL)
{
if (value->data.ch.info.compressed_need_clear != 0)
{
db_private_free_and_init (NULL, compressed_str);
}
}
}
break;
case DB_TYPE_BLOB:
case DB_TYPE_CLOB:
if (value->need_clear)
{
elo_free_structure (db_get_elo (value));
}
break;
case DB_TYPE_ENUMERATION:
if (value->need_clear)
{
// here is safe to const_cast since the ownership was handed over by setting need_clear flag to true
char *temp = CONST_CAST (char *, db_get_enum_string (value));
if (temp != NULL)
{
db_private_free_and_init (NULL, temp);
}
}
db_make_enumeration (value, 0, NULL, 0, db_get_enum_codeset (value), db_get_enum_collation (value));
break;
default:
break;
}
/* always make sure the value gets cleared */
PRIM_SET_NULL (value);
value->need_clear = false;
return NO_ERROR;
}
/*
* pr_clear_value_vector - clear a vector of db_values
* references
* return: void
* value(in/out): vector of values
*/
/* *INDENT-OFF* */
void
pr_clear_value_vector (std::vector<DB_VALUE> &value_vector)
{
for (DB_VALUE &dbval : value_vector)
{
pr_clear_value (&dbval);
}
}
/* *INDENT-ON* */
/*
* pr_free_value - free an internval value container any anything that it
* references
* return: NO_ERROR if successful, error code otherwise
* value(in/out): value to clear & free
*/
int
pr_free_value (DB_VALUE * value)
{
int error = NO_ERROR;
if (value != NULL)
{
/* some redundant checking but I want the semantics isolated */
error = pr_clear_value (value);
db_private_free_and_init (NULL, value);
}
return error;
}
/*
* pr_free_ext_value - free an external value container and anything that it
* references.
* return:
* value(in/out): external value to clear & free
* Note:
* Identical to pr_free_value except that it frees the value to the
* Value_area instead of to the workspace.
*/
int
pr_free_ext_value (DB_VALUE * value)
{
int error = NO_ERROR;
if (value != NULL)
{
/* some redundant checking but I want the semantics isolated */
error = pr_clear_value (value);
(void) area_free (Value_area, (void *) value);
}
return error;
}
/*
* pr_clone_value - copy the contents of one value container to another.
* return: none
* src(in): source value
* dest(out): destination value
* Note:
* For types that contain external allocations (like strings).
* The contents are copied.
*/
int
pr_clone_value (const DB_VALUE * src, DB_VALUE * dest)
{
const PR_TYPE *type;
DB_TYPE src_dbtype;
if (dest != NULL)
{
if (src == NULL)
{
db_make_null (dest);
}
else
{
src_dbtype = DB_VALUE_DOMAIN_TYPE (src);
if (DB_IS_NULL (src))
{
db_value_domain_init (dest, src_dbtype, DB_VALUE_PRECISION (src), DB_VALUE_SCALE (src));
}
else if (src != dest)
{
type = pr_type_from_id (src_dbtype);
if (type != NULL)
{
/*
* Formerly called "initval" here but that was removed as
* "setval" is supposed to properly initialize the
* destination domain. No need to do it twice.
* Make sure the COPY flag is set in the setval call.
*/
type->setval (dest, src, true);
}
else
{
/*
* can only get here in error conditions, initialize to NULL
*/
db_make_null (dest);
}
}
}
}
return NO_ERROR;
}
/*
* pr_copy_value - This creates a new internal value container with a copy
* of the contents of the source container.
* return: new value
* value(in): value to copy
*/
DB_VALUE *
pr_copy_value (DB_VALUE * value)
{
DB_VALUE *new_ = NULL;
if (value != NULL)
{
new_ = pr_make_value ();
if (pr_clone_value (value, new_) != NO_ERROR)
{
/*
* oh well, couldn't allocate storage for the clone.
* Note that pr_free_value can only return errors in the
* case where the value has been initialized so it won't
* stomp on the error code if we call it here
*/
pr_free_value (new_);
new_ = NULL;
}
}
return new_;
}
/*
* TYPE NULL
*/
/*
* This is largely a placeholder type that does nothing except assert
* that the size of a NULL value is zero.
* The "mem" functions are no-ops since NULL is not a valid domain type.
* The "value" functions don't do much, they just make sure the value
* domain is initialized.
*
*/
/*
* mr_initmem_null - dummy function
* return:
* memptr():
*/
static void
mr_initmem_null (void *memptr, TP_DOMAIN * domain)
{
}
/*
* mr_setmem_null - dummy function
* return:
* memptr():
* domain():
* value():
*/
static int
mr_setmem_null (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
return NO_ERROR;
}
/*
* mr_getmem_null - dummy function
* return:
* memptr():
* domain():
* value():
* copy():
*/
static int
mr_getmem_null (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
db_make_null (value);
return NO_ERROR;
}
/*
* mr_writemem_null - dummy function
* return:
* buf():
* memptr():
* domain():
*/
static void
mr_data_writemem_null (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
}
/*
* mr_readmem_null - dummy function
* return:
* buf():
* memptr():
* domain():
* size():
*/
static void
mr_data_readmem_null (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
}
static void
mr_initval_null (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_NULL, precision, scale);
}
/*
* mr_setval_null - dummy function
* return:
* dest():
* src():
* copy():
*/
static int
mr_setval_null (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
mr_initval_null (dest, 0, 0);
return NO_ERROR;
}
/*
* mr_writeval_null - dummy function
* return:
* buf():
* value():
*/
static int
mr_data_writeval_null (OR_BUF * buf, DB_VALUE * value)
{
return NO_ERROR;
}
/*
* mr_readval_null - dummy function
* return:
* buf():
* value():
* domain():
* size():
* copy():
* copy_buf():
* copy_buf_len():
*/
static int
mr_data_readval_null (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
if (value)
{
db_make_null (value);
value->need_clear = false;
}
return NO_ERROR;
}
/*
* mr_cmpdisk_null - dummy function
* return:
* mem1():
* mem2():
* domain():
* do_coercion():
* total_order():
* start_colp():
*/
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_null (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return DB_UNK;
}
/*
* mr_cmpval_null - dummy function
* return:
* value1():
* value2():
* do_coercion():
* total_order():
* start_colp():
*/
static DB_VALUE_COMPARE_RESULT
mr_cmpval_null (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
return DB_UNK;
}
/*
* TYPE INTEGER
*
* Your basic 32 bit signed integral value.
* At the storage level, we don't really care whether it is signed or unsigned.
*/
static void
mr_initmem_int (void *mem, TP_DOMAIN * domain)
{
*(int *) mem = 0;
}
static int
mr_setmem_int (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value != NULL)
*(int *) mem = db_get_int (value);
else
mr_initmem_int (mem, domain);
return NO_ERROR;
}
static int
mr_getmem_int (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_int (value, *(int *) mem);
}
static void
mr_data_writemem_int (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_int (buf, *(int *) mem);
}
static void
mr_data_readmem_int (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Integer.disksize);
}
else
{
*(int *) mem = or_get_int (buf, &rc);
}
}
static void
mr_initval_int (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_INTEGER, precision, scale);
db_make_int (value, 0);
}
static int
mr_setval_int (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_int (dest, db_get_int (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_INTEGER, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_int (OR_BUF * buf, DB_VALUE * value)
{
return or_put_int (buf, db_get_int (value));
}
static int
mr_data_readval_int (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int temp_int, rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Integer.disksize);
}
else
{
temp_int = or_get_int (buf, &rc);
if (rc == NO_ERROR)
{
db_make_int (value, temp_int);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_int (OR_BUF * buf, DB_VALUE * value)
{
int i;
i = db_get_int (value);
return or_put_data (buf, (char *) (&i), tp_Integer.disksize);
}
static int
mr_index_readval_int (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int i, rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Integer.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&i), tp_Integer.disksize);
if (rc == NO_ERROR)
{
db_make_int (value, i);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_int (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
int i1, i2;
assert (domain != NULL);
COPYMEM (int, &i1, mem1);
COPYMEM (int, &i2, mem2);
return MR_CMP (i1, i2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_int (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
int i1, i2;
assert (domain != NULL);
i1 = OR_GET_INT (mem1);
i2 = OR_GET_INT (mem2);
return MR_CMP (i1, i2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_int (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
int i1, i2;
i1 = db_get_int (value1);
i2 = db_get_int (value2);
return MR_CMP (i1, i2);
}
/*
* TYPE SHORT
*
* Your basic 16 bit signed integral value.
*/
static void
mr_initmem_short (void *mem, TP_DOMAIN * domain)
{
*(short *) mem = 0;
}
static int
mr_setmem_short (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
mr_initmem_short (mem, domain);
else
*(short *) mem = db_get_short (value);
return NO_ERROR;
}
static int
mr_getmem_short (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_short (value, *(short *) mem);
}
static void
mr_data_writemem_short (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
short *mem = (short *) memptr;
or_put_short (buf, *mem);
}
static void
mr_data_readmem_short (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Short.disksize);
}
else
{
*(short *) mem = or_get_short (buf, &rc);
}
}
static void
mr_initval_short (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_SHORT, precision, scale);
db_make_short (value, 0);
}
static int
mr_setval_short (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_short (dest, db_get_short (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_SHORT, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_short (OR_BUF * buf, DB_VALUE * value)
{
return or_put_short (buf, db_get_short (value));
}
static int
mr_data_readval_short (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
short s;
if (value == NULL)
{
rc = or_advance (buf, tp_Short.disksize);
}
else
{
s = (short) or_get_short (buf, &rc);
if (rc == NO_ERROR)
{
db_make_short (value, s);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_short (OR_BUF * buf, DB_VALUE * value)
{
short s;
s = db_get_short (value);
return or_put_data (buf, (char *) (&s), tp_Short.disksize);
}
static int
mr_index_readval_short (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
short s;
if (value == NULL)
{
rc = or_advance (buf, tp_Short.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&s), tp_Short.disksize);
if (rc == NO_ERROR)
{
db_make_short (value, s);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_short (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
short s1, s2;
assert (domain != NULL);
COPYMEM (short, &s1, mem1);
COPYMEM (short, &s2, mem2);
return MR_CMP (s1, s2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_short (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
short s1, s2;
assert (domain != NULL);
s1 = OR_GET_SHORT (mem1);
s2 = OR_GET_SHORT (mem2);
return MR_CMP (s1, s2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_short (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
short s1, s2;
s1 = db_get_short (value1);
s2 = db_get_short (value2);
return MR_CMP (s1, s2);
}
/*
* TYPE BIGINT
*
* Your basic 64 bit signed integral value.
* At the storage level, we don't really care whether it is signed or unsigned.
*/
static void
mr_initmem_bigint (void *mem, TP_DOMAIN * domain)
{
*(DB_BIGINT *) mem = 0;
}
static int
mr_setmem_bigint (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value != NULL)
*(DB_BIGINT *) mem = db_get_bigint (value);
else
mr_initmem_bigint (mem, domain);
return NO_ERROR;
}
static int
mr_getmem_bigint (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_bigint (value, *(DB_BIGINT *) mem);
}
static void
mr_data_writemem_bigint (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_bigint (buf, *(DB_BIGINT *) mem);
}
static void
mr_data_readmem_bigint (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Bigint.disksize);
}
else
{
*(DB_BIGINT *) mem = or_get_bigint (buf, &rc);
}
}
static void
mr_initval_bigint (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_BIGINT, precision, scale);
db_make_bigint (value, 0);
}
static int
mr_setval_bigint (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_bigint (dest, db_get_bigint (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_BIGINT, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_bigint (OR_BUF * buf, DB_VALUE * value)
{
return or_put_bigint (buf, db_get_bigint (value));
}
static int
mr_data_readval_bigint (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
DB_BIGINT temp_int;
if (value == NULL)
{
rc = or_advance (buf, tp_Bigint.disksize);
}
else
{
temp_int = or_get_bigint (buf, &rc);
if (rc == NO_ERROR)
{
db_make_bigint (value, temp_int);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_bigint (OR_BUF * buf, DB_VALUE * value)
{
DB_BIGINT bi;
bi = db_get_bigint (value);
return or_put_data (buf, (char *) (&bi), tp_Bigint.disksize);
}
static int
mr_index_readval_bigint (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
DB_BIGINT bi;
if (value == NULL)
{
rc = or_advance (buf, tp_Bigint.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&bi), tp_Bigint.disksize);
if (rc == NO_ERROR)
{
db_make_bigint (value, bi);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_bigint (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_BIGINT i1, i2;
assert (domain != NULL);
COPYMEM (DB_BIGINT, &i1, mem1);
COPYMEM (DB_BIGINT, &i2, mem2);
return MR_CMP (i1, i2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_bigint (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_BIGINT i1, i2;
assert (domain != NULL);
OR_GET_BIGINT (mem1, &i1);
OR_GET_BIGINT (mem2, &i2);
return MR_CMP (i1, i2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_bigint (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_BIGINT i1, i2;
i1 = db_get_bigint (value1);
i2 = db_get_bigint (value2);
return MR_CMP (i1, i2);
}
/*
* TYPE FLOAT
*
* IEEE single precision floating point values.
*/
static void
mr_initmem_float (void *mem, TP_DOMAIN * domain)
{
*(float *) mem = 0.0;
}
static int
mr_setmem_float (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
{
mr_initmem_float (mem, domain);
}
else
{
*(float *) mem = db_get_float (value);
}
return NO_ERROR;
}
static int
mr_getmem_float (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_float (value, *(float *) mem);
}
static void
mr_data_writemem_float (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_float (buf, *(float *) mem);
}
static void
mr_data_readmem_float (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Float.disksize);
}
else
{
*(float *) mem = or_get_float (buf, &rc);
}
}
static void
mr_initval_float (DB_VALUE * value, int precision, int scale)
{
db_make_float (value, 0.0);
value->need_clear = false;
}
static int
mr_setval_float (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_float (dest, db_get_float (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_FLOAT, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_float (OR_BUF * buf, DB_VALUE * value)
{
return or_put_float (buf, db_get_float (value));
}
static int
mr_data_readval_float (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
float temp;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Float.disksize);
}
else
{
temp = or_get_float (buf, &rc);
if (rc == NO_ERROR)
{
db_make_float (value, temp);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_float (OR_BUF * buf, DB_VALUE * value)
{
float f;
f = db_get_float (value);
return or_put_data (buf, (char *) (&f), tp_Float.disksize);
}
static int
mr_index_readval_float (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
float f;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Float.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&f), tp_Float.disksize);
if (rc == NO_ERROR)
{
db_make_float (value, f);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_float (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
float f1, f2;
assert (domain != NULL);
COPYMEM (float, &f1, mem1);
COPYMEM (float, &f2, mem2);
return MR_CMP (f1, f2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_float (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
float f1, f2;
assert (domain != NULL);
OR_GET_FLOAT (mem1, &f1);
OR_GET_FLOAT (mem2, &f2);
return MR_CMP (f1, f2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_float (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
float f1, f2;
f1 = db_get_float (value1);
f2 = db_get_float (value2);
return MR_CMP (f1, f2);
}
/*
* TYPE DOUBLE
*
* IEEE double precision floating vlaues.
* Remember the pointer here isn't necessarily valid as a "double*"
* because the value may be packed into the object such that it
* doesn't fall on a double word boundary.
*
*/
static void
mr_initmem_double (void *mem, TP_DOMAIN * domain)
{
double d = 0.0;
OR_MOVE_DOUBLE (&d, mem);
}
static int
mr_setmem_double (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
double d;
if (value == NULL)
{
mr_initmem_double (mem, domain);
}
else
{
d = db_get_double (value);
OR_MOVE_DOUBLE (&d, mem);
}
return NO_ERROR;
}
static int
mr_getmem_double (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
double d = 0;
OR_MOVE_DOUBLE (mem, &d);
return db_make_double (value, d);
}
static void
mr_data_writemem_double (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
double d = 0;
OR_MOVE_DOUBLE (mem, &d);
or_put_double (buf, d);
}
static void
mr_data_readmem_double (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
double d;
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Double.disksize);
}
else
{
d = or_get_double (buf, &rc);
OR_MOVE_DOUBLE (&d, mem);
}
}
static void
mr_initval_double (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_DOUBLE, precision, scale);
db_make_double (value, 0.0);
}
static int
mr_setval_double (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_double (dest, db_get_double (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_DOUBLE, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_double (OR_BUF * buf, DB_VALUE * value)
{
return or_put_double (buf, db_get_double (value));
}
static int
mr_data_readval_double (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
double temp;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Double.disksize);
}
else
{
temp = or_get_double (buf, &rc);
if (rc == NO_ERROR)
{
db_make_double (value, temp);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_double (OR_BUF * buf, DB_VALUE * value)
{
double d;
d = db_get_double (value);
return or_put_data (buf, (char *) (&d), tp_Double.disksize);
}
static int
mr_index_readval_double (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
double d;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Double.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&d), tp_Double.disksize);
if (rc == NO_ERROR)
{
db_make_double (value, d);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_double (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
double d1, d2;
assert (domain != NULL);
COPYMEM (double, &d1, mem1);
COPYMEM (double, &d2, mem2);
return MR_CMP (d1, d2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_double (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
double d1, d2;
assert (domain != NULL);
OR_GET_DOUBLE (mem1, &d1);
OR_GET_DOUBLE (mem2, &d2);
return MR_CMP (d1, d2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_double (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
double d1, d2;
d1 = db_get_double (value1);
d2 = db_get_double (value2);
return MR_CMP (d1, d2);
}
/*
* TYPE TIME
*
* 32 bit seconds counter. Interpreted as an offset within a given day.
* Probably not general enough currently to be used an an interval type?
*
*/
static void
mr_initmem_time (void *mem, TP_DOMAIN * domain)
{
*(DB_TIME *) mem = 0;
}
static int
mr_setmem_time (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
mr_initmem_time (mem, domain);
else
*(DB_TIME *) mem = *db_get_time (value);
return NO_ERROR;
}
static int
mr_getmem_time (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
(void) db_value_put_encoded_time (value, (DB_TIME *) mem);
value->need_clear = false;
return NO_ERROR;
}
static void
mr_data_writemem_time (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_time (buf, (DB_TIME *) mem);
}
static void
mr_data_readmem_time (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Time.disksize);
}
else
{
or_get_time (buf, (DB_TIME *) mem);
}
}
static void
mr_initval_time (DB_VALUE * value, int precision, int scale)
{
DB_TIME tm = 0;
db_value_put_encoded_time (value, &tm);
value->need_clear = false;
}
static int
mr_setval_time (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_TIME, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_value_put_encoded_time (dest, db_get_time (src));
}
return error;
}
static int
mr_data_writeval_time (OR_BUF * buf, DB_VALUE * value)
{
return or_put_time (buf, db_get_time (value));
}
static int
mr_data_readval_time (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_TIME tm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Time.disksize);
}
else
{
rc = or_get_time (buf, &tm);
if (rc == NO_ERROR)
{
db_value_put_encoded_time (value, &tm);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_time (OR_BUF * buf, DB_VALUE * value)
{
DB_TIME *tm;
tm = db_get_time (value);
return or_put_data (buf, (char *) tm, tp_Time.disksize);
}
static int
mr_index_readval_time (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_TIME tm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Time.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&tm), tp_Time.disksize);
if (rc == NO_ERROR)
{
db_value_put_encoded_time (value, &tm);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_time (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_TIME t1, t2;
assert (domain != NULL);
COPYMEM (DB_TIME, &t1, mem1);
COPYMEM (DB_TIME, &t2, mem2);
return MR_CMP (t1, t2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_time (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_TIME t1, t2;
assert (domain != NULL);
OR_GET_TIME (mem1, &t1);
OR_GET_TIME (mem2, &t2);
return MR_CMP (t1, t2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_time (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
const DB_TIME *t1, *t2;
t1 = db_get_time (value1);
t2 = db_get_time (value2);
return MR_CMP (*t1, *t2);
}
/*
* TYPE UTIME
*
* "Universal" time, more recently known as a "timestamp".
* These are 32 bit encoded values that contain both a date and time
* identification.
* The encoding is the standard Unix "time_t" format.
*/
static void
mr_initmem_utime (void *mem, TP_DOMAIN * domain)
{
*(DB_UTIME *) mem = 0;
}
static int
mr_setmem_utime (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
mr_initmem_utime (mem, domain);
else
*(DB_UTIME *) mem = *db_get_timestamp (value);
return NO_ERROR;
}
static int
mr_getmem_utime (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error;
error = db_make_utime (value, *(DB_UTIME *) mem);
value->need_clear = false;
return error;
}
static int
mr_getmem_timestampltz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error;
error = db_make_timestampltz (value, *(DB_UTIME *) mem);
value->need_clear = false;
return error;
}
static void
mr_data_writemem_utime (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_utime (buf, (DB_UTIME *) mem);
}
static void
mr_data_readmem_utime (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Utime.disksize);
}
else
{
or_get_utime (buf, (DB_UTIME *) mem);
}
}
static void
mr_initval_utime (DB_VALUE * value, int precision, int scale)
{
db_make_utime (value, 0);
value->need_clear = false;
}
static void
mr_initval_timestampltz (DB_VALUE * value, int precision, int scale)
{
db_make_timestampltz (value, 0);
value->need_clear = false;
}
static int
mr_setval_utime (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_TIMESTAMP, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_utime (dest, *db_get_timestamp (src));
}
return error;
}
static int
mr_setval_timestampltz (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_TIMESTAMPLTZ, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_timestampltz (dest, *db_get_timestamp (src));
}
return error;
}
static int
mr_data_writeval_utime (OR_BUF * buf, DB_VALUE * value)
{
return or_put_utime (buf, db_get_timestamp (value));
}
static int
mr_data_readval_utime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_UTIME utm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Utime.disksize);
}
else
{
rc = or_get_utime (buf, &utm);
if (rc == NO_ERROR)
{
db_make_utime (value, utm);
}
value->need_clear = false;
}
return rc;
}
static int
mr_data_readval_timestampltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_UTIME utm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Timestampltz.disksize);
}
else
{
rc = or_get_utime (buf, &utm);
db_make_timestampltz (value, utm);
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_utime (OR_BUF * buf, DB_VALUE * value)
{
DB_UTIME *utm;
utm = db_get_timestamp (value);
return or_put_data (buf, (char *) utm, tp_Utime.disksize);
}
static int
mr_index_readval_utime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_UTIME utm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Utime.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&utm), tp_Utime.disksize);
if (rc == NO_ERROR)
{
db_make_utime (value, utm);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_readval_timestampltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_UTIME utm;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Timestampltz.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&utm), tp_Timestampltz.disksize);
if (rc == NO_ERROR)
{
db_make_timestampltz (value, utm);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_utime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_UTIME utm1, utm2;
assert (domain != NULL);
COPYMEM (DB_UTIME, &utm1, mem1);
COPYMEM (DB_UTIME, &utm2, mem2);
return MR_CMP (utm1, utm2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_utime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_TIMESTAMP ts1, ts2;
assert (domain != NULL);
OR_GET_UTIME (mem1, &ts1);
OR_GET_UTIME (mem2, &ts2);
return MR_CMP (ts1, ts2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_utime (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
const DB_TIMESTAMP *ts1, *ts2;
ts1 = db_get_timestamp (value1);
ts2 = db_get_timestamp (value2);
return MR_CMP (*ts1, *ts2);
}
/*
* TYPE TIMESTAMPTZ
*
* This stores a TIMESTAMP and a zone identifier
* The requirement is 4 (TIMESTAMP) + 2 bytes (zone id)
* The encoding of TIMESTAMP is the standard Unix "time_t" format.
*/
static void
mr_initmem_timestamptz (void *mem, TP_DOMAIN * domain)
{
DB_TIMESTAMPTZ *ts_tz = (DB_TIMESTAMPTZ *) mem;
ts_tz->timestamp = 0;
ts_tz->tz_id = 0;
}
static int
mr_setmem_timestamptz (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
{
mr_initmem_timestamptz (mem, domain);
}
else
{
*(DB_TIMESTAMPTZ *) mem = *db_get_timestamptz (value);
}
return NO_ERROR;
}
static int
mr_getmem_timestamptz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error;
error = db_make_timestamptz (value, (DB_TIMESTAMPTZ *) mem);
return error;
}
static void
mr_data_writemem_timestamptz (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_timestamptz (buf, (DB_TIMESTAMPTZ *) mem);
}
static void
mr_data_readmem_timestamptz (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Timestamptz.disksize);
}
else
{
or_get_timestamptz (buf, (DB_TIMESTAMPTZ *) mem);
}
}
static void
mr_initval_timestamptz (DB_VALUE * value, int precision, int scale)
{
DB_TIMESTAMPTZ ts_tz;
mr_initmem_timestamptz (&ts_tz, NULL);
db_make_timestamptz (value, &ts_tz);
}
static int
mr_setval_timestamptz (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_TIMESTAMPTZ, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_timestamptz (dest, db_get_timestamptz (src));
}
return error;
}
static int
mr_data_writeval_timestamptz (OR_BUF * buf, DB_VALUE * value)
{
return or_put_timestamptz (buf, db_get_timestamptz (value));
}
static int
mr_data_readval_timestamptz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_TIMESTAMPTZ ts_tz;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Timestamptz.disksize);
}
else
{
rc = or_get_timestamptz (buf, &ts_tz);
db_make_timestamptz (value, &ts_tz);
}
return rc;
}
static int
mr_index_writeval_timestamptz (OR_BUF * buf, DB_VALUE * value)
{
DB_TIMESTAMPTZ *ts_tz;
int rc = NO_ERROR;
ts_tz = db_get_timestamptz (value);
assert (tp_Timestamptz.disksize == (tp_Utime.disksize + tp_Integer.disksize));
rc = or_put_data (buf, (char *) (&ts_tz->timestamp), tp_Utime.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&ts_tz->tz_id), tp_Integer.disksize);
}
return rc;
}
static int
mr_index_readval_timestamptz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_TIMESTAMPTZ ts_tz;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Timestamptz.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&ts_tz), tp_Timestamptz.disksize);
if (rc == NO_ERROR)
{
db_make_timestamptz (value, &ts_tz);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_timestamptz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
DB_UTIME utm1, utm2;
assert (domain != NULL);
/* TIMESTAMP with TZ compares the same as TIMESTAMP (zone is not taken into account) */
COPYMEM (DB_UTIME, &utm1, mem1);
COPYMEM (DB_UTIME, &utm2, mem2);
return MR_CMP (utm1, utm2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_timestamptz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
DB_TIMESTAMP ts1, ts2;
assert (domain != NULL);
/* TIMESTAMP with TZ compares the same as TIMESTAMP (zone is not taken into account) */
OR_GET_UTIME (mem1, &ts1);
OR_GET_UTIME (mem2, &ts2);
return MR_CMP (ts1, ts2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_timestamptz (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
const DB_TIMESTAMPTZ *ts_tz1, *ts_tz2;
/* TIMESTAMP with TZ compares the same as TIMESTAMP (zone is not taken into account); the first component of
* TIMESTAMPTZ is a TIMESTAMP, it is safe to use the TIMESTAMP part of DB_DATA union to read it */
ts_tz1 = db_get_timestamptz (value1);
ts_tz2 = db_get_timestamptz (value2);
#if defined (SA_MODE)
if (tz_Compare_timestamptz_tz_id == true && ts_tz1->tz_id != ts_tz2->tz_id)
{
return DB_NE;
}
#endif
return MR_CMP (ts_tz1->timestamp, ts_tz2->timestamp);
}
/*
* TYPE DATETIME
*
*/
static void
mr_initmem_datetime (void *memptr, TP_DOMAIN * domain)
{
DB_DATETIME *mem = (DB_DATETIME *) memptr;
mem->date = 0;
mem->time = 0;
}
static void
mr_initval_datetime (DB_VALUE * value, int precision, int scale)
{
DB_DATETIME dt;
mr_initmem_datetime (&dt, NULL);
db_make_datetime (value, &dt);
value->need_clear = false;
}
static void
mr_initval_datetimeltz (DB_VALUE * value, int precision, int scale)
{
DB_DATETIME dt;
mr_initmem_datetime (&dt, NULL);
db_make_datetimeltz (value, &dt);
value->need_clear = false;
}
static int
mr_setmem_datetime (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
{
mr_initmem_datetime (mem, domain);
}
else
{
*(DB_DATETIME *) mem = *db_get_datetime (value);
}
return NO_ERROR;
}
static int
mr_getmem_datetime (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_datetime (value, (DB_DATETIME *) mem);
}
static int
mr_getmem_datetimeltz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_datetimeltz (value, (DB_DATETIME *) mem);
}
static int
mr_setval_datetime (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_DATETIME, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_datetime (dest, db_get_datetime (src));
}
return error;
}
static int
mr_setval_datetimeltz (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_DATETIMELTZ, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_datetimeltz (dest, db_get_datetime (src));
}
return error;
}
static void
mr_data_writemem_datetime (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_datetime (buf, (DB_DATETIME *) mem);
}
static void
mr_data_readmem_datetime (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Datetime.disksize);
}
else
{
or_get_datetime (buf, (DB_DATETIME *) mem);
}
}
static int
mr_data_writeval_datetime (OR_BUF * buf, DB_VALUE * value)
{
return or_put_datetime (buf, db_get_datetime (value));
}
static int
mr_data_readval_datetime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIME datetime;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Datetime.disksize);
}
else
{
rc = or_get_datetime (buf, &datetime);
if (rc == NO_ERROR)
{
if (DATETIME_IS_NULL (&datetime))
{
db_make_null (value);
}
else
{
db_make_datetime (value, &datetime);
}
}
value->need_clear = false;
}
return rc;
}
static int
mr_data_readval_datetimeltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIME datetime;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Datetimeltz.disksize);
}
else
{
rc = or_get_datetime (buf, &datetime);
db_make_datetimeltz (value, &datetime);
}
return rc;
}
static int
mr_index_writeval_datetime (OR_BUF * buf, DB_VALUE * value)
{
DB_DATETIME *datetime;
int rc = NO_ERROR;
datetime = db_get_datetime (value);
assert (tp_Datetime.disksize == (tp_Date.disksize + tp_Time.disksize));
rc = or_put_data (buf, (char *) (&datetime->date), tp_Date.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&datetime->time), tp_Time.disksize);
}
return rc;
}
static int
mr_index_readval_datetime (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIME datetime;
int rc = NO_ERROR;
assert (tp_Datetime.disksize == (tp_Date.disksize + tp_Time.disksize));
if (value == NULL)
{
rc = or_advance (buf, tp_Datetime.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&datetime.date), tp_Date.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&datetime.time), tp_Time.disksize);
}
if (rc == NO_ERROR)
{
db_make_datetime (value, &datetime);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_readval_datetimeltz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIME datetime;
int rc = NO_ERROR;
assert (tp_Datetimeltz.disksize == (tp_Date.disksize + tp_Time.disksize));
if (value == NULL)
{
rc = or_advance (buf, tp_Datetimeltz.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&datetime.date), tp_Date.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&datetime.time), tp_Time.disksize);
}
if (rc == NO_ERROR)
{
db_make_datetimeltz (value, &datetime);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_datetime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
DB_DATETIME dt1, dt2;
assert (domain != NULL);
if (mem1 == mem2)
{
return DB_EQ;
}
COPYMEM (unsigned int, &dt1.date, (char *)mem1 + OR_DATETIME_DATE);
COPYMEM (unsigned int, &dt1.time, (char *) mem1 + OR_DATETIME_TIME);
COPYMEM (unsigned int, &dt2.date, (char *) mem2 + OR_DATETIME_DATE);
COPYMEM (unsigned int, &dt2.time, (char *) mem2 + OR_DATETIME_TIME);
if (dt1.date < dt2.date)
{
c = DB_LT;
}
else if (dt1.date > dt2.date)
{
c = DB_GT;
}
else
{
if (dt1.time < dt2.time)
{
c = DB_LT;
}
else if (dt1.time > dt2.time)
{
c = DB_GT;
}
else
{
c = DB_EQ;
}
}
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_datetime (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
DB_DATETIME dt1, dt2;
assert (domain != NULL);
if (mem1 == mem2)
{
return DB_EQ;
}
OR_GET_DATETIME (mem1, &dt1);
OR_GET_DATETIME (mem2, &dt2);
if (dt1.date < dt2.date)
{
c = DB_LT;
}
else if (dt1.date > dt2.date)
{
c = DB_GT;
}
else
{
if (dt1.time < dt2.time)
{
c = DB_LT;
}
else if (dt1.time > dt2.time)
{
c = DB_GT;
}
else
{
c = DB_EQ;
}
}
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_datetime (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
const DB_DATETIME *dt1, *dt2;
DB_VALUE_COMPARE_RESULT c;
dt1 = db_get_datetime (value1);
dt2 = db_get_datetime (value2);
if (dt1->date < dt2->date)
{
c = DB_LT;
}
else if (dt1->date > dt2->date)
{
c = DB_GT;
}
else
{
if (dt1->time < dt2->time)
{
c = DB_LT;
}
else if (dt1->time > dt2->time)
{
c = DB_GT;
}
else
{
c = DB_EQ;
}
}
return c;
}
/*
* TYPE DATETIMETZ
*
*/
static void
mr_initmem_datetimetz (void *memptr, TP_DOMAIN * domain)
{
DB_DATETIMETZ *mem = (DB_DATETIMETZ *) memptr;
mem->datetime.date = 0;
mem->datetime.time = 0;
mem->tz_id = 0;
}
static void
mr_initval_datetimetz (DB_VALUE * value, int precision, int scale)
{
DB_DATETIMETZ dt_tz;
mr_initmem_datetimetz (&dt_tz, NULL);
db_make_datetimetz (value, &dt_tz);
}
static int
mr_setmem_datetimetz (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
{
mr_initmem_datetimetz (mem, NULL);
}
else
{
*(DB_DATETIMETZ *) mem = *db_get_datetimetz (value);
}
return NO_ERROR;
}
static int
mr_getmem_datetimetz (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_datetimetz (value, (DB_DATETIMETZ *) mem);
}
static int
mr_setval_datetimetz (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_DATETIMETZ, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_datetimetz (dest, db_get_datetimetz (src));
}
return error;
}
static void
mr_data_writemem_datetimetz (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_datetimetz (buf, (DB_DATETIMETZ *) mem);
}
static void
mr_data_readmem_datetimetz (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Datetimetz.disksize);
}
else
{
or_get_datetimetz (buf, (DB_DATETIMETZ *) mem);
}
}
static int
mr_data_writeval_datetimetz (OR_BUF * buf, DB_VALUE * value)
{
return or_put_datetimetz (buf, db_get_datetimetz (value));
}
static int
mr_data_readval_datetimetz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIMETZ datetimetz;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Datetimetz.disksize);
}
else
{
rc = or_get_datetimetz (buf, &datetimetz);
db_make_datetimetz (value, &datetimetz);
}
return rc;
}
static int
mr_index_writeval_datetimetz (OR_BUF * buf, DB_VALUE * value)
{
DB_DATETIMETZ *datetimetz;
int rc = NO_ERROR;
datetimetz = db_get_datetimetz (value);
assert (tp_Datetimetz.disksize == (tp_Date.disksize + tp_Time.disksize + tp_Integer.disksize));
rc = or_put_data (buf, (char *) (&datetimetz->datetime.date), tp_Date.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&datetimetz->datetime.time), tp_Time.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&datetimetz->tz_id), tp_Integer.disksize);
}
}
return rc;
}
static int
mr_index_readval_datetimetz (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATETIMETZ datetimetz;
int rc = NO_ERROR;
assert (tp_Datetimetz.disksize == (tp_Date.disksize + tp_Time.disksize + tp_Integer.disksize));
if (value == NULL)
{
rc = or_advance (buf, tp_Datetimetz.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&datetimetz.datetime.date), tp_Date.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&datetimetz.datetime.time), tp_Time.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&datetimetz.tz_id), tp_Integer.disksize);
}
}
if (rc == NO_ERROR)
{
db_make_datetimetz (value, &datetimetz);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_datetimetz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
/* DATETIMETZ compares the same as DATETIME (tz_id is ignored) */
return mr_index_cmpdisk_datetime (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_datetimetz (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
/* DATETIMETZ compares the same as DATETIME (tz_id is ignored) */
return mr_data_cmpdisk_datetime (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_datetimetz (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
const DB_DATETIMETZ *dt_tz1, *dt_tz2;
const DB_DATETIME *dt1, *dt2;
DB_VALUE_COMPARE_RESULT c;
dt_tz1 = db_get_datetimetz (value1);
dt_tz2 = db_get_datetimetz (value2);
dt1 = &(dt_tz1->datetime);
dt2 = &(dt_tz2->datetime);
#if defined (SA_MODE)
if (tz_Compare_datetimetz_tz_id == true && dt_tz1->tz_id != dt_tz2->tz_id)
{
return DB_NE;
}
#endif /* SA_MODE */
if (dt1->date < dt2->date)
{
c = DB_LT;
}
else if (dt1->date > dt2->date)
{
c = DB_GT;
}
else
{
if (dt1->time < dt2->time)
{
c = DB_LT;
}
else if (dt1->time > dt2->time)
{
c = DB_GT;
}
else
{
c = DB_EQ;
}
}
return c;
}
/*
* TYPE MONETARY
*
* Practically useless combination of an IEEE double with a currency tag.
* Should consider re-implementing this using fixed precision numerics
* now that we have them.
* Because of double allignment problems, never access the amount field
* with a structure dereference.
*/
static void
mr_initmem_money (void *memptr, TP_DOMAIN * domain)
{
DB_MONETARY *mem = (DB_MONETARY *) memptr;
double d = 0.0;
mem->type = DB_CURRENCY_DEFAULT;
OR_MOVE_DOUBLE (&d, &mem->amount);
}
static int
mr_setmem_money (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
DB_MONETARY *mem = (DB_MONETARY *) memptr;
DB_MONETARY *money;
if (value == NULL)
{
mr_initmem_money (mem, domain);
}
else
{
money = db_get_monetary (value);
mem->type = money->type;
OR_MOVE_DOUBLE (&money->amount, &mem->amount);
}
return NO_ERROR;
}
static int
mr_getmem_money (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
DB_MONETARY *mem = (DB_MONETARY *) memptr;
double amt = 0;
OR_MOVE_DOUBLE (&mem->amount, &amt);
error = db_make_monetary (value, mem->type, amt);
value->need_clear = false;
return error;
}
static void
mr_data_writemem_money (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_monetary (buf, (DB_MONETARY *) mem);
}
static void
mr_data_readmem_money (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Monetary.disksize);
}
else
{
or_get_monetary (buf, (DB_MONETARY *) mem);
}
}
static void
mr_initval_money (DB_VALUE * value, int precision, int scale)
{
db_make_monetary (value, DB_CURRENCY_DEFAULT, 0.0);
value->need_clear = false;
}
static int
mr_setval_money (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
DB_MONETARY *money;
if (DB_IS_NULL (src) || ((money = db_get_monetary (src)) == NULL))
{
error = db_value_domain_init (dest, DB_TYPE_MONETARY, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_make_monetary (dest, money->type, money->amount);
}
return error;
}
static int
mr_data_writeval_money (OR_BUF * buf, DB_VALUE * value)
{
return or_put_monetary (buf, db_get_monetary (value));
}
static int
mr_data_readval_money (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_MONETARY money;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Monetary.disksize);
}
else
{
rc = or_get_monetary (buf, &money);
if (rc == NO_ERROR)
{
db_make_monetary (value, money.type, money.amount);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_money (OR_BUF * buf, DB_VALUE * value)
{
DB_MONETARY *money;
int rc = NO_ERROR;
money = db_get_monetary (value);
rc = or_put_data (buf, (char *) (&money->type), tp_Integer.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&money->amount), tp_Double.disksize);
}
return rc;
}
static int
mr_index_readval_money (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_MONETARY money;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Monetary.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&money.type), tp_Integer.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&money.amount), tp_Double.disksize);
}
if (rc == NO_ERROR)
{
db_make_monetary (value, money.type, money.amount);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_money (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_MONETARY m1, m2;
assert (domain != NULL);
COPYMEM (double, &m1.amount, (char *) mem1 + tp_Integer.disksize);
COPYMEM (double, &m2.amount, (char *) mem2 + tp_Integer.disksize);
return MR_CMP (m1.amount, m2.amount);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_money (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_MONETARY m1, m2;
assert (domain != NULL);
OR_GET_MONETARY (mem1, &m1);
OR_GET_MONETARY (mem2, &m2);
return MR_CMP (m1.amount, m2.amount);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_money (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
const DB_MONETARY *m1, *m2;
m1 = db_get_monetary (value1);
m2 = db_get_monetary (value2);
return MR_CMP (m1->amount, m2->amount);
}
/*
* TYPE DATE
*
* 32 bit day counter, commonly called a "julian" date.
*/
static void
mr_initmem_date (void *mem, TP_DOMAIN * domain)
{
*(DB_DATE *) mem = 0;
}
static int
mr_setmem_date (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
mr_initmem_date (mem, domain);
else
*(DB_DATE *) mem = *db_get_date (value);
return NO_ERROR;
}
static int
mr_getmem_date (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_value_put_encoded_date (value, (DB_DATE *) mem);
}
static void
mr_data_writemem_date (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_date (buf, (DB_DATE *) mem);
}
static void
mr_data_readmem_date (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
if (mem == NULL)
{
or_advance (buf, tp_Date.disksize);
}
else
{
or_get_date (buf, (DB_DATE *) mem);
}
}
static void
mr_initval_date (DB_VALUE * value, int precision, int scale)
{
db_value_put_encoded_date (value, 0);
value->need_clear = false;
}
static int
mr_setval_date (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
if (DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_DATE, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
error = db_value_put_encoded_date (dest, db_get_date (src));
}
return error;
}
static int
mr_data_writeval_date (OR_BUF * buf, DB_VALUE * value)
{
return or_put_date (buf, db_get_date (value));
}
static int
mr_data_readval_date (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATE dt;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Date.disksize);
}
else
{
rc = or_get_date (buf, &dt);
if (rc == NO_ERROR)
{
db_value_put_encoded_date (value, &dt);
}
value->need_clear = false;
}
return rc;
}
static int
mr_index_writeval_date (OR_BUF * buf, DB_VALUE * value)
{
DB_DATE *dt;
dt = db_get_date (value);
return or_put_data (buf, (char *) dt, tp_Date.disksize);
}
static int
mr_index_readval_date (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_DATE dt;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Date.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&dt), tp_Date.disksize);
if (rc == NO_ERROR)
{
db_value_put_encoded_date (value, &dt);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_date (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_DATE d1, d2;
assert (domain != NULL);
COPYMEM (DB_DATE, &d1, mem1);
COPYMEM (DB_DATE, &d2, mem2);
return MR_CMP (d1, d2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_date (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_DATE d1, d2;
assert (domain != NULL);
OR_GET_DATE (mem1, &d1);
OR_GET_DATE (mem2, &d2);
return MR_CMP (d1, d2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_date (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
const DB_DATE *d1, *d2;
d1 = db_get_date (value1);
d2 = db_get_date (value2);
return MR_CMP (*d1, *d2);
}
/*
* TYPE OBJECT
*/
/*
* This is a bit different than the other primitive types in that the memory
* value and the DB_VALUE representations are not the same. The memory value
* will be represented with a WS_MEMOID structure to avoid creating MOPs until
* they are actually needed.
*
* These types are not available on the server since there is no workspace
* over there. Although in standalone mode, we could promote OIDs to MOPs
* on both sides, use the db_on_server flag to control this so we make
* both sides behave similarly even though we're in standalone mode.
* The "mem" functions will in general be commented out since they
* call things that don't exist on the server. THe "val" functions will
* exist so that things tagged as DB_TYPE_OBJECT can be read as OID values.
*
*/
/*
* mr_null_oid - This is used to set an OID to the NULL state.
* return: void
* oid(out): oid to initialize
* Note:
* SET_OID_NULL does the actual work by setting the volid to -1 but it
* leaves garbage in the other fields which can be stored on disk and
* generally looks alarming when you encounter it later. Before
* calling SET_OID_NULL, initialize the fields to nice zero values.
* Should be an inline function.
*/
static void
mr_null_oid (OID * oid)
{
oid->pageid = 0;
oid->volid = 0;
oid->slotid = 0;
OID_SET_NULL (oid);
}
static void
mr_initmem_object (void *memptr, TP_DOMAIN * domain)
{
/* there is no use for initmem on the server */
#if !defined (SERVER_MODE)
WS_MEMOID *mem = (WS_MEMOID *) memptr;
mr_null_oid (&mem->oid);
mem->pointer = NULL;
#endif
}
/*
* Can get here on the server when dispatching from set element domains.
* Always represent object values as OIDs on the server.
*/
static void
mr_initval_object (DB_VALUE * value, int precision, int scale)
{
OID oid;
#if !defined (SERVER_MODE)
if (db_on_server)
{
db_value_domain_init (value, DB_TYPE_OID, precision, scale);
OID_SET_NULL (&oid);
db_make_oid (value, &oid);
}
else
{
db_value_domain_init (value, DB_TYPE_OBJECT, precision, scale);
db_make_object (value, NULL);
}
#else /* SERVER_MODE */
db_value_domain_init (value, DB_TYPE_OID, precision, scale);
OID_SET_NULL (&oid);
db_make_oid (value, &oid);
#endif /* !SERVER_MODE */
}
static int
mr_setmem_object (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
/* there is no need for setmem on the server */
#if !defined (SERVER_MODE)
WS_MEMOID *mem = (WS_MEMOID *) memptr;
OID *oid;
MOP op;
if (value == NULL)
{
mr_null_oid (&mem->oid);
mem->pointer = NULL;
}
else
{
op = db_get_object (value);
if (op == NULL)
{
mr_initmem_object (mem, domain);
}
else
{
oid = WS_OID (op);
mem->oid.volid = oid->volid;
mem->oid.pageid = oid->pageid;
mem->oid.slotid = oid->slotid;
if (op->is_temp)
{
mem->pointer = NULL;
}
else
{
mem->pointer = op;
}
}
}
#endif /* !SERVER_MODE */
return NO_ERROR;
}
static int
mr_getmem_object (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
/* there is no need for getmem on the server */
#if !defined (SERVER_MODE)
WS_MEMOID *mem = (WS_MEMOID *) memptr;
MOP op;
op = mem->pointer;
if (op == NULL)
{
if (!OID_ISNULL (&mem->oid))
{
op = ws_mop (&mem->oid, NULL);
if (op != NULL)
{
mem->pointer = op;
error = db_make_object (value, op);
}
else
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
(void) db_make_object (value, NULL);
}
}
}
else
error = db_make_object (value, op);
#endif /* !SERVER_MODE */
return error;
}
static int
mr_setval_object (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
OID *oid;
#if !defined (SERVER_MODE)
if (DB_IS_NULL (src))
{
db_make_null (dest);
}
/* can get here on the server when dispatching through set element domains */
else if (DB_VALUE_TYPE (src) == DB_TYPE_OID)
{
/* make sure that the target type is set properly */
db_value_domain_init (dest, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
oid = (OID *) db_get_oid (src);
error = db_make_oid (dest, oid);
}
else if (DB_VALUE_TYPE (src) == DB_TYPE_OBJECT)
{
/* If we're logically on the server, we probably shouldn't have gotten here but if we do, don't continue with the
* object representation, de-swizzle it back to an OID. */
if (db_on_server)
{
DB_OBJECT *obj;
/* what should this do for ISVID mops? */
obj = db_get_object (src);
db_value_domain_init (dest, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
oid = WS_OID (obj);
error = db_make_oid (dest, oid);
}
else
{
db_value_domain_init (dest, DB_TYPE_OBJECT, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
error = db_make_object (dest, db_get_object (src));
}
}
#else /* SERVER_MODE */
/*
* If we're really on the server, we can only get here when dispatching
* through set element domains. The value must contain an OID.
*/
if (DB_IS_NULL (src) || DB_VALUE_TYPE (src) != DB_TYPE_OID)
{
db_make_null (dest);
}
else
{
oid = (OID *) db_get_oid (src);
error = db_make_oid (dest, oid);
}
#endif /* !SERVER_MODE */
return error;
}
static int
mr_index_lengthval_object (DB_VALUE * value)
{
return tp_Oid.disksize;
}
/*
* mr_lengthval_object - checks if the object is virtual or not. and returns
* property type size.
* return: If it is virtual object returns calculated the DB_TYPE_VOBJ
* packed size. returns DB_TYPE_OID otherwise
* value(in): value to get length
* disk(in): indicator that it is disk object
*/
static int
mr_data_lengthval_object (DB_VALUE * value, int disk)
{
#if !defined (SERVER_MODE)
MOP mop;
#endif
int size;
if (disk)
{
size = OR_OID_SIZE;
}
else
{
size = MR_OID_SIZE;
}
#if !defined (SERVER_MODE)
if (DB_VALUE_TYPE (value) == DB_TYPE_OBJECT && disk)
{
mop = db_get_object (value);
if ((mop == NULL) || (WS_IS_DELETED (mop)))
{
/* The size of a NULL is OR_OID_SIZE, which is already set (from Jeff L.) */
}
else if (WS_ISVID (mop))
{
DB_VALUE vmop_seq;
int error;
error = vid_object_to_vobj (mop, &vmop_seq);
if (error >= 0)
{
size = mr_data_lengthval_set (&vmop_seq, disk);
pr_clear_value (&vmop_seq);
}
}
}
#endif
return size;
}
static void
mr_data_writemem_object (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
#if !defined (SERVER_MODE) /* there is no need for writemem on the server */
WS_MEMOID *mem = (WS_MEMOID *) memptr;
OID *oidp;
oidp = NULL;
if (mem != NULL)
{
oidp = &mem->oid;
}
if (oidp == NULL)
{
/* construct an unbound oid */
oidp = (OID *) (&oid_Null_oid);
}
else if (OID_ISTEMP (oidp))
{
/* Temporary oid, must get a permanent one. This should only happen if the MOID has a valid MOP. Check for
* deletion */
if ((mem->pointer == NULL) || (WS_IS_DELETED (mem->pointer)))
{
oidp = (OID *) (&oid_Null_oid);
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_MR_TEMP_OID_WITHOUT_MOP, 0);
}
else
{
oidp = WS_OID (mem->pointer);
if (OID_ISTEMP (oidp))
{
/* a MOP with a temporary OID, make an entry in the OID fixup table if we have one, otherwise, stop and
* assign a permanent one. */
oidp = tf_need_permanent_oid (buf, mem->pointer);
if (oidp == NULL)
{
/* normally would have used or_abort by now */
oidp = (OID *) (&oid_Null_oid);
}
}
}
}
else
{
/* normal OID check for deletion */
if ((mem->pointer != NULL) && (WS_IS_DELETED (mem->pointer)))
{
oidp = (OID *) (&oid_Null_oid);
}
}
or_put_oid (buf, oidp);
#else /* SERVER_MODE */
/* should never get here but in case we do, dump a NULL OID into the buffer. */
printf ("mr_writemem_object: called on the server !\n");
or_put_oid (buf, (OID *) (&oid_Null_oid));
#endif /* !SERVER_MODE */
}
static void
mr_data_readmem_object (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
#if !defined (SERVER_MODE) /* there is no need for readmem on the server ??? */
WS_MEMOID *mem = (WS_MEMOID *) memptr;
if (mem != NULL)
{
or_get_oid (buf, &mem->oid);
mem->pointer = NULL;
}
else
{
or_advance (buf, tp_Object.disksize);
}
#else
/* shouldn't get here but if we do, just skip over it */
printf ("mr_readmem_object: called on the server !\n");
or_advance (buf, tp_Object.disksize);
#endif
}
static int
mr_index_writeval_object (OR_BUF * buf, DB_VALUE * value)
{
return mr_index_writeval_oid (buf, value);
}
static int
mr_data_writeval_object (OR_BUF * buf, DB_VALUE * value)
{
#if !defined (SERVER_MODE)
MOP mop;
#endif
OID *oidp = NULL;
int rc = NO_ERROR;
#if !defined (SERVER_MODE)
if (db_on_server || pr_Inhibit_oid_promotion)
{
if (DB_VALUE_TYPE (value) == DB_TYPE_OID)
{
oidp = db_get_oid (value);
rc = or_put_oid (buf, oidp);
return rc;
}
else
{
return ER_FAILED;
}
}
if (DB_VALUE_TYPE (value) == DB_TYPE_OBJECT)
{
mop = db_get_object (value);
if ((mop == NULL) || (WS_IS_DELETED (mop)))
{
rc = or_put_oid (buf, (OID *) (&oid_Null_oid));
}
else if (WS_ISVID (mop))
{
DB_VALUE vmop_seq;
int error;
error = vid_object_to_vobj (mop, &vmop_seq);
if (error >= 0)
{
rc = mr_data_writeval_set (buf, &vmop_seq);
pr_clear_value (&vmop_seq);
}
else
{
rc = ER_FAILED;
}
}
else
{
oidp = WS_OID (mop);
if (OID_ISTEMP (oidp))
{
/* a MOP with a temporary OID, make an entry in the OID fixup table if we have one, otherwise, stop and
* assign a permanent one. */
oidp = tf_need_permanent_oid (buf, mop);
if (oidp == NULL)
{
/* normally would have used or_abort by now */
oidp = (OID *) (&oid_Null_oid);
}
}
rc = or_put_oid (buf, oidp);
}
}
else if (DB_VALUE_TYPE (value) == DB_TYPE_OID)
{
oidp = db_get_oid (value);
rc = or_put_oid (buf, oidp);
}
else
{
/* should never get here ! */
rc = or_put_oid (buf, (OID *) (&oid_Null_oid));
}
#else /* SERVER_MODE */
/* on the server, the value must contain an OID */
oidp = db_get_oid (value);
rc = or_put_oid (buf, oidp);
#endif /* !SERVER_MODE */
return rc;
}
static int
mr_index_readval_object (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_index_readval_oid (buf, value, domain, size, copy, copy_buf, copy_buf_len);
}
static int
mr_data_readval_object (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
OID oid;
int rc = NO_ERROR;
#if !defined (SERVER_MODE)
if (value == NULL)
{
rc = or_advance (buf, tp_Object.disksize);
}
else
{
if (db_on_server || pr_Inhibit_oid_promotion)
{
/* basically the same as mr_readval_server_oid, don't promote OIDs */
db_value_domain_init (value, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
rc = or_get_oid (buf, &oid);
db_make_oid (value, &oid);
}
else
{
db_value_domain_init (value, DB_TYPE_OBJECT, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
rc = or_get_oid (buf, &oid);
/*
* if the OID is NULL, leave the value with the NULL bit set
* and don't bother to put the OID inside.
* I added this because it seemed logical, does it break anything ?
*/
if (!OID_ISNULL (&oid))
{
db_make_object (value, ws_mop (&oid, NULL));
if (db_get_object (value) == NULL)
{
return ER_FAILED;
}
}
}
}
#else /* SERVER_MODE */
/* on the server, we only read OIDs */
if (value == NULL)
{
rc = or_advance (buf, tp_Object.disksize);
}
else
{
db_value_domain_init (value, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
rc = or_get_oid (buf, &oid);
/* should we be checking for the NULL OID here ? */
db_make_oid (value, &oid);
}
#endif /* !SERVER_MODE */
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_object (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_index_cmpdisk_oid (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_object (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
OID o1, o2;
int oidc;
assert (domain != NULL);
OR_GET_OID (mem1, &o1);
OR_GET_OID (mem2, &o2);
/* if we ever store virtual objects, this will need to be changed. However, since its known the only disk
* representation of objects is an OID, this is a valid optimization */
oidc = oid_compare (&o1, &o2);
return MR_CMP_RETURN_CODE (oidc);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_object (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
#if defined (SERVER_MODE)
const OID *o1, *o2;
int oidc;
/*
* we need to be careful here because even though the domain may
* say object, it may really be an OID (especially on the server).
*/
if (DB_VALUE_DOMAIN_TYPE (value1) == DB_TYPE_OID)
{
o1 = db_get_oid (value1);
}
else
{
assert (false);
o1 = &oid_Null_oid;
}
if (DB_VALUE_DOMAIN_TYPE (value2) == DB_TYPE_OID)
{
o2 = db_get_oid (value2);
}
else
{
assert (false);
o2 = &oid_Null_oid;
}
oidc = oid_compare (o1, o2);
return MR_CMP_RETURN_CODE (oidc);
#else /* !SERVER_MODE */
/* on the client, we must also handle virtual db_object types */
DB_VALUE_COMPARE_RESULT c;
OID *o1 = NULL, *o2 = NULL;
DB_OBJECT *mop1 = NULL, *mop2 = NULL, *class1, *class2;
int virtual_ = 0;
int nonupdate = 0;
DB_VALUE keys1, keys2;
/*
* we need to be careful here because even though the domain may
* say object, it may really be an OID (especially on the server).
*/
if (DB_VALUE_DOMAIN_TYPE (value1) == DB_TYPE_OID)
{
o1 = db_get_oid (value1);
}
else
{
mop1 = db_get_object (value1);
if (WS_ISVID (mop1))
{
if (db_is_updatable_object (mop1))
{
mop1 = db_real_instance (mop1);
}
else
{
nonupdate = 1;
}
if (mop1 != NULL)
{
if (WS_ISVID (mop1))
{
/* non updateble object or proxy object */
virtual_ = 1;
}
else
{
o1 = WS_OID (mop1);
}
}
else
{
o1 = (OID *) (&oid_Null_oid);
}
}
else
{
o1 = WS_OID (mop1);
}
}
if (DB_VALUE_DOMAIN_TYPE (value2) == DB_TYPE_OID)
{
o2 = db_get_oid (value2);
}
else
{
mop2 = db_get_object (value2);
if (WS_ISVID (mop2))
{
if (db_is_updatable_object (mop2))
{
mop2 = db_real_instance (mop2);
}
else
{
nonupdate += 2;
}
if (mop2 != NULL)
{
if (WS_ISVID (mop2))
{
/* non updateble object or proxy object */
virtual_ += 2;
}
else
{
o2 = WS_OID (mop2);
}
}
else
{
o2 = (OID *) (&oid_Null_oid);
}
}
else
{
o2 = WS_OID (mop2);
}
}
if (virtual_ == 0)
{
int oidc = oid_compare (o1, o2);
return MR_CMP_RETURN_CODE (oidc);
}
if (mop1 == mop2)
{
return DB_EQ; /* an optimization */
}
if (virtual_ == 1)
{
return DB_LT; /* consistent comparison of oids and */
}
if (virtual_ == 2)
{
return DB_GT; /* non-oid based vobjs, they are never equal */
}
/* virtual must be 3, meaning both objects are either proxies or non-updatable objects */
if (nonupdate == 1)
{
return DB_LT; /* again, a consistent comparison */
}
if (nonupdate == 2)
{
return DB_GT; /* for proxy mop and non-updatable mop */
}
if (nonupdate == 0)
{
int oidc;
/*
* comparing two proxy mops, the must both be from the
* same proxy class. Compare the proxy classes oids.
* Note class mops are never virtual mops.
*/
class1 = db_get_class (mop1);
class2 = db_get_class (mop2);
o1 = (class1) ? WS_OID (class1) : (OID *) (&oid_Null_oid);
o2 = (class2) ? WS_OID (class2) : (OID *) (&oid_Null_oid);
oidc = oid_compare (o1, o2);
c = MR_CMP_RETURN_CODE (oidc);
/*
* as long as the result is not equal, we are done
* If its equal, we need to continue with a key test below.
*/
if (c != DB_EQ)
{
return c;
}
}
/*
* here, nonupdate must be 3 or 0 and
* we must have two non-updatable mops, or two proxy mops
* from the same proxy. Consequently, their keys are comparable
* to identify the object.
*/
vid_get_keys (mop1, &keys1);
vid_get_keys (mop2, &keys2);
return tp_value_compare (&keys1, &keys2, do_coercion, total_order);
#endif /* SERVER_MODE */
}
#if !defined (SERVER_MODE)
#endif /* !SERVER_MODE */
static void
mr_initmem_elo (void *memptr, TP_DOMAIN * domain)
{
if (memptr != NULL)
{
*((DB_ELO **) memptr) = NULL;
}
}
static void
mr_initval_elo (DB_VALUE * value, int precision, int scale)
{
/* should not be called */
assert (0);
}
static void
mr_initval_blob (DB_VALUE * value, int precision, int scale)
{
DB_ELO *null_elo = NULL;
db_value_domain_init (value, DB_TYPE_BLOB, precision, scale);
db_make_elo (value, DB_TYPE_BLOB, null_elo);
}
static void
mr_initval_clob (DB_VALUE * value, int precision, int scale)
{
DB_ELO *null_elo = NULL;
db_value_domain_init (value, DB_TYPE_CLOB, precision, scale);
db_make_elo (value, DB_TYPE_CLOB, null_elo);
}
static int
mr_setmem_elo (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int rc;
DB_ELO *elo, *e;
if (memptr != NULL)
{
mr_freemem_elo (memptr);
mr_initmem_elo (memptr, domain);
if (value != NULL && (e = db_get_elo (value)) != NULL)
{
elo = (DB_ELO *) db_private_alloc (NULL, sizeof (DB_ELO));
if (elo == NULL)
{
return ((er_errid () == NO_ERROR) ? ER_FAILED : er_errid ());
}
rc = elo_copy_structure (e, elo);
if (rc != NO_ERROR)
{
if (elo != NULL)
{
db_private_free_and_init (NULL, elo);
}
return rc;
}
*((DB_ELO **) memptr) = elo;
}
}
else
{
assert_release (0);
}
return NO_ERROR;
}
static int
getmem_elo_with_type (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy, DB_TYPE type)
{
DB_ELO *elo;
int r = NO_ERROR;
if (memptr == NULL)
{
db_make_null (value);
return r;
}
elo = *((DB_ELO **) memptr);
if (elo == NULL || elo->size < 0)
{
db_make_null (value);
return r;
}
if (copy)
{
DB_ELO e;
r = elo_copy_structure (elo, &e);
if (r == NO_ERROR)
{
db_make_elo (value, type, &e);
value->need_clear = true;
}
}
else
{
db_make_elo (value, type, elo);
}
return r;
}
static int
mr_getmem_elo (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
/* should not happen */
assert (0);
return ER_FAILED;
}
static int
mr_getmem_blob (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return getmem_elo_with_type (memptr, domain, value, copy, DB_TYPE_BLOB);
}
static int
mr_getmem_clob (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return getmem_elo_with_type (memptr, domain, value, copy, DB_TYPE_CLOB);
}
static int
setval_elo_with_type (DB_VALUE * dest, const DB_VALUE * src, bool copy, DB_TYPE type)
{
int r = NO_ERROR;
if (DB_IS_NULL (src) || db_get_elo (src) == NULL)
{
db_make_null (dest);
return NO_ERROR;
}
if (copy)
{
DB_ELO elo;
DB_ELO *e = db_get_elo (src);
r = elo_copy_structure (e, &elo);
if (r == NO_ERROR)
{
db_make_elo (dest, type, &elo);
dest->need_clear = true;
}
}
else
{
db_make_elo (dest, type, db_get_elo (src));
}
return r;
}
static int
mr_setval_elo (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
assert (0);
return ER_FAILED;
}
static int
mr_setval_blob (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return setval_elo_with_type (dest, src, copy, DB_TYPE_BLOB);
}
static int
mr_setval_clob (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return setval_elo_with_type (dest, src, copy, DB_TYPE_CLOB);
}
static int
mr_data_lengthmem_elo (void *memptr, TP_DOMAIN * domain, int disk)
{
int len = 0;
if (!disk)
{
assert (tp_Elo.size == tp_Blob.size);
assert (tp_Blob.size == tp_Clob.size);
len = tp_Elo.size;
}
else if (memptr != NULL)
{
DB_ELO *elo = *((DB_ELO **) memptr);
if (elo != NULL && elo->type != ELO_NULL)
{
len = (OR_BIGINT_SIZE
+ or_packed_string_length (elo->locator, NULL)
+ or_packed_string_length (elo->meta_data, NULL) + OR_INT_SIZE);
}
}
else
{
assert_release (0);
}
return len;
}
static int
mr_data_lengthval_elo (DB_VALUE * value, int disk)
{
DB_ELO *elo;
if (value != NULL)
{
elo = db_get_elo (value);
return mr_data_lengthmem_elo ((void *) &elo, NULL, disk);
}
else
{
return 0;
}
}
static void
mr_data_writemem_elo (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
DB_ELO *elo;
if (memptr == NULL)
{
assert_release (0);
return;
}
elo = *((DB_ELO **) memptr);
if (elo != NULL && elo->type != ELO_NULL)
{
/* size */
or_put_bigint (buf, elo->size);
/* locator */
assert (elo->locator != NULL);
or_put_int (buf, or_packed_string_length (elo->locator, NULL) - OR_INT_SIZE);
if (elo->locator != NULL)
{
or_put_string_aligned (buf, elo->locator);
}
/* meta_data */
or_put_int (buf, or_packed_string_length (elo->meta_data, NULL) - OR_INT_SIZE);
if (elo->meta_data != NULL)
{
or_put_string_aligned (buf, elo->meta_data);
}
/* type */
or_put_int (buf, elo->type);
}
}
static void
peekmem_elo (OR_BUF * buf, DB_ELO * elo)
{
int locator_len, meta_data_len;
int rc = NO_ERROR;
/* size */
elo->size = or_get_bigint (buf, &rc);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
/* locator */
locator_len = or_get_int (buf, &rc);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
if (locator_len > 0)
{
elo->locator = buf->ptr;
}
else
{
assert (false);
goto error;
}
rc = or_advance (buf, locator_len);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
/* meta_data */
meta_data_len = or_get_int (buf, &rc);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
if (meta_data_len > 0)
{
elo->meta_data = buf->ptr;
}
else
{
elo->meta_data = NULL;
}
rc = or_advance (buf, meta_data_len);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
/* type */
elo->type = (DB_ELO_TYPE) or_get_int (buf, &rc);
if (rc != NO_ERROR)
{
assert (false);
goto error;
}
return;
error:
elo->locator = NULL;
elo->meta_data = NULL;
elo->size = 0;
elo->type = ELO_NULL;
}
static void
mr_data_readmem_elo (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
DB_ELO *elo;
DB_ELO e;
int rc = NO_ERROR;
if (size == 0)
{
return;
}
if (memptr == NULL)
{
or_advance (buf, size);
return;
}
elo = (DB_ELO *) db_private_alloc (NULL, sizeof (DB_ELO));
if (elo == NULL)
{
ASSERT_ERROR ();
return;
}
else
{
peekmem_elo (buf, &e);
rc = elo_copy_structure (&e, elo);
if (rc != NO_ERROR)
{
db_private_free_and_init (NULL, elo);
return;
}
}
*((DB_ELO **) memptr) = elo;
}
static int
mr_data_writeval_elo (OR_BUF * buf, DB_VALUE * value)
{
DB_ELO *elo;
elo = db_get_elo (value);
mr_data_writemem_elo (buf, (void *) &elo, NULL);
return NO_ERROR;
}
static int
readval_elo_with_type (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len, DB_TYPE type)
{
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, size);
return rc;
}
if (size != 0)
{
if (copy)
{
DB_ELO *e = NULL;
mr_data_readmem_elo (buf, (void *) &e, NULL, size);
/* structure copy - to value->data.elo */
rc = db_make_elo (value, type, e);
if (e != NULL)
{
db_private_free_and_init (NULL, e);
}
value->need_clear = true;
}
else
{
DB_ELO elo;
peekmem_elo (buf, &elo);
/* structure copy - to value->data.elo */
rc = db_make_elo (value, type, &elo);
}
}
return rc;
}
static int
mr_data_readval_elo (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
/* should not happen */
assert (0);
return ER_FAILED;
}
static int
mr_data_readval_blob (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return readval_elo_with_type (buf, value, domain, size, copy, copy_buf, copy_buf_len, DB_TYPE_BLOB);
}
static int
mr_data_readval_clob (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return readval_elo_with_type (buf, value, domain, size, copy, copy_buf, copy_buf_len, DB_TYPE_CLOB);
}
static void
mr_freemem_elo (void *memptr)
{
DB_ELO *elo;
if (memptr != NULL)
{
elo = *((DB_ELO **) memptr);
if (elo != NULL)
{
elo_free_structure (elo);
db_private_free_and_init (NULL, elo);
}
}
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_elo (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
/*
* don't know how to do this since elo's should find their way into
* listfiles and such.
*/
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_elo (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
DB_ELO *elo1, *elo2;
elo1 = db_get_elo (value1);
elo2 = db_get_elo (value2);
/* use address for collating sequence */
return MR_CMP ((UINTPTR) elo1, (UINTPTR) elo2);
}
/*
* TYPE VARIABLE
*
* Currently this can only be used internally for class objects. I think
* this is useful enough to make a general purpose thing.
* Implemented with the DB_VALUE (like set elements) which means that we
* will always create MOPs for variable values that are object references.
* If this gets to be a big deal, will need to define another union
* like DB_MEMORY_VALUE that has a local OID cache like the attribute
* values do.
* These were once just stubs that didn't do anything since the class
* transformer called the pr_write_va/rtype etc. functions directly. If
* they can be regular types for object attributes, we need to support
* an mr_ interface as well.
*
* NOTE: These are still stubs, need to think about other ramifications
* in the schema level before making these public.
*/
static void
mr_initval_variable (DB_VALUE * value, int precision, int scale)
{
mr_initval_null (value, precision, scale);
}
static int
mr_setval_variable (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
mr_initval_null (dest, 0, 0);
return NO_ERROR;
}
static int
mr_data_lengthval_variable (DB_VALUE * value, int disk)
{
return 0;
}
static int
mr_data_writeval_variable (OR_BUF * buf, DB_VALUE * value)
{
return NO_ERROR;
}
static int
mr_data_readval_variable (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_variable (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_variable (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
return DB_UNK;
}
/*
* TYPE SUBSTRUCTURE
*
* Only for meta objects. Might want to extend.
* This really only serves as a placeholder in the type table. These
* functions should never be referenced through the usual channels.
*/
static void
mr_initmem_sub (void *mem, TP_DOMAIN * domain)
{
}
static void
mr_initval_sub (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_SUB, precision, scale);
}
static int
mr_setmem_sub (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
return NO_ERROR;
}
static int
mr_getmem_sub (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return NO_ERROR;
}
static int
mr_setval_sub (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return NO_ERROR;
}
static int
mr_data_lengthmem_sub (void *mem, TP_DOMAIN * domain, int disk)
{
return 0;
}
static int
mr_data_lengthval_sub (DB_VALUE * value, int disk)
{
return 0;
}
static void
mr_data_writemem_sub (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
}
static void
mr_data_readmem_sub (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
}
static int
mr_data_writeval_sub (OR_BUF * buf, DB_VALUE * value)
{
return NO_ERROR;
}
static int
mr_data_readval_sub (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_sub (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_sub (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
return DB_UNK;
}
/*
* TYPE POINTER
*
* These exist only so that method arguments can have arbitrary pointer
* values. You cannot create an attribute that has a pointer value since
* these are not persistent values. Pointer values are used internally
* by the object templates to keep place holders to other templates
* that need to be expanded into objects.
*
*/
static void
mr_initmem_ptr (void *memptr, TP_DOMAIN * domain)
{
void **mem = (void **) memptr;
*mem = NULL;
}
static void
mr_initval_ptr (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_POINTER, precision, scale);
db_make_pointer (value, NULL);
}
static int
mr_setmem_ptr (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
void **mem = (void **) memptr;
if (value == NULL)
{
mr_initmem_ptr (mem, domain);
}
else
{
*mem = db_get_pointer (value);
}
return NO_ERROR;
}
static int
mr_getmem_ptr (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
void **mem = (void **) memptr;
return db_make_pointer (value, *mem);
}
static int
mr_setval_ptr (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (DB_IS_NULL (src))
{
db_make_null (dest);
return NO_ERROR;
}
else
{
return db_make_pointer (dest, db_get_pointer (src));
}
}
static int
mr_data_lengthmem_ptr (void *memptr, TP_DOMAIN * domain, int disk)
{
return 0;
}
static int
mr_data_lengthval_ptr (DB_VALUE * value, int disk)
{
void *ptr;
if (value != NULL)
{
ptr = db_get_pointer (value);
return mr_data_lengthmem_ptr (&ptr, NULL, disk);
}
else
{
return NO_ERROR;
}
}
static void
mr_data_writemem_ptr (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
}
static void
mr_data_readmem_ptr (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
void **mem = (void **) memptr;
*mem = NULL;
}
static int
mr_data_writeval_ptr (OR_BUF * buf, DB_VALUE * value)
{
return NO_ERROR;
}
static int
mr_data_readval_ptr (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
if (value)
{
db_value_domain_init (value, DB_TYPE_POINTER, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_ptr (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
/* don't know how to unpack pointers */
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_ptr (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
void *p1, *p2;
p1 = db_get_pointer (value1);
p2 = db_get_pointer (value2);
/* use address for collating sequence */
return MR_CMP ((UINTPTR) p1, (UINTPTR) p2);
}
/*
* TYPE ERROR
*
* This is used only for method arguments, they cannot be attribute values.
*/
static void
mr_initmem_error (void *memptr, TP_DOMAIN * domain)
{
int *mem = (int *) memptr;
*mem = NO_ERROR;
}
static void
mr_initval_error (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_ERROR, precision, scale);
db_make_error (value, NO_ERROR);
}
static int
mr_setmem_error (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int *mem = (int *) memptr;
if (value == NULL)
{
mr_initmem_error (mem, domain);
}
else
{
*mem = db_get_error (value);
}
return NO_ERROR;
}
static int
mr_getmem_error (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int *mem = (int *) memptr;
return db_make_error (value, *mem);
}
static int
mr_setval_error (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (DB_IS_NULL (src))
{
db_make_null (dest);
return NO_ERROR;
}
else
{
return db_make_error (dest, db_get_error (src));
}
}
static int
mr_data_lengthmem_error (void *memptr, TP_DOMAIN * domain, int disk)
{
return 0;
}
static int
mr_data_lengthval_error (DB_VALUE * value, int disk)
{
int error;
if (value != NULL)
{
error = db_get_error (value);
return mr_data_lengthmem_error (&error, NULL, disk);
}
else
{
return NO_ERROR;
}
}
static void
mr_data_writemem_error (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
}
static void
mr_data_readmem_error (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
int *mem = (int *) memptr;
*mem = NO_ERROR;
}
static int
mr_data_writeval_error (OR_BUF * buf, DB_VALUE * value)
{
return NO_ERROR;
}
static int
mr_data_readval_error (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
if (value)
{
db_value_domain_init (value, DB_TYPE_ERROR, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
db_make_error (value, NO_ERROR);
}
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_error (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
/* don't know how to unpack errors */
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_error (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
int e1, e2;
e1 = db_get_error (value1);
e2 = db_get_error (value2);
return MR_CMP (e1, e2);
}
/*
* TYPE OID
*
* DB_TYPE_OID is not really a "domain" type, it is rather a physical
* representation of an object domain. Due to the way we dispatch
* on DB_TYPE_ codes however, we need a fleshed out type vector
* for this.
*
* This is used by the server where we have no DB_OBJECT handles.
* It can also be used on the client in places where we defer
* the "swizzling" of OID references (e.g. inside sets).
*
* We don't have to handle the case where values come in with DB_TYPE_OBJECT
* as we do in the _object handlers, true ?
*
*/
static void
mr_initmem_oid (void *memptr, TP_DOMAIN * domain)
{
OID *mem = (OID *) memptr;
mr_null_oid (mem);
}
static void
mr_initval_oid (DB_VALUE * value, int precision, int scale)
{
OID oid;
mr_null_oid (&oid);
db_value_domain_init (value, DB_TYPE_OID, precision, scale);
db_make_oid (value, &oid);
}
static int
mr_setmem_oid (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
OID *mem = (OID *) memptr;
OID *oid;
if (value == NULL)
{
mr_initmem_oid (mem, domain);
}
else
{
oid = db_get_oid (value);
if (oid)
{
mem->volid = oid->volid;
mem->pageid = oid->pageid;
mem->slotid = oid->slotid;
}
else
{
return ER_FAILED;
}
}
return NO_ERROR;
}
static int
mr_getmem_oid (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
OID *mem = (OID *) memptr;
OID oid;
oid.volid = mem->volid;
oid.pageid = mem->pageid;
oid.slotid = mem->slotid;
return db_make_oid (value, &oid);
}
static int
mr_setval_oid (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
OID *oid;
if (DB_IS_NULL (src))
{
db_make_null (dest);
return NO_ERROR;
}
else
{
oid = (OID *) db_get_oid (src);
return db_make_oid (dest, oid);
}
}
static void
mr_data_writemem_oid (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
OID *mem = (OID *) memptr;
or_put_oid (buf, mem);
}
static void
mr_data_readmem_oid (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
OID *mem = (OID *) memptr;
OID oid;
if (mem != NULL)
{
or_get_oid (buf, mem);
}
else
{
or_get_oid (buf, &oid); /* skip over it */
}
}
static int
mr_data_writeval_oid (OR_BUF * buf, DB_VALUE * value)
{
return (or_put_oid (buf, db_get_oid (value)));
}
static int
mr_data_readval_oid (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
OID oid;
int rc = NO_ERROR;
if (value != NULL)
{
db_value_domain_init (value, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
rc = or_get_oid (buf, &oid);
db_make_oid (value, &oid);
}
else
{
rc = or_advance (buf, tp_Oid.disksize);
}
return rc;
}
static int
mr_index_writeval_oid (OR_BUF * buf, DB_VALUE * value)
{
OID *oidp = NULL;
int rc = NO_ERROR;
assert (DB_VALUE_TYPE (value) == DB_TYPE_OID || DB_VALUE_TYPE (value) == DB_TYPE_OBJECT);
oidp = db_get_oid (value);
rc = or_put_data (buf, (char *) (&oidp->pageid), tp_Integer.disksize);
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&oidp->slotid), tp_Short.disksize);
}
if (rc == NO_ERROR)
{
rc = or_put_data (buf, (char *) (&oidp->volid), tp_Short.disksize);
}
return rc;
}
static int
mr_index_readval_oid (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
OID oid;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_Object.disksize);
}
else
{
rc = or_get_data (buf, (char *) (&oid.pageid), tp_Integer.disksize);
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&oid.slotid), tp_Short.disksize);
}
if (rc == NO_ERROR)
{
rc = or_get_data (buf, (char *) (&oid.volid), tp_Short.disksize);
}
if (rc == NO_ERROR)
{
db_value_domain_init (value, DB_TYPE_OID, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
db_make_oid (value, &oid);
}
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_oid (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
OID o1, o2;
int oidc;
assert (domain != NULL);
COPYMEM (int, &o1.pageid, (char *) mem1 + OR_OID_PAGEID);
COPYMEM (short, &o1.slotid, (char *) mem1 + OR_OID_SLOTID);
COPYMEM (short, &o1.volid, (char *) mem1 + OR_OID_VOLID);
COPYMEM (int, &o2.pageid, (char *) mem2 + OR_OID_PAGEID);
COPYMEM (short, &o2.slotid, (char *) mem2 + OR_OID_SLOTID);
COPYMEM (short, &o2.volid, (char *) mem2 + OR_OID_VOLID);
oidc = oid_compare (&o1, &o2);
return MR_CMP_RETURN_CODE (oidc);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_oid (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
OID o1, o2;
int oidc;
assert (domain != NULL);
OR_GET_OID (mem1, &o1);
OR_GET_OID (mem2, &o2);
oidc = oid_compare (&o1, &o2);
return MR_CMP_RETURN_CODE (oidc);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_oid (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
OID *oid1, *oid2;
int oidc;
oid1 = db_get_oid (value1);
oid2 = db_get_oid (value2);
if (oid1 == NULL || oid2 == NULL)
{
return DB_UNK;
}
oidc = oid_compare (oid1, oid2);
return MR_CMP_RETURN_CODE (oidc);
}
/*
* TYPE SET
*
* This is easily the most complicated primitive type.
* Sets are defined to be owned by an object.
* They may be checked out of an object and accessed directly through the
* set structure. We need to move maintenance of set ownership down
* from the object layer to this layer. This will avoid a lot of special
* cases for sets that now exist in the pr_ and obj_ layers.
*/
static void
mr_initmem_set (void *memptr, TP_DOMAIN * domain)
{
SETOBJ **mem = (SETOBJ **) memptr;
*mem = NULL;
}
static void
mr_initval_set (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_SET, precision, scale);
db_make_set (value, NULL);
}
static int
mr_setmem_set (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
SETOBJ **mem = (SETOBJ **) memptr;
int error = NO_ERROR;
SETOBJ *set;
SETREF *ref;
/*
* NOTE: assumes ownership info has already been placed
* in the set reference by the caller
*/
if ((value != NULL) && ((ref = db_get_set (value)) != NULL))
{
set = ref->set;
if (*mem != set)
{
if (*mem != NULL)
{
error = setobj_release (*mem);
}
*mem = set;
}
}
else
{
if (*mem != NULL)
{
error = setobj_release (*mem);
}
mr_initmem_set (mem, domain);
}
return error;
}
static int
mr_getmem_set (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
SETOBJ **mem = (SETOBJ **) memptr;
int error = NO_ERROR;
SETOBJ *set;
SETREF *ref;
set = *mem;
if (set == NULL)
{
error = db_make_set (value, NULL);
}
else
{
ref = setobj_get_reference (set);
if (ref)
{
error = db_make_set (value, ref);
}
else
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
(void) db_make_set (value, NULL);
}
}
/*
* NOTE: assumes that ownership info will already have been set or will
* be set by the caller
*/
return error;
}
static int
mr_setval_set_internal (DB_VALUE * dest, const DB_VALUE * src, bool copy, DB_TYPE set_type)
{
int error = NO_ERROR;
SETREF *src_ref, *ref;
if (src != NULL && !DB_IS_NULL (src) && ((src_ref = db_get_set (src)) != NULL))
{
if (!copy)
{
ref = src_ref;
/* must increment the reference count */
ref->ref_count++;
}
else
{
/* need to check if we have a disk_image, if so we just copy it */
if (src_ref->disk_set)
{
ref = set_make_reference ();
if (ref == NULL)
{
goto err_set;
}
else
{
/* Copy the bits into a freshly allocated buffer. */
ref->disk_set = (char *) db_private_alloc (NULL, src_ref->disk_size);
if (ref->disk_set == NULL)
{
goto err_set;
}
else
{
ref->need_clear = true;
ref->disk_size = src_ref->disk_size;
ref->disk_domain = src_ref->disk_domain;
memcpy (ref->disk_set, src_ref->disk_set, src_ref->disk_size);
}
}
}
else
{
ref = set_copy (src_ref);
if (ref == NULL)
{
goto err_set;
}
}
}
switch (set_type)
{
case DB_TYPE_SET:
db_make_set (dest, ref);
break;
case DB_TYPE_MULTISET:
db_make_multiset (dest, ref);
break;
case DB_TYPE_SEQUENCE:
db_make_sequence (dest, ref);
break;
default:
break;
}
}
else
{
db_value_domain_init (dest, set_type, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
return error;
err_set:
/* couldn't allocate storage for set */
assert (er_errid () != NO_ERROR);
error = er_errid ();
switch (set_type)
{
case DB_TYPE_SET:
db_make_set (dest, NULL);
break;
case DB_TYPE_MULTISET:
db_make_multiset (dest, NULL);
break;
case DB_TYPE_SEQUENCE:
db_make_sequence (dest, NULL);
break;
default:
break;
}
db_make_null (dest);
return error;
}
static int
mr_setval_set (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return mr_setval_set_internal (dest, src, copy, DB_TYPE_SET);
}
static int
mr_data_lengthmem_set (void *memptr, TP_DOMAIN * domain, int disk)
{
int size;
if (!disk)
{
size = tp_Set.size;
}
else
{
SETOBJ **mem = (SETOBJ **) memptr;
size = or_packed_set_length (*mem, 0);
}
return size;
}
static int
mr_data_lengthval_set (DB_VALUE * value, int disk)
{
SETREF *ref;
SETOBJ *set;
int size;
#if !defined (SERVER_MODE)
int pin;
#endif
size = 0;
if (!disk)
{
size = sizeof (DB_SET *);
}
else
{
ref = db_get_set (value);
if (ref != NULL)
{
/* should have a set_ function for this ! */
if (ref->disk_set)
{
size = ref->disk_size;
}
else if (set_get_setobj (ref, &set, 0) == NO_ERROR)
{
if (set != NULL)
{
/* probably no need to pin here but it can't hurt */
#if !defined (SERVER_MODE)
pin = ws_pin (ref->owner, 1);
#endif
size = or_packed_set_length (set, 1);
#if !defined (SERVER_MODE)
(void) ws_pin (ref->owner, pin);
#endif
}
}
}
}
return size;
}
static void
mr_data_writemem_set (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
SETOBJ **mem = (SETOBJ **) memptr;
if (*mem != NULL)
{
/* note that we don't have to pin the object here since that will have been handled above this leve. */
or_put_set (buf, *mem, 0);
}
}
static int
mr_data_writeval_set (OR_BUF * buf, DB_VALUE * value)
{
SETREF *ref;
SETOBJ *set;
int size;
#if !defined (SERVER_MODE)
int pin;
#endif
int rc = NO_ERROR;
ref = db_get_set (value);
if (ref != NULL)
{
/* If we have a disk image of the set, we can just copy those bits here. This assumes very careful maintenance
* of the disk and memory images. Currently, we only have one or the other. That is, when we transform the disk
* image to memory, we clear the disk image. */
if (ref->disk_set)
{
/* check for overflow */
if ((((ptrdiff_t) (buf->endptr - buf->ptr)) < (ptrdiff_t) ref->disk_size))
{
return ER_TF_BUFFER_OVERFLOW;
}
else
{
memcpy (buf->ptr, ref->disk_set, ref->disk_size);
rc = or_advance (buf, ref->disk_size);
}
}
else if (set_get_setobj (ref, &set, 0) == NO_ERROR)
{
if (set != NULL)
{
if (ref->owner == NULL)
{
or_put_set (buf, set, 1);
}
else
{
#if !defined (SERVER_MODE)
pin = ws_pin (ref->owner, 1);
#endif
size = or_packed_set_length (set, 1);
/* remember the Windows pointer problem ! */
if (((ptrdiff_t) (buf->endptr - buf->ptr)) < (ptrdiff_t) size)
{
/* unpin the owner before we abort ! */
#if !defined (SERVER_MODE)
(void) ws_pin (ref->owner, pin);
#endif
return ER_TF_BUFFER_OVERFLOW;
}
else
{
/* the buffer is ok, do the transformation */
or_put_set (buf, set, 1);
}
#if !defined (SERVER_MODE)
(void) ws_pin (ref->owner, pin);
#endif
}
}
}
}
return rc;
}
static void
mr_data_readmem_set (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
SETOBJ **mem = (SETOBJ **) memptr;
SETOBJ *set;
if (mem == NULL)
{
if (size >= 0)
{
or_advance (buf, size);
}
else
{
set = or_get_set (buf, domain);
if (set != NULL)
{
setobj_free (set);
}
}
}
else
{
if (!size)
{
*mem = NULL;
}
else
{
set = or_get_set (buf, domain);
if (set != NULL)
{
*mem = set;
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return;
}
}
}
}
static int
mr_data_readval_set (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
SETOBJ *set;
SETREF *ref;
int rc = NO_ERROR;
if (value == NULL)
{
if (size == -1)
{
/* don't know the true size, must unpack the set and throw it away */
set = or_get_set (buf, domain);
if (set != NULL)
{
setobj_free (set);
}
else
{
return ER_FAILED;
}
}
else
{
if (size)
{
rc = or_advance (buf, size);
}
}
}
else
{
/* In some cases, like VOBJ reading, the domain passed is NULL here so be careful when initializing the value.
* If it is NULL, it will be read when the set is unpacked. */
if (!domain)
{
db_value_domain_init (value, DB_TYPE_SET, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), domain->precision, domain->scale);
}
/* If size is zero, we have nothing to do, if size is -1, just go ahead and unpack the set. */
if (!size)
{
db_make_set (value, NULL);
}
else if (copy)
{
set = or_get_set (buf, domain);
if (set == NULL)
{
return ER_FAILED;
}
else
{
ref = setobj_get_reference (set);
if (ref == NULL)
{
return ER_FAILED;
}
else
{
switch (set_get_type (ref))
{
case DB_TYPE_SET:
db_make_set (value, ref);
break;
case DB_TYPE_MULTISET:
db_make_multiset (value, ref);
break;
case DB_TYPE_SEQUENCE:
db_make_sequence (value, ref);
break;
default:
break;
}
}
}
}
else
{
/* copy == false, which means don't translate it into memory rep */
ref = set_make_reference ();
if (ref == NULL)
{
return ER_FAILED;
}
else
{
int disk_size;
DB_TYPE set_type;
if (size != -1)
{
char *set_st;
int num_elements, has_domain, bound_bits, offset_tbl, el_tags;
disk_size = size;
/* unfortunately, we still need to look at the header to find out the set type. */
set_st = buf->ptr;
or_get_set_header (buf, &set_type, &num_elements, &has_domain, &bound_bits, &offset_tbl, &el_tags,
NULL);
/* reset the OR_BUF */
buf->ptr = set_st;
}
else
{
/* we have to go figure the size out */
disk_size = or_disk_set_size (buf, domain, &set_type);
}
/* Record the pointer to the disk bits */
ref->disk_set = buf->ptr;
ref->need_clear = false;
ref->disk_size = disk_size;
ref->disk_domain = domain;
/* advance the buffer as if we had read the set */
rc = or_advance (buf, disk_size);
switch (set_type)
{
case DB_TYPE_SET:
db_make_set (value, ref);
break;
case DB_TYPE_MULTISET:
db_make_multiset (value, ref);
break;
case DB_TYPE_SEQUENCE:
db_make_sequence (value, ref);
break;
default:
break;
}
}
}
}
return rc;
}
static void
mr_freemem_set (void *memptr)
{
/* since we aren't explicitly setting the set to NULL, we must set up the reference structures so they will get the
* new set when it is brought back in, this is the only primitive type for which the free function is semantically
* different than using the setmem function with a NULL value */
SETOBJ **mem = (SETOBJ **) memptr;
if (*mem != NULL)
{
setobj_free (*mem); /* free storage, NULL references */
}
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_set (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
SETOBJ *set1 = NULL, *set2 = NULL;
assert (domain != NULL);
/* is not index type */
assert (!domain->is_desc && !tp_valid_indextype (TP_DOMAIN_TYPE (domain)));
mem1 = or_unpack_set ((char *) mem1, &set1, domain);
mem2 = or_unpack_set ((char *) mem2, &set2, domain);
if (set1 == NULL || set2 == NULL)
{
return DB_UNK;
}
c = setobj_compare_order (set1, set2, do_coercion, total_order);
setobj_free (set1);
setobj_free (set2);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_set (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
return set_compare_order (db_get_set (value1), db_get_set (value2), do_coercion, total_order);
}
/*
* TYPE MULTISET
*/
static void
mr_initval_multiset (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_MULTISET, precision, scale);
db_make_multiset (value, NULL);
}
static int
mr_getmem_multiset (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
SETOBJ **mem = (SETOBJ **) memptr;
int error = NO_ERROR;
SETOBJ *set;
SETREF *ref;
set = *mem;
if (set == NULL)
{
error = db_make_multiset (value, NULL);
}
else
{
ref = setobj_get_reference (set);
if (ref)
{
error = db_make_multiset (value, ref);
}
else
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
(void) db_make_multiset (value, NULL);
}
}
/* NOTE: assumes that ownership info will already have been set or will be set by the caller */
return error;
}
static int
mr_setval_multiset (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return mr_setval_set_internal (dest, src, copy, DB_TYPE_MULTISET);
}
/*
* TYPE SEQUENCE
*/
static void
mr_initval_sequence (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_SEQUENCE, precision, scale);
db_make_sequence (value, NULL);
}
static int
mr_getmem_sequence (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
SETOBJ **mem = (SETOBJ **) memptr;
int error = NO_ERROR;
SETOBJ *set;
SETREF *ref;
set = *mem;
if (set == NULL)
{
error = db_make_sequence (value, NULL);
}
else
{
ref = setobj_get_reference (set);
if (ref)
{
error = db_make_sequence (value, ref);
}
else
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
(void) db_make_sequence (value, NULL);
}
}
/*
* NOTE: assumes that ownership info will already have been set or will
* be set by the caller
*/
return error;
}
static int
mr_setval_sequence (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
return mr_setval_set_internal (dest, src, copy, DB_TYPE_SEQUENCE);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_sequence (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
SETOBJ *seq1 = NULL, *seq2 = NULL;
assert (domain != NULL);
/* is not index type */
assert (!domain->is_desc && !tp_valid_indextype (TP_DOMAIN_TYPE (domain)));
mem1 = or_unpack_set ((char *) mem1, &seq1, domain);
mem2 = or_unpack_set ((char *) mem2, &seq2, domain);
if (seq1 == NULL || seq2 == NULL)
{
return DB_UNK;
}
c = setobj_compare_order (seq1, seq2, do_coercion, total_order);
setobj_free (seq1);
setobj_free (seq2);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_sequence (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
return set_seq_compare (db_get_set (value1), db_get_set (value2), do_coercion, total_order);
}
/*
* TYPE MIDXKEY
*/
static void
mr_initval_midxkey (DB_VALUE * value, int precision, int scale)
{
DB_MIDXKEY *midxkey = NULL;
db_value_domain_init (value, DB_TYPE_MIDXKEY, precision, scale);
db_make_midxkey (value, midxkey);
}
static int
mr_setval_midxkey (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision;
DB_MIDXKEY dst_idx;
DB_MIDXKEY *src_idx;
if (DB_IS_NULL (src))
{
return db_value_domain_init (dest, DB_TYPE_MIDXKEY, DB_DEFAULT_PRECISION, 0);
}
/* Get information from the value. */
src_idx = db_get_midxkey (src);
src_precision = db_value_precision (src);
if (src_idx == NULL)
{
return db_value_domain_init (dest, DB_TYPE_MIDXKEY, src_precision, 0);
}
if (src_idx->size < 0)
{
dst_idx.size = mr_index_lengthmem_midxkey (src_idx->buf, src_idx->domain);
}
else
{
dst_idx.size = src_idx->size;
}
dst_idx.ncolumns = src_idx->ncolumns;
dst_idx.domain = src_idx->domain;
dst_idx.min_max_val.position = src_idx->min_max_val.position;
dst_idx.min_max_val.type = src_idx->min_max_val.type;
/* should we be paying attention to this? it is extremely dangerous */
if (!copy)
{
dst_idx.buf = src_idx->buf;
error = db_make_midxkey (dest, &dst_idx);
dest->need_clear = false;
}
else
{
dst_idx.buf = (char *) db_private_alloc (NULL, dst_idx.size);
if (dst_idx.buf == NULL)
{
db_value_domain_init (dest, DB_TYPE_MIDXKEY, src_precision, 0);
assert (er_errid () != NO_ERROR);
return er_errid ();
}
memcpy (dst_idx.buf, src_idx->buf, dst_idx.size);
error = db_make_midxkey (dest, &dst_idx);
dest->need_clear = true;
}
return error;
}
static int
mr_data_writeval_midxkey (OR_BUF * buf, DB_VALUE * value)
{
return mr_index_writeval_midxkey (buf, value);
}
static int
mr_index_writeval_midxkey (OR_BUF * buf, DB_VALUE * value)
{
DB_MIDXKEY *midxkey;
int rc;
midxkey = db_get_midxkey (value);
if (midxkey == NULL)
{
return ER_FAILED;
}
rc = or_put_data (buf, (char *) midxkey->buf, midxkey->size);
return rc;
}
static int
mr_data_readval_midxkey (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_index_readval_midxkey (buf, value, domain, size, copy, copy_buf, copy_buf_len);
}
static int
mr_index_readval_midxkey (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
char *new_;
DB_MIDXKEY midxkey;
int rc = NO_ERROR;
TP_DOMAIN *dom;
if (size == -1)
{ /* unknown size */
size = mr_index_lengthmem_midxkey (buf->ptr, domain);
}
if (size <= 0)
{
assert (false);
return ER_FAILED;
}
if (value == NULL)
{
return or_advance (buf, size);
}
midxkey.size = size;
midxkey.domain = domain;
midxkey.min_max_val.position = -1;
midxkey.min_max_val.type = MIN_COLUMN;
midxkey.ncolumns = domain->precision;
if (!copy)
{
midxkey.buf = buf->ptr;
db_make_midxkey (value, &midxkey);
rc = or_advance (buf, size);
}
else
{
if (copy_buf && copy_buf_len >= size)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/*
* Allocate storage for the string
* do not include the kludge NULL terminator
*/
new_ = (char *) db_private_alloc (NULL, size);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), TP_FLOATING_PRECISION_VALUE, 0);
return ER_FAILED;
}
else
{
rc = or_get_data (buf, new_, size);
if (rc == NO_ERROR)
{
/* round up to a word boundary */
/* rc = or_get_align32 (buf); *//* need ?? */
}
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return rc;
}
midxkey.buf = new_;
db_make_midxkey (value, &midxkey);
value->need_clear = (new_ != copy_buf) ? true : false;
}
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
pr_midxkey_compare_element (char *mem1, char *mem2, TP_DOMAIN * dom1, TP_DOMAIN * dom2, int do_coercion,
int total_order)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
DB_VALUE val1, val2;
bool error = false;
OR_BUF buf_val1, buf_val2;
bool comparable = true;
if (dom1->is_desc != dom2->is_desc)
{
assert (false);
return DB_UNK; /* impossible case */
}
or_init (&buf_val1, mem1, -1);
or_init (&buf_val2, mem2, -1);
db_make_null (&val1);
db_make_null (&val2);
if (dom1->type->index_readval (&buf_val1, &val1, dom1, -1, false, NULL, 0) != NO_ERROR)
{
error = true;
goto clean_up;
}
if (dom2->type->index_readval (&buf_val2, &val2, dom2, -1, false, NULL, 0) != NO_ERROR)
{
error = true;
goto clean_up;
}
c = tp_value_compare_with_error (&val1, &val2, do_coercion, total_order, &comparable);
clean_up:
if (DB_NEED_CLEAR (&val1))
{
pr_clear_value (&val1);
}
if (DB_NEED_CLEAR (&val2))
{
pr_clear_value (&val2);
}
if (!comparable || error == true)
{
return DB_UNK;
}
return c;
}
DB_VALUE_COMPARE_RESULT
pr_midxkey_compare (DB_MIDXKEY * mul1, DB_MIDXKEY * mul2, int do_coercion, int total_order, int num_index_term,
int *start_colp, int *diff_column, bool * dom_is_desc, int *result_size)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
int i;
TP_DOMAIN *dom1, *dom2;
char *nullmap_ptr1, *nullmap_ptr2;
char *mem1, *mem2;
int offset1, offset2;
int last;
assert (total_order == 1);
if (total_order == 0)
{
/* unknown case */
return DB_UNK;
}
assert (mul1->domain != NULL);
assert (TP_DOMAIN_TYPE (mul1->domain) == DB_TYPE_MIDXKEY);
assert (mul1->domain->setdomain != NULL);
assert (mul2->domain != NULL);
assert (TP_DOMAIN_TYPE (mul2->domain) == DB_TYPE_MIDXKEY);
assert (mul2->domain->setdomain != NULL);
assert (mul1->ncolumns == mul2->ncolumns);
assert (mul1->domain->precision == mul2->domain->precision);
/* safe guard */
if (mul1->domain == NULL || TP_DOMAIN_TYPE (mul1->domain) != DB_TYPE_MIDXKEY || mul1->domain->setdomain == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_MR_NULL_DOMAIN, 0);
return DB_UNK;
}
/* safe guard */
if (mul2->domain == NULL || TP_DOMAIN_TYPE (mul2->domain) != DB_TYPE_MIDXKEY || mul2->domain->setdomain == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_MR_NULL_DOMAIN, 0);
return DB_UNK;
}
/* safe guard */
if (mul1->ncolumns != mul2->ncolumns || mul1->domain->precision != mul2->domain->precision)
{
return DB_UNK;
}
#if !defined(NDEBUG)
{
int dom_ncols = 0; /* init */
for (dom1 = mul1->domain->setdomain; dom1; dom1 = dom1->next)
{
dom_ncols++;
}
if (dom_ncols <= 0)
{
assert (false);
return DB_UNK;
}
assert (dom_ncols == mul1->domain->precision);
}
#endif /* NDEBUG */
nullmap_ptr1 = mul1->buf;
nullmap_ptr2 = mul2->buf;
last = or_multi_header_size (mul1->domain->precision);
mem1 = mul1->buf + last;
mem2 = mul2->buf + last;
dom1 = mul1->domain->setdomain;
dom2 = mul2->domain->setdomain;
last = (num_index_term > 0) ? num_index_term : mul1->ncolumns;
i = 0;
if (start_colp && *start_colp > 0)
{
offset1 = or_multi_get_element_offset (nullmap_ptr1, mul1->domain->precision, *start_colp);
offset2 = or_multi_get_element_offset (nullmap_ptr2, mul2->domain->precision, *start_colp);
/* fallthrough: i, dom1, dom2 */
if (offset1 > 0)
{
if (offset2 > 0)
{
mem1 = mul1->buf + offset1;
mem2 = mul2->buf + offset2;
for (; i < *start_colp; i++, dom1 = dom1->next, dom2 = dom2->next)
{
assert (dom1 != NULL);
assert (dom2 != NULL);
assert (dom1->is_desc == dom2->is_desc);
}
}
else
{
mem1 = mul1->buf + offset1;
for (; i < *start_colp; i++, dom1 = dom1->next, dom2 = dom2->next)
{
assert (dom1 != NULL);
assert (dom2 != NULL);
assert (dom1->is_desc == dom2->is_desc);
if (or_multi_is_not_null (nullmap_ptr2, i))
{
mem2 += pr_midxkey_element_disk_size (mem2, dom2);
}
}
}
}
else if (offset2 > 0)
{
mem2 = mul2->buf + offset2;
for (; i < *start_colp; i++, dom1 = dom1->next, dom2 = dom2->next)
{
if (or_multi_is_not_null (nullmap_ptr1, i))
{
assert (dom1 != NULL);
assert (dom2 != NULL);
assert (dom1->is_desc == dom2->is_desc);
mem1 += pr_midxkey_element_disk_size (mem1, dom1);
}
}
}
else
{
for (; i < *start_colp; i++, dom1 = dom1->next, dom2 = dom2->next)
{
assert (dom1 != NULL);
assert (dom2 != NULL);
assert (dom1->is_desc == dom2->is_desc);
if (or_multi_is_not_null (nullmap_ptr1, i))
{
mem1 += pr_midxkey_element_disk_size (mem1, dom1);
}
if (or_multi_is_not_null (nullmap_ptr2, i))
{
mem2 += pr_midxkey_element_disk_size (mem2, dom2);
}
}
}
}
/* fallthrough: i, dom1, dom2 */
for (c = DB_EQ; i < last; i++, dom1 = dom1->next, dom2 = dom2->next)
{
if (dom1 == NULL || dom2 == NULL || dom1->is_desc != dom2->is_desc)
{
assert (false);
return DB_UNK;
}
if (or_multi_is_not_null (nullmap_ptr1, i))
{
if (or_multi_is_not_null (nullmap_ptr2, i))
{
/* check for val1 and val2 same domain */
if (dom1 == dom2 || tp_domain_match (dom1, dom2, TP_EXACT_MATCH))
{
c = dom1->type->index_cmpdisk (mem1, mem2, dom1, do_coercion, total_order, NULL);
}
else
{
/* coercion and comparison
* val1 and val2 have different domain
*/
c = pr_midxkey_compare_element (mem1, mem2, dom1, dom2, do_coercion, total_order);
}
if (c == DB_EQ)
{
mem1 += pr_midxkey_element_disk_size (mem1, dom1);
mem2 += pr_midxkey_element_disk_size (mem2, dom2);
continue;
}
}
else
{
/* val 1 bound, val 2 unbound */
if (mul2->min_max_val.position == i)
{
/* safeguard */
assert (mul2->min_max_val.type == MIN_COLUMN || mul2->min_max_val.type == MAX_COLUMN);
c = (mul2->min_max_val.type == MIN_COLUMN) ? DB_GT : DB_LT;
}
else
{
c = DB_GT;
}
}
}
else if (or_multi_is_not_null (nullmap_ptr2, i))
{
/* val 1 unbound, val 2 bound */
if (mul1->min_max_val.position == i)
{
/* safeguard */
assert (mul1->min_max_val.type == MIN_COLUMN || mul1->min_max_val.type == MAX_COLUMN);
c = (mul1->min_max_val.type == MIN_COLUMN) ? DB_LT : DB_GT;
}
else
{
c = DB_LT;
}
}
else
{
/* val 1 unbound, val 2 unbound */
/* SPECIAL_COLUMN_MIN > NULL */
if (mul1->min_max_val.position == i)
{
if (mul2->min_max_val.position == i)
{
MIN_MAX_COLUMN_TYPE type1 = mul1->min_max_val.type;
MIN_MAX_COLUMN_TYPE type2 = mul2->min_max_val.type;
c = (type1 == type2) ? DB_EQ : ((type1 == MIN_COLUMN) ? DB_LT : DB_GT);
}
else
{
assert (mul1->min_max_val.type == MIN_COLUMN || mul1->min_max_val.type == MAX_COLUMN);
c = (mul1->min_max_val.type == MIN_COLUMN) ? DB_LT : DB_GT;
}
}
else if (mul2->min_max_val.position == i)
{
assert (mul2->min_max_val.type == MIN_COLUMN || mul2->min_max_val.type == MAX_COLUMN);
c = (mul2->min_max_val.type == MIN_COLUMN) ? DB_GT : DB_LT;
}
else
{
c = DB_EQ;
continue;
}
}
break; /* exit for-loop */
}
if (start_colp != NULL)
{
if (c != DB_EQ)
{
/* save the start position of non-equal-value column */
*start_colp = i;
}
}
if (result_size)
{
result_size[0] = CAST_BUFLEN (mem1 - mul1->buf);
result_size[1] = CAST_BUFLEN (mem2 - mul2->buf);
if (c != DB_EQ)
{
if (dom1 != NULL && or_multi_is_not_null (nullmap_ptr1, i))
{
result_size[0] += pr_midxkey_element_disk_size (mem1, dom1);
}
if (dom2 != NULL && or_multi_is_not_null (nullmap_ptr2, i))
{
result_size[1] += pr_midxkey_element_disk_size (mem2, dom2);
}
}
}
*diff_column = i;
if (dom_is_desc)
{
if (dom1)
{
dom_is_desc[0] = dom1->is_desc;
dom_is_desc[1] = dom1->next ? dom1->next->is_desc : false;
}
else
{
dom_is_desc[0] = dom_is_desc[1] = false;
}
}
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_midxkey (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
DB_MIDXKEY *midxkey1;
DB_MIDXKEY *midxkey2;
int dummy_diff_column;
midxkey1 = db_get_midxkey (value1);
midxkey2 = db_get_midxkey (value2);
if (midxkey1 == NULL || midxkey2 == NULL)
{
assert_release (false); /* error */
return DB_UNK;
}
if (midxkey1 == midxkey2)
{
if (total_order)
{
return DB_EQ;
}
assert_release (false); /* error */
return DB_UNK;
}
assert_release (midxkey1->domain != NULL);
assert_release (midxkey1->domain->precision == midxkey1->ncolumns);
assert_release (midxkey2->domain != NULL);
assert_release (midxkey2->domain->precision == midxkey2->ncolumns);
c =
(DB_VALUE_COMPARE_RESULT) pr_midxkey_compare (midxkey1, midxkey2, do_coercion, total_order, -1, start_colp,
&dummy_diff_column, NULL, NULL);
assert_release (c == DB_UNK || (DB_LT <= c && c <= DB_GT));
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_midxkey (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (false);
assert (domain != NULL);
return mr_index_cmpdisk_midxkey (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_midxkey (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
DB_MIDXKEY midxkey1;
DB_MIDXKEY midxkey2;
TP_DOMAIN *cmp_dom;
int n_atts = 0;
int dummy_diff_column;
assert (false);
assert (domain != NULL && !domain->is_desc);
assert (mem1 != NULL);
assert (mem2 != NULL);
if (mem1 == NULL || mem2 == NULL)
{
assert (false); /* error */
return DB_UNK;
}
if (mem1 == mem2)
{
if (total_order)
{
return DB_EQ;
}
assert (false); /* error */
return DB_UNK;
}
midxkey1.buf = (char *) mem1;
midxkey2.buf = (char *) mem2;
n_atts = 0;
for (cmp_dom = domain->setdomain; cmp_dom; cmp_dom = cmp_dom->next)
{
n_atts++;
}
midxkey1.size = midxkey2.size = -1; /* is dummy */
midxkey1.ncolumns = midxkey2.ncolumns = n_atts;
midxkey1.domain = midxkey2.domain = domain;
c =
pr_midxkey_compare (&midxkey1, &midxkey2, do_coercion, total_order, -1, start_colp, &dummy_diff_column, NULL, NULL);
assert (c == DB_UNK || (DB_LT <= c && c <= DB_GT));
return c;
}
static int
mr_data_lengthmem_midxkey (void *memptr, TP_DOMAIN * domain, int disk)
{
return mr_index_lengthmem_midxkey (memptr, domain);
}
static int
mr_index_lengthmem_midxkey (void *memptr, TP_DOMAIN * domain)
{
char *nullmap_ptr, *buf_ptr;
TP_DOMAIN *dom;
int idx_ncols = 0, i;
int offset, advance_size;
int len;
idx_ncols = domain->precision;
if (idx_ncols <= 0)
{
assert (false);
goto exit_on_error; /* give up */
}
/* There is no difference between the disk & memory sizes. */
nullmap_ptr = (char *) memptr;
#if !defined (NDEBUG)
{
buf_ptr = nullmap_ptr + or_multi_header_size (idx_ncols);
for (i = 0, dom = domain->setdomain; dom; i++, dom = dom->next)
{
/* check for val is NULL */
if (or_multi_is_null (nullmap_ptr, i))
{
continue; /* zero size; go ahead */
}
/* at here, val is non-NULL */
buf_ptr += pr_midxkey_element_disk_size (buf_ptr, dom);
}
if (i <= 0)
{
assert (false);
goto exit_on_error;
}
assert (i == idx_ncols);
}
#endif /* NDEBUG */
offset = or_multi_get_size_offset (nullmap_ptr, idx_ncols);
if (offset > 0)
{
assert (offset == CAST_BUFLEN (buf_ptr - nullmap_ptr));
return offset;
}
else
{
buf_ptr = nullmap_ptr + or_multi_header_size (idx_ncols);
for (i = 0, dom = domain->setdomain; i < idx_ncols; i++, dom = dom->next)
{
/* check for val is NULL */
if (or_multi_is_null (nullmap_ptr, i))
{
continue; /* zero size; go ahead */
}
/* at here, val is non-NULL */
buf_ptr += pr_midxkey_element_disk_size (buf_ptr, dom);
}
}
/* set buf size */
len = CAST_BUFLEN (buf_ptr - nullmap_ptr);
exit_on_end:
return len;
exit_on_error:
len = -1; /* set error */
goto exit_on_end;
}
static int
mr_data_lengthval_midxkey (DB_VALUE * value, int disk)
{
return mr_index_lengthval_midxkey (value);
}
static int
mr_index_lengthval_midxkey (DB_VALUE * value)
{
int len;
if (DB_IS_NULL (value))
{
return 0;
}
len = value->data.midxkey.size;
return len;
}
/*
* TYPE VOBJ
*
* This is used only for virtual object keys in SQL/M.
* Internal structures identical to sequences.
*/
static void
mr_initval_vobj (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_VOBJ, precision, scale);
}
static int
mr_setval_vobj (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error;
error = mr_setval_sequence (dest, src, copy);
db_value_alter_type (dest, DB_TYPE_VOBJ);
return error;
}
static int
mr_data_readval_vobj (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
if (mr_data_readval_set (buf, value, &tp_Sequence_domain, size, copy, copy_buf, copy_buf_len) != NO_ERROR)
{
return ER_FAILED;
}
if (value)
{
db_value_alter_type (value, DB_TYPE_VOBJ);
}
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_vobj (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
SETOBJ *seq1 = NULL, *seq2 = NULL;
assert (domain != NULL);
/* is not index type */
assert (!domain->is_desc && !tp_valid_indextype (TP_DOMAIN_TYPE (domain)));
mem1 = or_unpack_set ((char *) mem1, &seq1, domain);
mem2 = or_unpack_set ((char *) mem2, &seq2, domain);
if (seq1 == NULL || seq2 == NULL)
{
return DB_UNK;
}
c = setvobj_compare (seq1, seq2, do_coercion, total_order);
setobj_free (seq1);
setobj_free (seq2);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_vobj (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
return vobj_compare (db_get_set (value1), db_get_set (value2), do_coercion, total_order);
}
/*
* TYPE NUMERIC
*/
static void
mr_initmem_numeric (void *memptr, TP_DOMAIN * domain)
{
assert (!IS_FLOATING_PRECISION (domain->precision));
memset (memptr, 0, MR_NUMERIC_SIZE (domain->precision));
}
/*
* Due to the "within tolerance" domain comparison used during attribute
* assignment validation, we may receive a numeric whose precision is less
* then the actual precision of the attribute. In that case we should be doing
* an on-the-fly coercion here.
*/
static int
mr_setmem_numeric (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
int src_precision, src_scale, byte_size;
DB_C_NUMERIC num, src_num;
if (value == NULL)
{
mr_initmem_numeric (mem, domain);
}
else
{
src_num = db_get_numeric (value);
src_precision = db_value_precision (value);
src_scale = db_value_scale (value);
/* this should have been handled by now */
if (src_num == NULL || src_precision != domain->precision || src_scale != domain->scale)
{
error = ER_OBJ_DOMAIN_CONFLICT;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
else
{
num = (DB_C_NUMERIC) mem;
byte_size = MR_NUMERIC_SIZE (src_precision);
memcpy (num, src_num, byte_size);
}
}
return error;
}
static int
mr_getmem_numeric (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
DB_C_NUMERIC num;
if (value == NULL)
{
return error;
}
num = (DB_C_NUMERIC) mem;
error = db_make_numeric (value, num, domain->precision, domain->scale);
value->need_clear = false;
return error;
}
static void
mr_data_writemem_numeric (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
int disk_size;
disk_size = OR_NUMERIC_SIZE (domain->precision);
or_put_data (buf, (char *) mem, disk_size);
}
static void
mr_data_readmem_numeric (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
/* if stored size is unknown, the domain precision must be set correctly */
if (size < 0)
{
size = OR_NUMERIC_SIZE (domain->precision);
}
if (mem == NULL)
{
if (size)
{
or_advance (buf, size);
}
}
else if (size)
{
if (size != OR_NUMERIC_SIZE (domain->precision))
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return;
}
else
{
or_get_data (buf, (char *) mem, size);
}
}
}
static int
mr_index_lengthmem_numeric (void *mem, TP_DOMAIN * domain)
{
return mr_data_lengthmem_numeric (mem, domain, 1);
}
static int
mr_data_lengthmem_numeric (void *mem, TP_DOMAIN * domain, int disk)
{
int len;
/* think about caching this in the domain so we don't have to calculate it */
if (disk)
{
len = OR_NUMERIC_SIZE (domain->precision);
}
else
{
len = MR_NUMERIC_SIZE (domain->precision);
}
return len;
}
static void
mr_initval_numeric (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_NUMERIC, precision, scale);
}
static int
mr_setval_numeric (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision, src_scale;
DB_C_NUMERIC src_numeric;
assert (!db_value_is_corrupted (src));
if (src == NULL || DB_IS_NULL (src))
{
db_value_domain_init (dest, DB_TYPE_NUMERIC, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
else
{
src_precision = db_value_precision (src);
src_scale = db_value_scale (src);
src_numeric = (DB_C_NUMERIC) db_get_numeric (src);
if (DB_IS_NULL (src) || src_numeric == NULL)
{
db_value_domain_init (dest, DB_TYPE_NUMERIC, src_precision, src_scale);
}
else
{
/*
* Because numerics are stored in an inline buffer, there is no
* difference between the copy and non-copy operations, this may
* need to change.
*/
error = db_make_numeric (dest, src_numeric, src_precision, src_scale);
}
}
return error;
}
static int
mr_index_lengthval_numeric (DB_VALUE * value)
{
return mr_data_lengthval_numeric (value, 1);
}
static int
mr_data_lengthval_numeric (DB_VALUE * value, int disk)
{
int precision, len;
len = 0;
if (value != NULL)
{
/* better have a non-NULL value by the time writeval is called ! */
precision = db_value_precision (value);
if (disk)
{
len = OR_NUMERIC_SIZE (precision);
}
else
{
len = MR_NUMERIC_SIZE (precision);
}
}
return len;
}
static int
mr_index_writeval_numeric (OR_BUF * buf, DB_VALUE * value)
{
return mr_data_writeval_numeric (buf, value);
}
static int
mr_data_writeval_numeric (OR_BUF * buf, DB_VALUE * value)
{
DB_C_NUMERIC numeric;
int precision, disk_size;
int rc = NO_ERROR;
if (value != NULL)
{
numeric = db_get_numeric (value);
if (numeric != NULL)
{
precision = db_value_precision (value);
disk_size = OR_NUMERIC_SIZE (precision);
rc = or_put_data (buf, (char *) numeric, disk_size);
}
}
return rc;
}
static int
mr_index_readval_numeric (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_data_readval_numeric (buf, value, domain, size, copy, copy_buf, copy_buf_len);
}
static int
mr_data_readval_numeric (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
if (domain == NULL)
{
return ER_FAILED;
}
/*
* If size is -1, the caller doesn't know the size and we must determine
* it from the domain.
*/
if (size == -1)
{
size = OR_NUMERIC_SIZE (domain->precision);
}
if (size == 1)
{
size = OR_NUMERIC_SIZE (domain->precision);
}
if (value == NULL)
{
if (size)
{
rc = or_advance (buf, size);
}
}
else
{
/*
* the copy and no copy cases are identical because db_make_numeric
* will copy the bits into its internal buffer.
*/
(void) db_make_numeric (value, (DB_C_NUMERIC) buf->ptr, domain->precision, domain->scale);
value->need_clear = false;
rc = or_advance (buf, size);
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_numeric (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_data_cmpdisk_numeric (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_numeric (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
OR_BUF buf;
DB_VALUE value1, value2;
DB_VALUE answer;
int rc = NO_ERROR;
assert (domain != NULL);
or_init (&buf, (char *) mem1, 0);
rc = mr_data_readval_numeric (&buf, &value1, domain, -1, 0, NULL, 0);
if (rc != NO_ERROR)
{
return DB_UNK;
}
or_init (&buf, (char *) mem2, 0);
rc = mr_data_readval_numeric (&buf, &value2, domain, -1, 0, NULL, 0);
if (rc != NO_ERROR)
{
return DB_UNK;
}
rc = numeric_db_value_compare (&value1, &value2, &answer);
if (rc != NO_ERROR)
{
return DB_UNK;
}
c = MR_CMP_RETURN_CODE (db_get_int (&answer));
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_numeric (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
DB_VALUE answer;
if (numeric_db_value_compare (value1, value2, &answer) != NO_ERROR)
{
return DB_UNK;
}
if (db_get_int (&answer) < 0)
{
c = DB_LT;
}
else
{
if (db_get_int (&answer) > 0)
{
c = DB_GT;
}
else
{
c = DB_EQ;
}
}
return c;
}
/*
* PRIMITIVE TYPE SUPPORT ROUTINES
*/
/*
* pr_type_from_id - maps a type identifier such as DB_TYPE_INTEGER into its
* corresponding primitive type descriptor structures.
* return: type descriptor
* id(in): type identifier constant
*/
const PR_TYPE *
pr_type_from_id (DB_TYPE id)
{
const PR_TYPE *type = NULL;
if (id <= DB_TYPE_LAST && id != DB_TYPE_TABLE)
{
type = tp_Type_id_map[(int) id];
}
return type;
}
/*
* pr_type_name - Returns the string type name associated with a type constant.
* return: type name
* id(in): type identifier constant
* Note:
* The string must not be freed after use.
*/
const char *
pr_type_name (DB_TYPE id)
{
const char *name = NULL;
const PR_TYPE *type;
type = pr_type_from_id (id);
if (type != NULL)
{
name = type->name;
}
return name;
}
/*
* pr_is_variable_type - determine whether or not a type is fixed or variable
* width on disk.
* return: non-zero if this is a variable width type
* id(in): type id
* Note:
* With the advent of parameterized types like CHAR(n), NUMERIC(p,s) etc.
* this doesn't mean that all values of this type will be the same size,
* it means that for any particular attribute of a class, they will all be
* the same size and the value will be stored in the "fixed" region of the
* disk representation.
*/
int
pr_is_variable_type (DB_TYPE id)
{
const PR_TYPE *type;
int is_variable = 0;
type = pr_type_from_id (id);
if (type != NULL)
{
is_variable = type->variable_p;
}
return is_variable;
}
/*
* pr_find_type - Locate a type descriptor given a name.
* return: type structure
* name(in): type name
* Note:
* Called by the schema manager to map a domain name into a primitive
* type.
* This now recognizes some alias names for a few of the types.
* The aliases should be more centrally defined so the parser can
* check for them.
*
*/
const PR_TYPE *
pr_find_type (const char *name)
{
const PR_TYPE *type, *found;
int i;
if (name == NULL)
{
return NULL;
}
found = NULL;
for (i = DB_TYPE_FIRST; i <= DB_TYPE_LAST && found == NULL; i++)
{
type = tp_Type_id_map[i];
if (type->name != NULL)
{
if (intl_mbs_casecmp (name, type->name) == 0)
{
found = type;
}
}
}
/* alias kludge */
if (found == NULL)
{
if (intl_mbs_casecmp (name, "int") == 0)
{
found = tp_Type_integer;
}
else if (intl_mbs_casecmp (name, "multi_set") == 0)
{
found = tp_Type_multiset;
}
else if (intl_mbs_casecmp (name, "short") == 0)
{
found = tp_Type_short;
}
else if (intl_mbs_casecmp (name, "string") == 0)
{
found = tp_Type_string;
}
else if (intl_mbs_casecmp (name, "utime") == 0)
{
found = tp_Type_utime;
}
else if (intl_mbs_casecmp (name, "list") == 0)
{
found = tp_Type_sequence;
}
}
return found;
}
/*
* SIZE CALCULATORS
* These operation on the instance memory format of data values.
*/
/*
* pr_mem_size - Determine the number of bytes required for the memory
* representation of a particular type.
* return: memory size of type
* type(in): const PR_TYPE structure
* Note:
* This only determines the size for an attribute value in contiguous
* memory storage for an instance.
* It does not include the size of any reference memory (like strings.
* For strings, it returns the size of the pointer NOT the length
* of the string.
*
*/
int
pr_mem_size (const PR_TYPE * type)
{
return type->size;
}
/*
* DB_VALUE TRANSFORMERS
*
* Used in the storage of class objects.
* Need to fully extend this into the variabe type above so these can
* be used at attribute values as well.
*
* Predicate processor must be able to understand these if we can issue
* queries on these.
*
* This needs to be merged with the partially implemented support
* for tp_Type_variable above.
*
* These functions will be called with a DB_DATA union NOT a pointer to
* the memory representation of an attribute.
*/
/*
* pr_value_mem_size - Returns the amount of storage necessary to hold the
* contents of a DB_VALUE.
* return: byte size used by contents of DB_VALUE
* value(in): value to examine
* Note:
* Does not include the amount of space necessary for the DB_VALUE.
* Used by some statistics modules that calculate memory sizes of structures.
*/
int
pr_value_mem_size (const DB_VALUE * value)
{
const PR_TYPE *type;
DB_TYPE dbval_type;
dbval_type = DB_VALUE_DOMAIN_TYPE (value);
type = pr_type_from_id (dbval_type);
assert (type != NULL);
if (type != NULL)
{
return type->get_mem_size_of_value (value);
}
else
{
return 0;
}
}
/*
* pr_midxkey_get_vals_size() -
* return: int
* domains(in) :
* dbvals(in) :
* total(in) :
*
*/
static int
pr_midxkey_get_vals_size (TP_DOMAIN * domains, DB_VALUE * dbvals, int total)
{
TP_DOMAIN *dom;
int i;
for (dom = domains, i = 0; dom; dom = dom->next, i++)
{
if (DB_IS_NULL (&dbvals[i]))
{
continue;
}
total += pr_index_writeval_disk_size (&dbvals[i]);
}
return total;
}
/*
* pr_midxkey_get_element_offset - Returns element offset of midxkey
* return:
* midxkey(in):
* index(in):
*/
int
pr_midxkey_get_element_offset (const DB_MIDXKEY * midxkey, int index)
{
TP_DOMAIN *domain;
int idx_ncols = 0, i;
OR_BUF buf;
char *nullmap_ptr;
int offset, advance_size;
idx_ncols = midxkey->domain->precision;
if (idx_ncols <= 0)
{
assert (false);
goto exit_on_error;
}
if (index >= midxkey->ncolumns)
{
assert (false);
goto exit_on_error;
}
/* get domain list, attr number */
domain = midxkey->domain->setdomain; /* first element's domain */
or_init (&buf, midxkey->buf, midxkey->size);
nullmap_ptr = midxkey->buf;
if (or_advance (&buf, or_multi_header_size (idx_ncols)) != NO_ERROR)
{
goto exit_on_error;
}
offset = or_multi_get_element_offset (nullmap_ptr, idx_ncols, index);
if (offset > 0)
{
return offset;
}
else
{
for (i = 0; i < index; i++, domain = domain->next)
{
/* check for element is NULL */
if (or_multi_is_null (nullmap_ptr, i))
{
continue;
}
advance_size = pr_midxkey_element_disk_size (buf.ptr, domain);
or_advance (&buf, advance_size);
}
}
if (er_errid () != NO_ERROR)
{
goto exit_on_error;
}
return CAST_BUFLEN (buf.ptr - buf.buffer);
exit_on_error:
assert (false);
return -1;
}
/*
* pr_midxkey_add_prefix -
*
* return:
* prefix(in):
* postfix(in):
* result(out):
* n_prefix(in):
*/
int
pr_midxkey_add_prefix (DB_VALUE * result, DB_VALUE * prefix, DB_VALUE * postfix, int n_prefix)
{
int i, offset, offset_postfix, offset_prefix;
DB_MIDXKEY *midx_prefix, *midx_postfix;
DB_MIDXKEY midx_result;
int prefix_size;
assert (DB_VALUE_TYPE (prefix) == DB_TYPE_MIDXKEY);
assert (DB_VALUE_TYPE (postfix) == DB_TYPE_MIDXKEY);
midx_prefix = db_get_midxkey (prefix);
midx_postfix = db_get_midxkey (postfix);
offset_prefix = pr_midxkey_get_element_offset (midx_prefix, n_prefix);
offset_postfix = pr_midxkey_get_element_offset (midx_postfix, n_prefix);
midx_result.size = offset_prefix + (midx_postfix->size - offset_postfix);
midx_result.buf = (char *) db_private_alloc (NULL, midx_result.size);
if (midx_result.buf == NULL)
{
return ER_FAILED;
}
midx_result.domain = midx_postfix->domain;
midx_result.ncolumns = midx_postfix->ncolumns;
memcpy (midx_result.buf, midx_prefix->buf, offset_prefix);
memcpy (midx_result.buf + offset_prefix, midx_postfix->buf + offset_postfix, midx_postfix->size - offset_postfix);
#if !defined(NDEBUG)
for (i = 0; i < n_prefix; i++)
{
/* Compressed columns must be null. */
assert (or_multi_is_null (midx_postfix->buf, i));
}
#endif
i = n_prefix;
prefix_size = offset_prefix - or_multi_header_size (midx_prefix->domain->precision);
if (prefix_size < OR_MULTI_MAX_OFFSET)
{
/* fallthrough: i */
for (; i < midx_postfix->domain->precision; i++)
{
/* update nullmap */
if (or_multi_is_not_null (midx_postfix->buf, i))
{
or_multi_set_not_null (midx_result.buf, i);
}
else
{
/* The lower fence key stores from the first column to the columns that begin to differ when compared
* to the upper fence key of the previous page. The number of columns in which the fence key stores
* the value is unrelated to whether or not it is compressed. Therefore, even for columns after prefix,
* it is not guaranteed that the fence key will always store null. */
or_multi_set_null (midx_result.buf, i);
}
/* update offset */
offset = or_multi_get_next_element_offset (midx_postfix->buf, midx_postfix->domain->precision, i);
if (offset > 0 && (offset + prefix_size) < OR_MULTI_MAX_OFFSET)
{
or_multi_put_next_element_offset (midx_result.buf, midx_result.domain->precision, offset + prefix_size,
i);
}
else
{
break;
}
}
}
assert (prefix_size >= OR_MULTI_MAX_OFFSET || i == midx_postfix->domain->precision || offset <= 0);
/* fallthrough: i */
for (; i < midx_postfix->domain->precision; i++)
{
/* update nullmap */
if (or_multi_is_not_null (midx_postfix->buf, i))
{
or_multi_set_not_null (midx_result.buf, i);
}
else
{
/* The lower fence key stores from the first column to the columns that begin to differ when compared
* to the upper fence key of the previous page. The number of columns in which the fence key stores
* the value is unrelated to whether or not it is compressed. Therefore, even for columns after prefix,
* it is not guaranteed that the fence key will always store null. */
or_multi_set_null (midx_result.buf, i);
}
/* update offset */
or_multi_put_next_element_offset (midx_result.buf, midx_result.domain->precision, OR_MULTI_MAX_OFFSET, i);
}
midx_result.min_max_val.position = -1;
midx_result.min_max_val.type = MIN_COLUMN;
db_make_midxkey (result, &midx_result);
result->need_clear = true;
assert (midx_result.size == or_multi_get_size_offset (midx_result.buf, midx_result.domain->precision)
|| midx_result.size >= OR_MULTI_MAX_OFFSET);
return NO_ERROR;
}
/*
* pr_midxkey_remove_prefix -
*
* return:
* key(in):
* prefix(in):
*/
int
pr_midxkey_remove_prefix (DB_VALUE * key, int prefix)
{
DB_MIDXKEY *midx_key;
TP_DOMAIN *domain;
char *buf_ptr;
int i, start, offset;
int prefix_size, advance_size;
midx_key = db_get_midxkey (key);
start = pr_midxkey_get_element_offset (midx_key, 0);
offset = pr_midxkey_get_element_offset (midx_key, prefix);
memmove (midx_key->buf + start, midx_key->buf + offset, midx_key->size - offset);
for (i = 0, domain = midx_key->domain->setdomain; i < prefix; i++, domain = domain->next)
{
or_multi_set_null (midx_key->buf, i);
or_multi_put_next_element_offset (midx_key->buf, midx_key->domain->precision, start, i);
}
assert (i == prefix);
assert (domain != midx_key->domain->setdomain);
prefix_size = offset - start;
/* fallthrough: i, domain */
for (; i < midx_key->domain->precision; i++, domain = domain->next)
{
offset = or_multi_get_next_element_offset (midx_key->buf, midx_key->domain->precision, i);
if (offset > 0)
{
or_multi_put_next_element_offset (midx_key->buf, midx_key->domain->precision, offset - prefix_size, i);
}
else
{
break;
}
}
assert (i == midx_key->domain->precision || offset <= 0);
if (i < midx_key->domain->precision)
{
/* recalculate offset */
offset = or_multi_get_element_offset (midx_key->buf, midx_key->domain->precision, i);
assert (offset > 0);
assert (offset < OR_MULTI_MAX_OFFSET);
buf_ptr = midx_key->buf + offset;
/* fallthrough: i, domain */
for (; i < midx_key->domain->precision; i++, domain = domain->next)
{
if (or_multi_is_null (midx_key->buf, i))
{
or_multi_put_next_element_offset (midx_key->buf, midx_key->domain->precision, offset, i);
continue;
}
advance_size = pr_midxkey_element_disk_size (buf_ptr, domain);
if ((offset + advance_size) < OR_MULTI_MAX_OFFSET)
{
or_multi_put_next_element_offset (midx_key->buf, midx_key->domain->precision, offset + advance_size, i);
offset += advance_size;
buf_ptr += advance_size;
}
else
{
break;
}
}
/* fallthrough: i, domain */
for (; i < midx_key->domain->precision; i++, domain = domain->next)
{
or_multi_put_next_element_offset (midx_key->buf, midx_key->domain->precision, OR_MULTI_MAX_OFFSET, i);
}
}
midx_key->size -= prefix_size;
assert (midx_key->size == or_multi_get_size_offset (midx_key->buf, midx_key->domain->precision)
|| midx_key->size >= OR_MULTI_MAX_OFFSET);
return NO_ERROR;
}
/*
* pr_midxkey_common_prefix -
*
* return:
* key1(in):
* key2(in):
*/
int
pr_midxkey_common_prefix (DB_VALUE * key1, DB_VALUE * key2)
{
int diff_column, ret;
DB_MIDXKEY *midx_lf_key, *midx_uf_key;
assert (DB_VALUE_TYPE (key1) == DB_TYPE_MIDXKEY);
assert (DB_VALUE_TYPE (key2) == DB_TYPE_MIDXKEY);
diff_column = 0; /* init */
midx_lf_key = db_get_midxkey (key1);
midx_uf_key = db_get_midxkey (key2);
ret = pr_midxkey_compare (midx_lf_key, midx_uf_key, 0, 1, -1, NULL, &diff_column, NULL, NULL);
if (ret == DB_UNK)
{
assert (false);
diff_column = 0;
}
return diff_column;
}
/*
* pr_midxkey_get_element_internal()
* return:
* midxkey(in) :
* index(in) :
* value(in) :
* copy(in) :
* prev_indexp(in) :
* prev_ptrp(in) :
*/
static int
pr_midxkey_get_element_internal (const DB_MIDXKEY * midxkey, int index, DB_VALUE * value, bool copy, int *prev_indexp,
char **prev_ptrp)
{
TP_DOMAIN *domain;
int idx_ncols;
OR_BUF buf;
char *nullmap_ptr;
int offset, advance_size;
int i;
int error = NO_ERROR;
idx_ncols = midxkey->domain->precision;
if (idx_ncols <= 0)
{
assert (false);
goto exit_on_error;
}
if (index >= midxkey->ncolumns)
{
assert (false);
goto exit_on_error;
}
#if !defined (NDEBUG)
{
int dom_ncols = 0;
for (domain = midxkey->domain->setdomain; domain; domain = domain->next)
{
dom_ncols++;
}
if (dom_ncols <= 0)
{
assert (false);
goto exit_on_error;
}
assert (dom_ncols == idx_ncols);
}
#endif /* NDEBUG */
/* get bit-mask */
nullmap_ptr = midxkey->buf;
/* get domain list, attr number */
domain = midxkey->domain->setdomain; /* first element's domain */
if (or_multi_is_null (nullmap_ptr, index))
{
db_make_null (value);
}
else
{
i = 0;
or_init (&buf, midxkey->buf, midxkey->size);
or_advance (&buf, or_multi_header_size (idx_ncols));
offset = or_multi_get_element_offset (midxkey->buf, idx_ncols, index);
if (offset > 0)
{
or_seek (&buf, offset);
for (i = 0; i < index; i++, domain = domain->next)
{
assert (domain != NULL);
}
}
else
{
if (prev_indexp && prev_ptrp)
{
offset = CAST_BUFLEN (*prev_ptrp - midxkey->buf);
if (*prev_indexp <= 0 || *prev_indexp > index || offset <= 0)
{ /* invalid info */
/* nop */
}
else
{
or_seek (&buf, offset);
for (i = 0; i < *prev_indexp; i++, domain = domain->next)
{
assert (domain != NULL);
}
}
}
for (; i < index; i++, domain = domain->next)
{
/* check for element is NULL */
if (or_multi_is_null (nullmap_ptr, i))
{
continue; /* skip and go ahead */
}
advance_size = pr_midxkey_element_disk_size (buf.ptr, domain);
or_advance (&buf, advance_size);
}
}
error = domain->type->index_readval (&buf, value, domain, -1, copy, NULL, 0);
if (error != NO_ERROR)
{
goto exit_on_error;
}
/* save the next index info */
if (prev_indexp && prev_ptrp)
{
*prev_indexp = index + 1;
*prev_ptrp = buf.ptr;
}
}
exit_on_end:
return error;
exit_on_error:
if (error == NO_ERROR)
{
error = -1; /* set error */
}
goto exit_on_end;
}
/*
* pr_midxkey_unique_prefix () -
* return: NO_ERROR or error code.
*
* db_midxkey1(in) : Left side of compare.
* db_midxkey2(in) : Right side of compare.
* db_result(out) : midxkey such that > midxkey1, and <= midxkey2.
* or < midxkey1, and >= midxkey2 (desc)
*
* Note:
*
*/
int
pr_midxkey_unique_prefix (const DB_VALUE * db_midxkey1, const DB_VALUE * db_midxkey2, DB_VALUE * db_result)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
int i, offset;
int size_buf[2], diff_column;
bool dom_is_desc[2];
int result_size = 0;
char *result_buf;
DB_MIDXKEY *midxkey1, *midxkey2;
DB_MIDXKEY result_midxkey;
/* Assertions */
assert (db_midxkey1 != (DB_VALUE *) NULL);
assert (db_midxkey2 != (DB_VALUE *) NULL);
assert (db_result != (DB_VALUE *) NULL);
midxkey1 = db_get_midxkey (db_midxkey1);
midxkey2 = db_get_midxkey (db_midxkey2);
assert (midxkey1->size != -1);
assert (midxkey2->size != -1);
assert (midxkey1->ncolumns == midxkey2->ncolumns);
assert (midxkey1->domain == midxkey2->domain);
assert (midxkey1->domain->setdomain == midxkey2->domain->setdomain);
c = pr_midxkey_compare (midxkey1, midxkey2, 0, 1, -1, NULL, &diff_column, dom_is_desc, size_buf);
if (dom_is_desc[0])
{
c = ((c == DB_GT) ? DB_LT : (c == DB_LT) ? DB_GT : c);
}
assert (c == DB_LT);
if (c != DB_LT)
{
return (er_errid () == NO_ERROR) ? ER_FAILED : er_errid ();
}
if (size_buf[0] == midxkey1->size || size_buf[1] == midxkey2->size
|| or_multi_is_null (midxkey1->buf, diff_column + 1) || or_multi_is_null (midxkey2->buf, diff_column + 1))
{
/* not found separator: give up */
pr_clone_value (db_midxkey2, db_result);
}
else
{
assert (size_buf[0] < midxkey1->size);
assert (size_buf[1] < midxkey2->size);
if (!dom_is_desc[1])
{
result_buf = midxkey2->buf;
result_size = size_buf[1];
}
else
{
result_buf = midxkey1->buf;
result_size = size_buf[0];
}
result_midxkey.buf = (char *) db_private_alloc (NULL, result_size);
if (result_midxkey.buf == NULL)
{
/* will already be set by memory mgr */
assert (er_errid () != NO_ERROR);
return er_errid ();
}
memcpy (result_midxkey.buf, result_buf, result_size);
result_midxkey.size = result_size;
result_midxkey.domain = midxkey2->domain;
result_midxkey.ncolumns = midxkey2->ncolumns;
offset = or_multi_get_next_element_offset (result_midxkey.buf, result_midxkey.domain->precision, diff_column);
if (offset < 0)
{
offset = OR_MULTI_MAX_OFFSET;
}
for (i = diff_column + 1; i < result_midxkey.domain->precision; i++)
{
or_multi_set_null (result_midxkey.buf, i);
or_multi_put_next_element_offset (result_midxkey.buf, result_midxkey.domain->precision, offset, i);
}
or_multi_put_size_offset (result_midxkey.buf, result_midxkey.domain->precision, result_midxkey.size);
result_midxkey.min_max_val.position = -1;
result_midxkey.min_max_val.type = MIN_COLUMN;
db_make_midxkey (db_result, &result_midxkey);
db_result->need_clear = true;
#if !defined(NDEBUG)
/* midxkey1 < result_midxkey */
c = pr_midxkey_compare (midxkey1, &result_midxkey, 0, 1, -1, NULL, &diff_column, dom_is_desc, NULL);
assert (c == DB_UNK || (DB_LT <= c && c <= DB_GT));
if (dom_is_desc[0])
{
c = ((c == DB_GT) ? DB_LT : (c == DB_LT) ? DB_GT : c);
}
assert (c == DB_LT);
/* result_midxkey <= midxkey2 */
c = pr_midxkey_compare (&result_midxkey, midxkey2, 0, 1, -1, NULL, &diff_column, dom_is_desc, NULL);
assert (c == DB_UNK || (DB_LT <= c && c <= DB_GT));
if (dom_is_desc[0])
{
c = ((c == DB_GT) ? DB_LT : (c == DB_LT) ? DB_GT : c);
}
assert (c == DB_LT || c == DB_EQ);
#endif
}
return NO_ERROR;
}
/*
* pr_midxkey_get_element_nocopy() -
* return: error code
* midxkey(in) :
* index(in) :
* value(in) :
* prev_indexp(in) :
* prev_ptrp(in) :
*/
int
pr_midxkey_get_element_nocopy (const DB_MIDXKEY * midxkey, int index, DB_VALUE * value, int *prev_indexp,
char **prev_ptrp)
{
return pr_midxkey_get_element_internal (midxkey, index, value, false /* not copy */ ,
prev_indexp, prev_ptrp);
}
int
pr_midxkey_add_elements (DB_VALUE * keyval, DB_VALUE * dbvals, int num_dbvals, struct tp_domain *dbvals_domain_list)
{
TP_DOMAIN *dom;
DB_MIDXKEY *midxkey;
int i, total_size, header_size;
char *new_IDXbuf;
char *nullmap_ptr;
OR_BUF buf;
/* phase 1: find old */
midxkey = db_get_midxkey (keyval);
if (midxkey == NULL)
{
return ER_FAILED;
}
if (midxkey->ncolumns > 0 && midxkey->size > 0)
{
assert (midxkey->domain->precision == midxkey->ncolumns + num_dbvals);
header_size = or_multi_header_size (midxkey->domain->precision);
total_size = midxkey->size;
}
else
{
header_size = or_multi_header_size (num_dbvals);
total_size = header_size;
}
/* phase 2: calculate how many bytes need */
total_size = pr_midxkey_get_vals_size (dbvals_domain_list, dbvals, total_size);
/* phase 3: initialize new_IDXbuf */
new_IDXbuf = (char *) db_private_alloc (NULL, total_size);
if (new_IDXbuf == NULL)
{
goto error;
}
or_init (&buf, new_IDXbuf, -1);
nullmap_ptr = new_IDXbuf;
/* phase 4: copy new_IDXbuf from old */
if (midxkey->ncolumns > 0 && midxkey->size > 0)
{
or_put_data (&buf, midxkey->buf, midxkey->size);
}
else
{
or_multi_clear_header (nullmap_ptr, num_dbvals);
or_advance (&buf, header_size);
}
for (i = 0, dom = dbvals_domain_list; i < num_dbvals; i++, dom = dom->next)
{
or_multi_put_element_offset (nullmap_ptr, midxkey->domain->precision, CAST_BUFLEN (buf.ptr - buf.buffer),
midxkey->ncolumns + i);
/* check for added val is NULL */
if (DB_IS_NULL (&dbvals[i]))
{
continue; /* skip and go ahead */
}
dom->type->index_writeval (&buf, &dbvals[i]);
or_multi_set_not_null (nullmap_ptr, midxkey->ncolumns + i);
} /* for (i = 0, ...) */
assert (total_size == CAST_BUFLEN (buf.ptr - buf.buffer));
or_multi_put_size_offset (nullmap_ptr, midxkey->domain->precision, total_size);
/* phase 5: make new multiIDX */
if (midxkey->size > 0)
{
db_private_free_and_init (NULL, midxkey->buf);
midxkey->buf = NULL;
}
midxkey->buf = new_IDXbuf;
midxkey->size = total_size;
midxkey->ncolumns += num_dbvals;
return NO_ERROR;
error:
if (midxkey->buf)
{
db_private_free_and_init (NULL, midxkey->buf);
midxkey->buf = NULL;
}
return ER_FAILED;
}
/* support for SUPPORT_DEDUPLICATE_KEY_MODE */
int
pr_midxkey_add_elements_with_null (DB_VALUE * keyval, DB_VALUE * dbvals, int num_dbvals,
struct tp_domain *dbvals_domain_list, int tail_null_cnt)
{
TP_DOMAIN *dom;
DB_MIDXKEY *midxkey;
int i, total_size, header_size, offset;
char *new_IDXbuf;
char *nullmap_ptr;
OR_BUF buf;
/* phase 1: find old */
midxkey = db_get_midxkey (keyval);
if (midxkey == NULL)
{
return ER_FAILED;
}
assert (midxkey->ncolumns == 0 && midxkey->size == 0);
header_size = or_multi_header_size (num_dbvals + tail_null_cnt);
total_size = header_size;
/* phase 2: calculate how many bytes need */
total_size = pr_midxkey_get_vals_size (dbvals_domain_list, dbvals, total_size);
/* phase 3: initialize new_IDXbuf */
new_IDXbuf = (char *) db_private_alloc (NULL, total_size);
if (new_IDXbuf == NULL)
{
return ER_FAILED;
}
or_init (&buf, new_IDXbuf, -1);
nullmap_ptr = new_IDXbuf;
or_multi_clear_header (nullmap_ptr, num_dbvals + tail_null_cnt);
or_advance (&buf, header_size);
/* phase 4: copy new_IDXbuf from old */
for (i = 0, dom = dbvals_domain_list; i < num_dbvals; i++, dom = dom->next)
{
/* check for added val is NULL */
if (DB_IS_NULL (&dbvals[i]))
{
continue; /* skip and go ahead */
}
dom->type->index_writeval (&buf, &dbvals[i]);
or_multi_set_not_null (nullmap_ptr, midxkey->ncolumns + i);
} /* for (i = 0, ...) */
assert (total_size == CAST_BUFLEN (buf.ptr - buf.buffer));
for (i = num_dbvals; i < (num_dbvals + tail_null_cnt); i++)
{
assert (or_multi_is_null (nullmap_ptr, i));
or_multi_put_element_offset (nullmap_ptr, num_dbvals + tail_null_cnt, total_size, i);
}
or_multi_put_size_offset (nullmap_ptr, midxkey->ncolumns + num_dbvals + tail_null_cnt, total_size);
midxkey->buf = new_IDXbuf;
midxkey->size = total_size;
midxkey->ncolumns += (num_dbvals + tail_null_cnt);
return NO_ERROR;
}
/*
* pr_data_writeval_disk_size - returns the number of bytes that will be
* written by the "writeval" type function for this value.
* return: byte size of disk representation
* value(in): db value
* Note:
* It is generally used prior to writing the value to pre-calculate the
* required size.
* Formerly called pr_value_disk_size.
*
* Note that "writeval" is used for the construction of disk objects,
* and it will leave space for fixed width types that are logically
* NULL. If you need a compressed representation for random values,
* look at the or_put_value family of functions.
*/
int
pr_data_writeval_disk_size (DB_VALUE * value)
{
const PR_TYPE *type;
DB_TYPE dbval_type;
dbval_type = DB_VALUE_DOMAIN_TYPE (value);
type = pr_type_from_id (dbval_type);
assert (type != NULL);
if (type)
{
return type->get_disk_size_of_value (value);
}
return 0;
}
/*
* pr_index_writeval_disk_size - returns the number of bytes that will be
* written by the "index_write" type function for this value.
* return: byte size of disk representation
* value(in): db value
* Note:
*/
int
pr_index_writeval_disk_size (DB_VALUE * value)
{
const PR_TYPE *type;
DB_TYPE dbval_type;
dbval_type = DB_VALUE_DOMAIN_TYPE (value);
type = pr_type_from_id (dbval_type);
assert (type != NULL);
if (type)
{
return type->get_index_size_of_value (value);
}
return 0;
}
void
pr_data_writeval (struct or_buf *buf, DB_VALUE * value)
{
const PR_TYPE *type;
DB_TYPE dbval_type;
dbval_type = DB_VALUE_DOMAIN_TYPE (value);
type = pr_type_from_id (dbval_type);
if (type == NULL)
{
type = tp_Type_null; /* handle strange arguments with NULL */
}
type->data_writeval (buf, value);
}
/*
* MISCELLANEOUS TYPE-RELATED HELPER FUNCTIONS
*/
/*
* pr_valstring - Take the value and formats it using the sptrfunc member of
* the pr_type vector for the appropriate type.
* return: a freshly db_private_realloc()'ed string with a printed rep of "val" in it
* val(in): some DB_VALUE
* Note:
* The caller is responsible for eventually freeing the memory using db_private_free()
*
* This is really just a debugging helper; it probably doesn't do enough
* serious formatting for external use. Use it to get printed DB_VALUE
* representations into error messages and the like.
*/
char *
pr_valstring (const DB_VALUE * val)
{
const size_t BUFFER_SIZE = 1024;
string_buffer sb (cubmem::PRIVATE_BLOCK_ALLOCATOR, BUFFER_SIZE);
if (val == NULL || DB_IS_NULL (val))
{
/* space with terminating NULL */
sb ("(null)");
}
else
{
db_sprint_value (val, sb);
}
return sb.release_ptr (); //caller should use db_private_free() to deallocate it
}
/*
* pr_complete_enum_value - Sets both index and string of a enum value in case
* one of them is missing.
* return: NO_ERROR or error code.
* value(in/out): enumeration value.
* domain(in): enumeration domain against which the value is checked.
*/
int
pr_complete_enum_value (DB_VALUE * value, struct tp_domain *domain)
{
unsigned short short_val;
const char *str_val;
int enum_count, str_val_size, idx;
DB_ENUM_ELEMENT *db_elem = 0;
if (value == NULL || domain == NULL || DB_IS_NULL (value))
{
return NO_ERROR;
}
if (value->domain.general_info.type != DB_TYPE_ENUMERATION || domain->type->id != DB_TYPE_ENUMERATION)
{
return ER_FAILED;
}
short_val = db_get_enum_short (value);
str_val = db_get_enum_string (value);
str_val_size = db_get_enum_string_size (value);
enum_count = DOM_GET_ENUM_ELEMS_COUNT (domain);
if (short_val > enum_count)
{
return ER_FAILED;
}
if (short_val > 0)
{
db_elem = &DOM_GET_ENUM_ELEM (domain, short_val);
if (str_val != NULL && DB_GET_ENUM_ELEM_STRING_SIZE (db_elem) == str_val_size
&& !memcmp (str_val, DB_GET_ENUM_ELEM_STRING (db_elem), str_val_size))
{
db_make_enumeration (value, short_val, str_val, str_val_size, DB_GET_ENUM_ELEM_CODESET (db_elem),
db_get_enum_collation (value));
return NO_ERROR;
}
pr_clear_value (value);
str_val_size = DB_GET_ENUM_ELEM_STRING_SIZE (db_elem);
char *str_val_tmp = (char *) db_private_alloc (NULL, str_val_size + 1);
if (str_val_tmp == NULL)
{
return ER_OUT_OF_VIRTUAL_MEMORY;
}
memcpy (str_val_tmp, DB_GET_ENUM_ELEM_STRING (db_elem), str_val_size);
str_val_tmp[str_val_size] = 0;
str_val = str_val_tmp;
db_make_enumeration (value, short_val, str_val, str_val_size, DB_GET_ENUM_ELEM_CODESET (db_elem),
db_get_enum_collation (value));
value->need_clear = true;
return NO_ERROR;
}
else if (str_val == NULL)
{
/* empty string enum value with index 0 */
return NO_ERROR;
}
for (idx = 0; idx < enum_count; idx++)
{
db_elem = &DOM_GET_ENUM_ELEM (domain, idx + 1);
if (DB_GET_ENUM_ELEM_STRING_SIZE (db_elem) == str_val_size
&& !memcmp (DB_GET_ENUM_ELEM_STRING (db_elem), str_val, str_val_size))
{
db_make_enumeration (value, DB_GET_ENUM_ELEM_SHORT (db_elem), str_val, str_val_size,
DB_GET_ENUM_ELEM_CODESET (db_elem), db_get_enum_collation (value));
break;
}
}
return NO_ERROR;
}
/*
* TYPE RESULTSET
*/
static void
mr_initmem_resultset (void *mem, TP_DOMAIN * domain)
{
*(DB_BIGINT *) mem = 0;
}
static int
mr_setmem_resultset (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value != NULL)
{
*(DB_BIGINT *) mem = db_get_resultset (value);
}
else
{
mr_initmem_resultset (mem, domain);
}
return NO_ERROR;
}
static int
mr_getmem_resultset (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
return db_make_resultset (value, *(DB_BIGINT *) mem);
}
static void
mr_data_writemem_resultset (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
or_put_bigint (buf, *(DB_BIGINT *) mem);
}
static void
mr_data_readmem_resultset (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_ResultSet.disksize);
}
else
{
*(DB_BIGINT *) mem = or_get_bigint (buf, &rc);
}
}
static void
mr_initval_resultset (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_RESULTSET, precision, scale);
db_make_resultset (value, 0);
}
static int
mr_setval_resultset (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
if (src && !DB_IS_NULL (src))
{
return db_make_resultset (dest, db_get_resultset (src));
}
else
{
return db_value_domain_init (dest, DB_TYPE_RESULTSET, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
}
static int
mr_data_writeval_resultset (OR_BUF * buf, DB_VALUE * value)
{
return or_put_bigint (buf, db_get_resultset (value));
}
static int
mr_data_readval_resultset (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
DB_BIGINT temp;
int rc = NO_ERROR;
if (value == NULL)
{
rc = or_advance (buf, tp_ResultSet.disksize);
}
else
{
temp = (DB_BIGINT) or_get_bigint (buf, &rc);
if (rc == NO_ERROR)
{
db_make_resultset (value, temp);
}
value->need_clear = false;
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_resultset (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
DB_BIGINT i1, i2;
assert (domain != NULL);
/* is not index type */
assert (!domain->is_desc && !tp_valid_indextype (TP_DOMAIN_TYPE (domain)));
OR_GET_BIGINT (mem1, &i1);
OR_GET_BIGINT (mem2, &i2);
return MR_CMP (i1, i2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_resultset (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_BIGINT i1, i2;
i1 = db_get_resultset (value1);
i2 = db_get_resultset (value2);
return MR_CMP (i1, i2);
}
/*
* TYPE STRING
*/
static void
mr_initmem_string (void *mem, TP_DOMAIN * domain)
{
*(char **) mem = NULL;
}
/*
* The main difference between "memory" strings and "value" strings is that
* the length tag is stored as an in-line prefix in the memory block allocated
* to hold the string characters.
*/
static int
mr_setmem_string (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
const char *src;
char *cur, *new_, **mem;
int src_precision, src_length, new_length;
/* get the current memory contents */
mem = (char **) memptr;
cur = *mem;
if (value == NULL || (src = db_get_string (value)) == NULL)
{
/* remove the current value */
if (cur != NULL)
{
db_private_free_and_init (NULL, cur);
mr_initmem_string (memptr, domain);
}
}
else
{
/*
* Get information from the value. Ignore precision for the time being
* since we really only care about the byte size of the value for varchar.
* Whether or not the value "fits" should have been checked by now.
*/
src_precision = DB_GET_STRING_PRECISION (value);
src_length = db_get_string_size (value); /* size in bytes */
if (src_length < 0)
{
src_length = strlen (src);
}
/* Currently we NULL terminate the workspace string. Could try to do the single byte size hack like we have in
* the disk representation. */
new_length = src_length + sizeof (int) + 1;
new_ = (char *) db_private_alloc (NULL, new_length);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
if (cur != NULL)
{
db_private_free_and_init (NULL, cur);
}
/* pack in the length prefix */
*(int *) new_ = src_length;
cur = new_ + sizeof (int);
/* store the string */
memcpy (cur, src, src_length);
/* NULL terminate the stored string for safety */
cur[src_length] = '\0';
*mem = new_;
}
}
return error;
}
static int
mr_getmem_string (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
int mem_length;
char **mem, *cur, *new_;
/* get to the current value */
mem = (char **) memptr;
cur = *mem;
if (cur == NULL)
{
db_value_domain_init (value, DB_TYPE_VARCHAR, domain->precision, 0);
value->need_clear = false;
}
else
{
/* extract the length prefix and the pointer to the actual string data */
mem_length = *(int *) cur;
cur += sizeof (int);
if (TP_DOMAIN_COLLATION_FLAG (domain) != TP_DOMAIN_COLL_NORMAL)
{
assert (false);
return ER_FAILED;
}
if (!copy)
{
db_make_varchar (value, domain->precision, cur, mem_length, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
}
else
{
/* return it with a NULL terminator */
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, cur, mem_length);
new_[mem_length] = '\0';
db_make_varchar (value, domain->precision, new_, mem_length, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = true;
}
}
}
return error;
}
/*
* For the disk representation, we may be adding pad bytes to round up to a
* word boundary.
*
* We are currently adding a NULL terminator to the disk representation
* for some code on the server that still manufactures pointers directly into
* the disk buffer and assumes it is a NULL terminated string. This terminator
* can be removed after the server has been updated. The logic for maintaining
* the terminator is actually in the or_put_varchar, family of functions.
*/
static int
mr_data_lengthmem_string (void *memptr, TP_DOMAIN * domain, int disk)
{
char **mem, *cur;
int len;
len = 0;
if (!disk)
{
len = tp_String.size;
}
else if (memptr != NULL)
{
mem = (char **) memptr;
cur = *mem;
if (cur != NULL)
{
len = *(int *) cur;
if (len >= OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
/* Skip the length of the string */
len = pr_get_compression_length ((cur + sizeof (int)), len) + PRIM_TEMPORARY_DISK_SIZE;
len = or_packed_varchar_length (len) - PRIM_TEMPORARY_DISK_SIZE;
}
else
{
len = or_packed_varchar_length (len);
}
}
}
return len;
}
static int
mr_index_lengthmem_string (void *memptr, TP_DOMAIN * domain)
{
int charlen;
OR_BUF buf;
int rc = NO_ERROR, compressed_length = 0, decompressed_length = 0, length = 0;
/* generally, index key-value is short enough */
charlen = OR_GET_BYTE (memptr);
if (charlen < OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
return or_varchar_length (charlen);
}
assert (charlen == OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION);
or_init (&buf, (char *) memptr, -1);
rc = or_get_varchar_compression_lengths (&buf, &compressed_length, &decompressed_length);
if (compressed_length > 0)
{
charlen = compressed_length;
}
else
{
charlen = decompressed_length;
}
/* Temporary disk size in case the length of the current buffer is less than 255.
* Therefore the or_varchar_length will always add the 8 bytes consisting the compressed_length
* and decompressed_length stored in buffer.
*/
charlen += PRIM_TEMPORARY_DISK_SIZE;
length = or_varchar_length (charlen);
return length - PRIM_TEMPORARY_DISK_SIZE;
}
static void
mr_data_writemem_string (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
char **mem, *cur;
int len;
mem = (char **) memptr;
cur = *mem;
if (cur != NULL)
{
len = *(int *) cur;
cur += sizeof (int);
or_packed_put_varchar (buf, cur, len);
}
}
/*
* The amount of memory requested is currently calculated based on the
* stored size prefix. If we ever go to a system where we avoid storing the
* size, then we could use the size argument passed in to this function but
* that may also include any padding byte that added to bring us up to a word
* boundary.
* Might want some way to determine which bytes at the end of a string are
* padding.
*/
static void
mr_data_readmem_string (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
char **mem, *cur, *new_;
int len;
int mem_length, pad;
char *start;
int rc = NO_ERROR;
/*
* we must have an explicit size here as it can't be determined from the
* domain
*/
if (size < 0)
{
return;
}
if (memptr == NULL)
{
if (size)
{
or_advance (buf, size);
}
}
else
{
mem = (char **) memptr;
cur = *mem;
/* should we be checking for existing strings ? */
#if 0
if (cur != NULL)
db_private_free_and_init (NULL, cur);
#endif
new_ = NULL;
if (size)
{
int compressed_size;
start = buf->ptr;
/* KLUDGE, we have some knowledge of how the thing is stored here in order have some control over the
* conversion between the packed length prefix and the full word memory length prefix. Might want to put this
* in another specialized or_ function. */
/* Get just the length prefix. */
rc = or_get_varchar_compression_lengths (buf, &compressed_size, &len);
if (rc != NO_ERROR)
{
return;
}
/*
* Allocate storage for this string, including our own full word size
* prefix and a NULL terminator.
*/
mem_length = len + sizeof (int) + 1;
new_ = (char *) db_private_alloc (NULL, mem_length);
if (new_ == NULL)
{
return;
}
else
{
/* store the length in our memory prefix */
*(int *) new_ = len;
cur = new_ + sizeof (int);
/* decompress buffer (this also writes nul terminator) */
rc = pr_get_compressed_data_from_buffer (buf, cur, compressed_size, len);
if (rc != NO_ERROR)
{
db_private_free (NULL, new_);
ASSERT_ERROR ();
return;
}
/* align like or_get_varchar */
or_get_align32 (buf);
}
/* If we were given a size, check to see if for some reason this is larger than the already word aligned
* string that we have now extracted. This shouldn't be the case but since we've got a length, we may as
* well obey it. */
pad = size - (int) (buf->ptr - start);
if (pad > 0)
{
or_advance (buf, pad);
}
}
*mem = new_;
}
}
static void
mr_freemem_string (void *memptr)
{
char *cur;
if (memptr != NULL)
{
cur = *(char **) memptr;
if (cur != NULL)
db_private_free_and_init (NULL, cur);
}
}
static void
mr_initval_string (DB_VALUE * value, int precision, int scale)
{
db_make_varchar (value, precision, NULL, 0, LANG_SYS_CODESET, LANG_SYS_COLLATION);
value->need_clear = false;
}
static int
mr_setval_string (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision, src_length;
const char *src_str;
char *new_, *new_compressed_buf;
assert (!db_value_is_corrupted (src));
if (src == NULL || DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_VARCHAR, DB_DEFAULT_PRECISION, 0);
}
else if ((src_str = db_get_string (src)) == NULL)
{
error = db_value_domain_init (dest, DB_TYPE_VARCHAR, db_value_precision (src), 0);
if (src->data.ch.info.is_max_string)
{
dest->data.ch.info.style = MEDIUM_STRING;
dest->data.ch.info.is_max_string = true;
dest->domain.general_info.is_null = 0;
dest->domain.char_info.collation_id = db_get_string_collation (src);
dest->data.ch.medium.compressed_buf = NULL;
dest->data.ch.medium.codeset = db_get_string_codeset (src);
dest->data.ch.medium.compressed_size = DB_UNCOMPRESSABLE;
dest->data.ch.info.compressed_need_clear = false;
dest->data.ch.medium.size = 0;
dest->data.ch.medium.length = -1;
dest->data.ch.medium.buf = NULL;
}
}
else
{
/* Get information from the value. */
src_precision = db_value_precision (src);
src_length = db_get_string_size (src);
if (src_length < 0)
{
src_length = strlen (src_str);
}
assert (src->data.ch.info.is_max_string == false);
/* should we be paying attention to this? it is extremely dangerous */
if (!copy)
{
error = db_make_varchar (dest, src_precision, src_str, src_length, db_get_string_codeset (src),
db_get_string_collation (src));
dest->data.ch.medium.compressed_buf = src->data.ch.medium.compressed_buf;
dest->data.ch.info.compressed_need_clear = false;
}
else
{
new_ = (char *) db_private_alloc (NULL, src_length + 1);
if (new_ == NULL)
{
db_value_domain_init (dest, DB_TYPE_VARCHAR, src_precision, 0);
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, src_str, src_length);
new_[src_length] = '\0';
db_make_varchar (dest, src_precision, new_, src_length, db_get_string_codeset (src),
db_get_string_collation (src));
dest->need_clear = true;
}
if (src->data.ch.medium.compressed_buf == NULL)
{
dest->data.ch.medium.compressed_buf = NULL;
dest->data.ch.info.compressed_need_clear = false;
}
else
{
new_compressed_buf = (char *) db_private_alloc (NULL, src->data.ch.medium.compressed_size + 1);
if (new_compressed_buf == NULL)
{
db_value_domain_init (dest, DB_TYPE_VARCHAR, src_precision, 0);
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_compressed_buf, src->data.ch.medium.compressed_buf, src->data.ch.medium.compressed_size);
new_compressed_buf[src->data.ch.medium.compressed_size] = '\0';
dest->data.ch.medium.compressed_buf = new_compressed_buf;
dest->data.ch.info.compressed_need_clear = true;
}
}
}
dest->data.ch.medium.length = src->data.ch.medium.length;
dest->data.ch.medium.compressed_size = src->data.ch.medium.compressed_size;
}
return error;
}
static int
mr_index_lengthval_string (DB_VALUE * value)
{
return mr_lengthval_string_internal (value, 1, CHAR_ALIGNMENT);
}
static int
mr_index_writeval_string (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_string_internal (buf, value, CHAR_ALIGNMENT);
}
static int
mr_index_readval_string (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_string_internal (buf, value, domain, size, copy, copy_buf, copy_buf_len, CHAR_ALIGNMENT);
}
static int
mr_data_lengthval_string (DB_VALUE * value, int disk)
{
return mr_lengthval_string_internal (value, disk, INT_ALIGNMENT);
}
static int
mr_data_writeval_string (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_string_internal (buf, value, INT_ALIGNMENT);
}
static int
mr_data_readval_string (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_string_internal (buf, value, domain, size, copy, copy_buf, copy_buf_len, INT_ALIGNMENT);
}
/*
* Ignoring precision as byte size is really the only important thing for
* varchar.
*/
static int
mr_lengthval_string_internal (DB_VALUE * value, int disk, int align)
{
int len;
bool is_temporary_data = false;
const char *str;
int rc = NO_ERROR;
int compressed_size = 0;
if (DB_IS_NULL (value))
{
return 0;
}
str = value->data.ch.medium.buf;
len = value->data.ch.medium.size;
if (!str)
{
return 0;
}
if (len < 0)
{
len = strlen (str);
}
if (disk == 0)
{
return len;
}
else
{
/* Test and try compression. */
if (!DB_TRIED_COMPRESSION (value))
{
/* It means that the value has never passed through a compression process. */
rc = pr_do_db_value_string_compression (value);
}
/* We are now sure that the value has been through the process of compression */
compressed_size = db_get_compressed_size (value);
/* If the compression was successful, then we use the compression size value */
if (compressed_size > 0)
{
len = compressed_size + PRIM_TEMPORARY_DISK_SIZE;
is_temporary_data = true;
}
else
{
/* Compression failed so we are using the uncompressed size */
len = value->data.ch.medium.size;
}
if (len >= OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION && is_temporary_data == false)
{
/* The compression failed but the size of the string calls for the new encoding. */
len += PRIM_TEMPORARY_DISK_SIZE;
is_temporary_data = true;
}
if (align == INT_ALIGNMENT)
{
len = or_packed_varchar_length (len);
}
else
{
len = or_varchar_length (len);
}
if (is_temporary_data == true)
{
return len - PRIM_TEMPORARY_DISK_SIZE;
}
return len;
}
}
/*
* Ignoring precision as byte size is really the only important thing for
* varchar.
*/
static int
mr_writeval_string_internal (OR_BUF * buf, DB_VALUE * value, int align)
{
int src_length, compressed_size;
const char *str, *compressed_string;
int rc = NO_ERROR;
const char *string;
int size;
if (value != NULL && !db_value_is_null (value))
{
str = db_get_string (value);
src_length = db_get_string_size (value); /* size in bytes */
if (src_length <= 0)
{
if (src_length == 0)
{
return pr_write_uncompressed_string_to_buffer (buf, "", 0, align);
}
src_length = strlen (str);
}
/* Test for possible compression. */
if (!DB_TRIED_COMPRESSION (value))
{
/* It means that the value has never passed through a compression process. */
rc = pr_do_db_value_string_compression (value);
}
if (rc != NO_ERROR)
{
return rc;
}
compressed_size = db_get_compressed_size (value);
compressed_string = DB_GET_COMPRESSED_STRING (value);
if (compressed_size == DB_UNCOMPRESSABLE && src_length < OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
rc = pr_write_uncompressed_string_to_buffer (buf, str, src_length, align);
}
else
{
/* String has been prompted to compression before. */
assert (compressed_size != DB_NOT_YET_COMPRESSED);
if (compressed_string == NULL)
{
/* The value passed through a compression process but it failed due to its size. */
assert (compressed_size == DB_UNCOMPRESSABLE);
string = value->data.ch.medium.buf;
}
else
{
/* Compression successful. */
assert (compressed_size > 0);
string = compressed_string;
}
if (compressed_size == DB_UNCOMPRESSABLE)
{
size = 0;
}
else
{
size = compressed_size;
}
rc = pr_write_compressed_string_to_buffer (buf, string, size, src_length, align);
}
}
return rc;
}
static int
mr_readval_string_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len, int align)
{
int precision;
int rc = NO_ERROR;
int compressed_size = 0, expected_decompressed_size = 0;
char *decompressed_string = NULL, *compressed_string = NULL;
if (value == NULL)
{
if (size == -1)
{
rc = or_skip_varchar (buf, align);
}
else if (size)
{
rc = or_advance (buf, size);
}
return rc;
}
precision = (domain != NULL) ? domain->precision : DB_MAX_VARCHAR_PRECISION;
if (size == 0)
{
/* its NULL */
db_value_domain_init (value, DB_TYPE_VARCHAR, precision, 0);
return NO_ERROR;
}
if (TP_DOMAIN_COLLATION_FLAG (domain) != TP_DOMAIN_COLL_NORMAL)
{
assert (false);
return ER_FAILED;
}
/* Get the compressed size and uncompressed size from the buffer, and point the buf->ptr
* towards the data stored in the buffer */
rc = or_get_varchar_compression_lengths (buf, &compressed_size, &expected_decompressed_size);
if (rc != NO_ERROR)
{
return rc;
}
if (copy || (compressed_size > 0))
{
if (copy_buf && copy_buf_len >= expected_decompressed_size + 1)
{
/* read buf image into the copy_buf */
decompressed_string = copy_buf;
}
else
{
/* Allocate storage for the string including the kludge NULL terminator */
decompressed_string = (char *) db_private_alloc (NULL, expected_decompressed_size + 1);
if (decompressed_string == NULL)
{
rc = ER_OUT_OF_VIRTUAL_MEMORY;
goto cleanup;
}
}
}
if (compressed_size > 0)
{
rc = pr_get_compressed_data_from_buffer (buf, decompressed_string, compressed_size, expected_decompressed_size);
if (rc != NO_ERROR)
{
goto cleanup;
}
db_make_varchar (value, precision, decompressed_string, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = (decompressed_string != copy_buf) ? true : false;
#if defined(CS_MODE)
db_set_compressed_string (value, NULL, DB_NOT_YET_COMPRESSED, false);
#else
compressed_string = (char *) db_private_alloc (NULL, compressed_size + 1);
if (compressed_string == NULL)
{
rc = ER_OUT_OF_VIRTUAL_MEMORY;
goto cleanup;
}
memcpy (compressed_string, buf->ptr, compressed_size);
compressed_string[compressed_size] = '\0';
db_set_compressed_string (value, compressed_string, compressed_size, true);
#endif
}
else
{
assert (compressed_size == 0);
if (!copy)
{
assert (decompressed_string == NULL);
db_make_varchar (value, precision, buf->ptr, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
}
else /* if (!copy) */
{
assert (decompressed_string != NULL);
memcpy (decompressed_string, buf->ptr, expected_decompressed_size);
decompressed_string[expected_decompressed_size] = '\0';
db_make_varchar (value, precision, decompressed_string, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = (decompressed_string != copy_buf) ? true : false;
}
db_set_compressed_string (value, NULL, DB_UNCOMPRESSABLE, false);
}
or_skip_varchar_remainder (buf, (compressed_size > 0) ? compressed_size : expected_decompressed_size, align);
cleanup:
if (rc != NO_ERROR)
{
if (decompressed_string != NULL && decompressed_string != copy_buf)
{
db_private_free_and_init (NULL, decompressed_string);
}
if (compressed_string != NULL)
{
db_private_free_and_init (NULL, compressed_string);
}
}
return rc;
}
#if (MAJOR_VERSION >= 11) || (MAJOR_VERSION == 10 && MINOR_VERSION >= 1)
/* data_readval_string() was written separately to read varchar columns
* from HEAP records to support unloaddb.
* TO-DO: After applying [CBRD-25293], decide whether to consolidate and rewrite the function.
*/
int
data_readval_string (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int precision;
int align = INT_ALIGNMENT;
int rc = NO_ERROR;
int compressed_size = 0, expected_decompressed_size = 0;
char *decompressed_string = NULL, *compressed_string = NULL;
if (value == NULL)
{
if (size == -1)
{
rc = or_skip_varchar (buf, align);
}
else if (size)
{
rc = or_advance (buf, size);
}
return rc;
}
precision = (domain != NULL) ? domain->precision : DB_MAX_VARCHAR_PRECISION;
if (size == 0)
{
/* its NULL */
db_value_domain_init (value, DB_TYPE_VARCHAR, precision, 0);
return NO_ERROR;
}
if (TP_DOMAIN_COLLATION_FLAG (domain) != TP_DOMAIN_COLL_NORMAL)
{
assert (false);
return ER_FAILED;
}
/* Get the compressed size and uncompressed size from the buffer, and point the buf->ptr
* towards the data stored in the buffer */
rc = or_get_varchar_compression_lengths (buf, &compressed_size, &expected_decompressed_size);
if (rc != NO_ERROR)
{
return rc;
}
if (!copy)
{
if (compressed_size > 0)
{
if (copy_buf && copy_buf_len >= expected_decompressed_size + 1)
{
/* read buf image into the copy_buf */
decompressed_string = copy_buf;
}
else
{
/* Allocate storage for the string including the kludge NULL terminator */
decompressed_string = (char *) db_private_alloc (NULL, expected_decompressed_size + 1);
if (decompressed_string == NULL)
{
rc = ER_OUT_OF_VIRTUAL_MEMORY;
goto cleanup;
}
}
rc =
pr_get_compressed_data_from_buffer (buf, decompressed_string, compressed_size, expected_decompressed_size);
if (rc != NO_ERROR)
{
goto cleanup;
}
db_make_varchar (value, precision, decompressed_string, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = (decompressed_string != copy_buf) ? true : false;
db_set_compressed_string (value, NULL, DB_NOT_YET_COMPRESSED, false);
}
else
{
assert (compressed_size == 0);
db_make_varchar (value, precision, buf->ptr, expected_decompressed_size, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
db_set_compressed_string (value, NULL, DB_UNCOMPRESSABLE, false);
}
}
else /* if (!copy) */
{
bool compressed_need_clear = false;
int decompressed_size = 0;
if (copy_buf && copy_buf_len >= expected_decompressed_size + 1)
{
/* read buf image into the copy_buf */
decompressed_string = copy_buf;
}
else
{
/* Allocate storage for the string including the kludge NULL terminator */
decompressed_string = (char *) db_private_alloc (NULL, expected_decompressed_size + 1);
if (decompressed_string == NULL)
{
rc = ER_OUT_OF_VIRTUAL_MEMORY;
goto cleanup;
}
}
if (compressed_size > 0)
{
rc =
pr_get_compressed_data_from_buffer (buf, decompressed_string, compressed_size, expected_decompressed_size);
if (rc != NO_ERROR)
{
goto cleanup;
}
db_make_varchar (value, precision, decompressed_string, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = (decompressed_string != copy_buf) ? true : false;
db_set_compressed_string (value, NULL, DB_NOT_YET_COMPRESSED, false);
}
else
{
assert (compressed_size == 0);
memcpy (decompressed_string, buf->ptr, expected_decompressed_size);
decompressed_string[expected_decompressed_size] = '\0';
db_make_varchar (value, precision, decompressed_string, expected_decompressed_size,
TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = (decompressed_string != copy_buf) ? true : false;
db_set_compressed_string (value, NULL, DB_UNCOMPRESSABLE, false);
}
}
or_skip_varchar_remainder (buf, (compressed_size > 0) ? compressed_size : expected_decompressed_size, align);
cleanup:
if (rc != NO_ERROR)
{
if (decompressed_string != NULL && decompressed_string != copy_buf)
{
db_private_free_and_init (NULL, decompressed_string);
}
if (compressed_string != NULL)
{
db_private_free_and_init (NULL, compressed_string);
}
}
return rc;
}
#endif // #if (MAJOR_VERSION >= 11) || (MAJOR_VERSION == 10 && MINOR_VERSION >= 1)
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_string (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_data_cmpdisk_string (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_string (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c = DB_UNK;
char *str1, *str2;
int str_length1, str1_compressed_length = 0, str1_decompressed_length = 0;
int str_length2, str2_compressed_length = 0, str2_decompressed_length = 0;
OR_BUF buf1, buf2;
int rc = NO_ERROR;
char *string1 = NULL, *string2 = NULL;
bool alloced_string1 = false, alloced_string2 = false;
int strc;
bool ti = true;
static bool ignore_trailing_space = prm_get_bool_value (PRM_ID_IGNORE_TRAILING_SPACE);
assert (domain != NULL);
str1 = (char *) mem1;
str2 = (char *) mem2;
/* generally, data is short enough */
str_length1 = OR_GET_BYTE (str1);
str_length2 = OR_GET_BYTE (str2);
if (!ignore_trailing_space)
{
ti = false;
}
if (str_length1 < OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION && str_length2 < OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
str1 += OR_BYTE_SIZE;
str2 += OR_BYTE_SIZE;
strc =
QSTR_COMPARE (domain->collation_id, (unsigned char *) str1, str_length1, (unsigned char *) str2, str_length2,
ti);
c = MR_CMP_RETURN_CODE (strc);
return c;
}
assert (str_length1 == OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION
|| str_length2 == OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION);
/* String 1 */
or_init (&buf1, str1, 0);
if (str_length1 == OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
rc = or_get_varchar_compression_lengths (&buf1, &str1_compressed_length, &str1_decompressed_length);
if (rc != NO_ERROR)
{
goto cleanup;
}
string1 = (char *) db_private_alloc (NULL, str1_decompressed_length + 1);
if (string1 == NULL)
{
/* Error report */
goto cleanup;
}
alloced_string1 = true;
rc = pr_get_compressed_data_from_buffer (&buf1, string1, str1_compressed_length, str1_decompressed_length);
if (rc != NO_ERROR)
{
goto cleanup;
}
str_length1 = str1_decompressed_length;
string1[str_length1] = '\0';
}
else
{
/* Skip the size byte */
string1 = buf1.ptr + OR_BYTE_SIZE;
}
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
goto cleanup;
}
/* String 2 */
or_init (&buf2, str2, 0);
if (str_length2 == OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION)
{
rc = or_get_varchar_compression_lengths (&buf2, &str2_compressed_length, &str2_decompressed_length);
if (rc != NO_ERROR)
{
goto cleanup;
}
string2 = (char *) db_private_alloc (NULL, str2_decompressed_length + 1);
if (string2 == NULL)
{
/* Error report */
goto cleanup;
}
alloced_string2 = true;
rc = pr_get_compressed_data_from_buffer (&buf2, string2, str2_compressed_length, str2_decompressed_length);
if (rc != NO_ERROR)
{
goto cleanup;
}
str_length2 = str2_decompressed_length;
string2[str_length2] = '\0';
}
else
{
/* Skip the size byte */
string2 = buf2.ptr + OR_BYTE_SIZE;
}
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
goto cleanup;
}
/* Compare the strings */
strc =
QSTR_COMPARE (domain->collation_id, (unsigned char *) string1, str_length1, (unsigned char *) string2, str_length2,
ti);
c = MR_CMP_RETURN_CODE (strc);
/* Clean up the strings */
if (string1 != NULL && alloced_string1 == true)
{
db_private_free_and_init (NULL, string1);
}
if (string2 != NULL && alloced_string2 == true)
{
db_private_free_and_init (NULL, string2);
}
return c;
cleanup:
if (string1 != NULL && alloced_string1 == true)
{
db_private_free_and_init (NULL, string1);
}
if (string2 != NULL && alloced_string2 == true)
{
db_private_free_and_init (NULL, string2);
}
return DB_UNK;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_string (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_VALUE_COMPARE_RESULT c;
int size1, size2;
int strc;
static bool ti = prm_get_bool_value (PRM_ID_IGNORE_TRAILING_SPACE);
DB_TYPE type1 = (DB_TYPE) value1->domain.char_info.type;
DB_TYPE type2 = (DB_TYPE) value2->domain.char_info.type;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
/*
* Check if the is_max_string flag set for each DB_VALUE.
* If "value1" has the flag set, return 1, meaning that "value2" is Less Than "value1".
* If "value2" has the flag set, return -1, meaning that "value1" is Greater Than "value2".
*/
if (value1->data.ch.info.is_max_string != 0)
{
if (value2->data.ch.info.is_max_string != 0)
{
/* Both strings are max_string. Therefore equal. Even though this should not happen. */
assert (false);
return DB_EQ;
}
return DB_GT;
}
else
{
if (value2->data.ch.info.is_max_string != 0)
{
return DB_LT;
}
}
if (string1 == NULL || string2 == NULL || db_get_string_codeset (value1) != db_get_string_codeset (value2))
{
return DB_UNK;
}
size1 = (int) db_get_string_size (value1);
size2 = (int) db_get_string_size (value2);
if (size1 < 0)
{
size1 = strlen ((char *) string1);
}
if (size2 < 0)
{
size2 = strlen ((char *) string2);
}
if (collation == -1)
{
assert (false);
return DB_UNK;
}
strc = QSTR_COMPARE (collation, string1, size1, string2, size2, ti);
c = MR_CMP_RETURN_CODE (strc);
return c;
}
#if defined (ENABLE_UNUSED_FUNCTION)
static int
mr_cmpval_string2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order, int *start_colp)
{
int c;
int len1, len2, string_size;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
string_size = (int) db_get_string_size (value1);
len1 = MIN (string_size, length);
string_size = (int) db_get_string_size (value2);
len2 = MIN (string_size, length);
c = QSTR_COMPARE (string1, len1, string2, len2);
c = MR_CMP_RETURN_CODE (c);
return c;
}
#endif
const PR_TYPE tp_String = {
"character varying", DB_TYPE_STRING, 1, sizeof (const char *), 0, 1,
mr_initmem_string,
mr_initval_string,
mr_setmem_string,
mr_getmem_string,
mr_setval_string,
mr_data_lengthmem_string,
mr_data_lengthval_string,
mr_data_writemem_string,
mr_data_readmem_string,
mr_data_writeval_string,
mr_data_readval_string,
mr_index_lengthmem_string,
mr_index_lengthval_string,
mr_index_writeval_string,
mr_index_readval_string,
mr_index_cmpdisk_string,
mr_freemem_string,
mr_data_cmpdisk_string,
mr_cmpval_string
};
const PR_TYPE *tp_Type_string = &tp_String;
/*
* TYPE CHAR
*/
static void
mr_initmem_char (void *memptr, TP_DOMAIN * domain)
{
#if !defined(NDEBUG)
int mem_length;
assert (!IS_FLOATING_PRECISION (domain->precision));
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
memset (memptr, 0, mem_length);
#endif
}
/*
* Note! Due to the "within tolerance" comparison of domains used for
* assignment validation, we may get values in here whose precision is
* less than the precision of the actual attribute. This prevents
* having to copy a string just to coerce a value into a larger precision.
* Note that the precision of the source value may also come in as -1 here
* which is used to mean a "floating" precision that is assumed to be
* compatible with the destination domain as long as the associated value
* is within tolerance. This case is generally only seen for string
* literals that have been produced by the parser. These literals will
* not contain blank padding and strlen() or db_get_string_size() can be
* used to determine the number of significant characters.
*
*/
static int
mr_setmem_char (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
char *mem;
const char *src;
int src_precision, src_length, mem_length, pad;
assert (!IS_FLOATING_PRECISION (domain->precision));
if (value == NULL)
{
return NO_ERROR;
}
/* Get information from the value */
src = db_get_string (value);
src_precision = DB_GET_STRING_PRECISION (value);
src_length = db_get_string_size (value); /* size in bytes */
if (src == NULL)
{
return NO_ERROR;
}
/* Check for special NTS flag. This may not be necessary any more. */
if (src_length < 0)
{
src_length = strlen (src);
}
/* The only thing we really care about at this point, is the byte length of the string. The precision could be
* checked here but it really isn't necessary for this operation. Calculate the maximum number of bytes we have
* available here. The multiplier is dependent on codeset */
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (mem_length < src_length)
{
/*
* should never get here, this is supposed to be caught during domain
* validation, need a better error message.
*/
error = ER_OBJ_DOMAIN_CONFLICT;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
else
{
/* copy the value into memory */
mem = (char *) memptr;
memcpy (mem, src, src_length);
/*
* Check for space padding, if this were a national string, we would
* need to be padding with the appropriate space character !
*/
pad = mem_length - src_length;
if (pad)
{
int i;
for (i = src_length; i < mem_length; i++)
{
mem[i] = ' ';
}
}
}
return error;
}
static int
mr_getmem_char (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int mem_length;
char *new_;
assert (!IS_FLOATING_PRECISION (domain->precision));
if (TP_DOMAIN_COLLATION_FLAG (domain) != TP_DOMAIN_COLL_NORMAL)
{
assert (false);
return ER_FAILED;
}
intl_char_size ((unsigned char *) mem, domain->precision, TP_DOMAIN_CODESET (domain), &mem_length);
if (mem_length == 0)
{
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
}
if (!copy)
{
new_ = (char *) mem;
}
else
{
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
return er_errid ();
}
memcpy (new_, (char *) mem, mem_length);
/* make sure that all outgoing strings are NULL terminated */
new_[mem_length] = '\0';
}
db_make_char (value, domain->precision, new_, mem_length, TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
if (copy)
{
value->need_clear = true;
}
return NO_ERROR;
}
static int
mr_data_lengthmem_char (void *memptr, TP_DOMAIN * domain, int disk)
{
int mem_length;
assert (!IS_FLOATING_PRECISION (domain->precision));
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
return mem_length;
}
static int
mr_index_lengthmem_char (void *memptr, TP_DOMAIN * domain)
{
int mem_length;
assert (!(IS_FLOATING_PRECISION (domain->precision) && memptr == NULL));
if (IS_FLOATING_PRECISION (domain->precision))
{
memcpy (&mem_length, memptr, OR_INT_SIZE);
mem_length += OR_INT_SIZE;
}
else
{
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
}
return mem_length;
}
static void
mr_data_writemem_char (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
int mem_length;
assert (!IS_FLOATING_PRECISION (domain->precision));
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
/*
* We simply dump the memory image to disk, it will already have been padded.
* If this were a national character string, at this point, we'd have to
* decide now to perform a character set conversion.
*/
or_put_data (buf, (char *) mem, mem_length);
}
static void
mr_data_readmem_char (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int mem_length, padding;
assert (!IS_FLOATING_PRECISION (domain->precision));
if (mem == NULL)
{
/*
* If we passed in a size, then use it. Otherwise, determine the
* size from the domain.
*/
if (size > 0)
{
or_advance (buf, size);
}
else
{
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
or_advance (buf, mem_length);
}
}
else
{
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (size != -1 && mem_length > size)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return;
}
or_get_data (buf, (char *) mem, mem_length);
/*
* We should only see padding if the string is contained within a packed
* value that had extra padding to ensure alignment. If we see these,
* just pop them out of the buffer. This shouldn't ever happen for the
* "getmem" function, only for the "getval" function.
*/
if (size != -1)
{
padding = size - mem_length;
if (padding > 0)
{
or_advance (buf, padding);
}
}
}
}
static void
mr_freemem_char (void *memptr)
{
}
static void
mr_initval_char (DB_VALUE * value, int precision, int scale)
{
DB_DOMAIN_INIT_CHAR (value, precision);
}
static int
mr_setval_char (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision, src_length;
char *new_;
const char *src_string;
assert (!db_value_is_corrupted (src));
if (DB_IS_NULL (src))
{
DB_DOMAIN_INIT_CHAR (dest, TP_FLOATING_PRECISION_VALUE);
}
else
{
src_precision = DB_GET_STRING_PRECISION (src);
if (src_precision == 0)
{
src_precision = TP_FLOATING_PRECISION_VALUE;
}
DB_DOMAIN_INIT_CHAR (dest, src_precision);
/* Get information from the value */
src_string = db_get_string (src);
src_length = db_get_string_size (src); /* size in bytes */
/* shouldn't see a NULL string at this point, treat as NULL */
if (src_string != NULL)
{
if (!copy)
{
db_make_char (dest, src_precision, src_string, src_length, db_get_string_codeset (src),
db_get_string_collation (src));
}
else
{
/* Check for NTS marker, may not need to do this any more */
if (src_length < 0)
{
src_length = strlen (src_string);
}
/* make sure the copy gets a NULL terminator */
new_ = (char *) db_private_alloc (NULL, src_length + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, src_string, src_length);
new_[src_length] = '\0';
db_make_char (dest, src_precision, new_, src_length, db_get_string_codeset (src),
db_get_string_collation (src));
dest->need_clear = true;
}
}
dest->data.ch.medium.length = src->data.ch.medium.length;
}
}
return error;
}
static int
mr_index_lengthval_char (DB_VALUE * value)
{
return mr_data_lengthval_char (value, 1);
}
/*
*/
static int
mr_data_lengthval_char (DB_VALUE * value, int disk)
{
int packed_length, src_precision;
const char *src = db_get_string (value);
if (src == NULL)
{
return 0;
}
src_precision = db_value_precision (value);
if (!IS_FLOATING_PRECISION (src_precision))
{
packed_length = STR_SIZE (src_precision, db_get_string_codeset (value));
}
else
{
/*
* Precision is "floating", calculate the effective precision based on the
* string length.
* Should be rounding this up so it is a proper multiple of the charset
* width ?
*/
packed_length = db_get_string_size (value);
if (packed_length < 0)
{
packed_length = strlen (src);
}
/* add in storage for a size prefix on the packed value. */
packed_length += OR_INT_SIZE;
}
/*
* NOTE: We do NOT perform padding here, if this is used in the context
* of a packed value, the or_put_value() family of functions must handle
* their own padding, this is because "lengthval" and "writeval" can be
* used to place values into the disk representation of instances and
* there can be no padding in there.
*/
return packed_length;
}
static int
mr_index_writeval_char (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_char_internal (buf, value, CHAR_ALIGNMENT);
}
/*
* See commentary in mr_lengthval_char.
*/
static int
mr_data_writeval_char (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_char_internal (buf, value, INT_ALIGNMENT);
}
static int
mr_writeval_char_internal (OR_BUF * buf, DB_VALUE * value, int align)
{
int src_precision, src_length, packed_length, pad;
const char *src;
int rc = NO_ERROR;
src = db_get_string (value);
if (src == NULL)
{
return rc;
}
src_precision = db_value_precision (value);
if (!IS_FLOATING_PRECISION (src_precision))
{
src_length = db_get_string_size (value); /* size in bytes */
if (src_length < 0)
{
src_length = strlen (src);
}
packed_length = STR_SIZE (src_precision, db_get_string_codeset (value));
if (packed_length < src_length)
{
/* should have caught this by now, truncate silently */
rc = or_put_data (buf, src, packed_length);
}
else
{
rc = or_put_data (buf, src, src_length);
/*
* Check for space padding, if this were a national string, we
* would need to be padding with the appropriate space character !
*/
pad = packed_length - src_length;
if (pad)
{
int i;
for (i = src_length; i < packed_length; i++)
{
rc = or_put_byte (buf, (int) ' ');
}
}
}
if (rc != NO_ERROR)
{
return rc;
}
}
else
{
/*
* This is a "floating" precision value. Pack what we can based on the
* string size. Note that for this to work, this can only be packed as
* part of a domain tagged value and we must include a length prefix
* after the domain.
*/
packed_length = db_get_string_size (value);
if (packed_length < 0)
{
packed_length = strlen (src);
}
/* store the size prefix */
if (align == INT_ALIGNMENT)
{
rc = or_put_int (buf, packed_length);
}
else
{
rc = or_put_data (buf, (char *) (&packed_length), OR_INT_SIZE);
}
if (rc == NO_ERROR)
{
/* store the data */
rc = or_put_data (buf, src, packed_length);
/* there is no blank padding in this case */
}
}
return rc;
}
static int
mr_index_readval_char (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_char_internal (buf, value, domain, disk_size, copy, copy_buf, copy_buf_len, CHAR_ALIGNMENT);
}
static int
mr_data_readval_char (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_char_internal (buf, value, domain, disk_size, copy, copy_buf, copy_buf_len, INT_ALIGNMENT);
}
static int
mr_readval_char_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len, int align)
{
int mem_length, padding;
int str_length, precision;
char *new_;
int rc = NO_ERROR;
precision = domain->precision;
if (TP_DOMAIN_COLLATION_FLAG (domain) != TP_DOMAIN_COLL_NORMAL)
{
assert (false);
return ER_FAILED;
}
if (IS_FLOATING_PRECISION (domain->precision))
{
if (align == INT_ALIGNMENT)
{
mem_length = or_get_int (buf, &rc);
}
else
{
rc = or_get_data (buf, (char *) (&mem_length), OR_INT_SIZE);
}
if (rc != NO_ERROR)
{
return rc;
}
if (value == NULL)
{
rc = or_advance (buf, mem_length);
}
else if (!copy)
{
db_make_char (value, TP_FLOATING_PRECISION_VALUE, buf->ptr, mem_length, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
rc = or_advance (buf, mem_length);
}
else
{
if (copy_buf && copy_buf_len >= mem_length + 1)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/* Allocate storage for the string including the kludge NULL terminator */
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), TP_FLOATING_PRECISION_VALUE, 0);
return ER_FAILED;
}
else
{
rc = or_get_data (buf, new_, mem_length);
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return rc;
}
new_[mem_length] = '\0'; /* append the kludge NULL terminator */
db_make_char (value, TP_FLOATING_PRECISION_VALUE, new_, mem_length, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = (new_ != copy_buf) ? true : false;
}
}
}
else
{
/*
* Normal fixed width char(n) whose size can be determined by looking at
* the domain.
*/
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (disk_size != -1 && mem_length > disk_size)
{
/*
* If we're low here, we could just read what we have and make a
* smaller value. Still the domain should match at this point.
*/
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return ER_FAILED;
}
if (value == NULL)
{
rc = or_advance (buf, mem_length);
}
else if (disk_size == 0)
{
db_value_domain_init (value, DB_TYPE_CHAR, precision, 0);
}
else if (!copy)
{
intl_char_size ((unsigned char *) buf->ptr, domain->precision, TP_DOMAIN_CODESET (domain), &str_length);
if (str_length == 0)
{
str_length = mem_length;
}
db_make_char (value, precision, buf->ptr, str_length, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
rc = or_advance (buf, mem_length);
}
else
{
if (copy_buf && copy_buf_len >= mem_length + 1)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/*
* Allocate storage for the string including the kludge NULL
* terminator
*/
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), domain->precision, 0);
return ER_FAILED;
}
else
{
int actual_size = 0;
rc = or_get_data (buf, new_, mem_length);
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return rc;
}
intl_char_size ((unsigned char *) new_, domain->precision, TP_DOMAIN_CODESET (domain), &actual_size);
if (actual_size == 0)
{
actual_size = mem_length;
}
new_[actual_size] = '\0'; /* append the kludge NULL terminator */
db_make_char (value, domain->precision, new_, actual_size, TP_DOMAIN_CODESET (domain),
TP_DOMAIN_COLLATION (domain));
value->need_clear = (new_ != copy_buf) ? true : false;
}
}
if (rc == NO_ERROR)
{
/*
* We should only see padding if the string is contained within a
* packed value that had extra padding to ensure alignment. If we
* see these, just pop them out of the buffer.
*/
if (disk_size != -1)
{
padding = disk_size - mem_length;
if (padding > 0)
{
rc = or_advance (buf, padding);
}
}
}
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_char (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_cmpdisk_char_internal (mem1, mem2, domain, do_coercion, total_order, start_colp, CHAR_ALIGNMENT);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_char (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_cmpdisk_char_internal (mem1, mem2, domain, do_coercion, total_order, start_colp, INT_ALIGNMENT);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpdisk_char_internal (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp,
int align)
{
DB_VALUE_COMPARE_RESULT c;
int mem_length1, mem_length2, strc;
bool ti = true;
static bool ignore_trailing_space = prm_get_bool_value (PRM_ID_IGNORE_TRAILING_SPACE);
if (IS_FLOATING_PRECISION (domain->precision))
{
if (align == INT_ALIGNMENT)
{
mem_length1 = OR_GET_INT (mem1);
mem_length2 = OR_GET_INT (mem2);
}
else
{
memcpy (&mem_length1, mem1, OR_INT_SIZE);
memcpy (&mem_length2, mem2, OR_INT_SIZE);
}
mem1 = (char *) mem1 + OR_INT_SIZE;
mem2 = (char *) mem2 + OR_INT_SIZE;
}
else
{
/*
* Normal fixed width char(n) whose size can be determined by looking at
* the domain.
* Needs NCHAR work here to separate the dependencies on disk_size and
* mem_size.
*/
mem_length1 = mem_length2 = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
}
if (!ignore_trailing_space)
{
ti = (domain->type->id == DB_TYPE_CHAR);
}
strc = QSTR_CHAR_COMPARE (domain->collation_id, (unsigned char *) mem1, mem_length1, (unsigned char *) mem2,
mem_length2, ti);
c = MR_CMP_RETURN_CODE (strc);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_char (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
DB_VALUE_COMPARE_RESULT c;
int strc, size1, size2;
bool ti = true;
static bool ignore_trailing_space = prm_get_bool_value (PRM_ID_IGNORE_TRAILING_SPACE);
DB_TYPE type1 = (DB_TYPE) value1->domain.char_info.type;
DB_TYPE type2 = (DB_TYPE) value2->domain.char_info.type;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
/*
* Check if the is_max_string flag set for each DB_VALUE.
* If "value1" has the flag set, return 1, meaning that "value2" is Less Than "value1".
* If "value2" has the flag set, return -1, meaning that "value1" is Greater Than "value2".
*/
if (value1->data.ch.info.is_max_string != 0)
{
if (value2->data.ch.info.is_max_string != 0)
{
/* Both strings are max_string. Therefore equal. Even though this should not happen. */
assert (false);
return DB_EQ;
}
return DB_GT;
}
else
{
if (value2->data.ch.info.is_max_string != 0)
{
return DB_LT;
}
}
if (string1 == NULL || string2 == NULL || db_get_string_codeset (value1) != db_get_string_codeset (value2))
{
return DB_UNK;
}
if (collation == -1)
{
assert (false);
return DB_UNK;
}
size1 = db_get_string_size (value1);
size2 = db_get_string_size (value2);
if (!ignore_trailing_space)
{
if (!TP_IS_FIXED_LEN_CHAR_TYPE (type1) || !TP_IS_FIXED_LEN_CHAR_TYPE (type2))
{
ti = false;
}
}
strc = QSTR_CHAR_COMPARE (collation, string1, size1, string2, size2, ti);
c = MR_CMP_RETURN_CODE (strc);
return c;
}
#if defined (ENABLE_UNUSED_FUNCTION)
static int
mr_cmpval_char2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order, int *start_colp)
{
int c;
int len1, len2, string_size;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
string_size = (int) db_get_string_size (value1);
len1 = MIN (string_size, length);
string_size = (int) db_get_string_size (value2);
len2 = MIN (string_size, length);
c = QSTR_CHAR_COMPARE (string1, len1, string2, len2);
c = MR_CMP_RETURN_CODE (c);
return c;
}
#endif
const PR_TYPE tp_Char = {
"character", DB_TYPE_CHAR, 0, 0, 0, 1,
mr_initmem_char,
mr_initval_char,
mr_setmem_char,
mr_getmem_char,
mr_setval_char,
mr_data_lengthmem_char,
mr_data_lengthval_char,
mr_data_writemem_char,
mr_data_readmem_char,
mr_data_writeval_char,
mr_data_readval_char,
mr_index_lengthmem_char,
mr_index_lengthval_char,
mr_index_writeval_char,
mr_index_readval_char,
mr_index_cmpdisk_char,
mr_freemem_char,
mr_data_cmpdisk_char,
mr_cmpval_char
};
const PR_TYPE *tp_Type_char = &tp_Char;
/*
* TYPE BIT
*/
static void
mr_initmem_bit (void *memptr, TP_DOMAIN * domain)
{
#if !defined(NDEBUG)
int mem_length;
assert (!IS_FLOATING_PRECISION (domain->precision));
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
memset (memptr, 0, mem_length);
#endif
}
/*
* Due to the "within tolerance" comparison of domains used for
* assignment validation, we may get values in here whose precision is
* less than the precision of the actual attribute. This prevents
* having to copy a string just to coerce a value into a larger precision.
* Note that the precision of the source value may also come in as -1 here
* which is used to mean a "floating" precision that is assumed to be
* compatible with the destination domain as long as the associated value
* is within tolerance. This case is generally only seen for string
* literals that have been produced by the parser. These literals will
* not contain blank padding and strlen() or db_get_string_size() can be
* used to determine the number of significant characters.
*/
static int
mr_setmem_bit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
char *mem;
const char *src;
int src_precision, src_length, mem_length, pad;
if (value == NULL)
{
return NO_ERROR;
}
/* Get information from the value */
src = db_get_string (value);
src_precision = db_value_precision (value);
src_length = db_get_string_size (value); /* size in bytes */
if (src == NULL)
{
return NO_ERROR;
}
/*
* The only thing we really care about at this point, is the byte
* length of the string. The precision could be checked here but it
* really isn't necessary for this operation.
* Calculate the maximum number of bytes we have available here.
*/
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (mem_length < src_length)
{
/*
* should never get here, this is supposed to be caught during domain
* validation, need a better error message.
*/
error = ER_OBJ_DOMAIN_CONFLICT;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
else
{
/* copy the value into memory */
mem = (char *) memptr;
memcpy (mem, src, src_length);
/* Check for padding */
pad = mem_length - src_length;
if (pad)
{
int i;
for (i = src_length; i < mem_length; i++)
{
mem[i] = '\0';
}
}
}
return error;
}
static int
mr_getmem_bit (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int mem_length;
char *new_;
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (!copy)
{
new_ = (char *) mem;
}
else
{
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
return er_errid ();
}
memcpy (new_, (char *) mem, mem_length);
}
db_make_bit (value, domain->precision, new_, domain->precision);
if (copy)
{
value->need_clear = true;
}
return NO_ERROR;
}
static int
mr_data_lengthmem_bit (void *memptr, TP_DOMAIN * domain, int disk)
{
assert (!IS_FLOATING_PRECISION (domain->precision));
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
/* There is no difference between the disk & memory sizes. */
return STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
}
static void
mr_data_writemem_bit (OR_BUF * buf, void *mem, TP_DOMAIN * domain)
{
int mem_length;
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
/*
* We simply dump the memory image to disk, it will already have been padded.
* If this were a national character string, at this point, we'd have to
* decide now to perform a character set conversion.
*/
or_put_data (buf, (char *) mem, mem_length);
}
static void
mr_data_readmem_bit (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int mem_length, padding;
if (mem == NULL)
{
/* If we passed in a size, then use it. Otherwise, determine the size from the domain. */
if (size > 0)
{
or_advance (buf, size);
}
else
{
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
or_advance (buf, mem_length);
}
}
else
{
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (size != -1 && mem_length > size)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return;
}
or_get_data (buf, (char *) mem, mem_length);
/*
* We should only see padding if the string is contained within a packed
* value that had extra padding to ensure alignment. If we see these,
* just pop them out of the buffer. This shouldn't ever happen for the
* "getmem" function, only for the "getval" function.
*/
if (size != -1)
{
padding = size - mem_length;
if (padding > 0)
{
or_advance (buf, padding);
}
}
}
}
static void
mr_freemem_bit (void *memptr)
{
}
static void
mr_initval_bit (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_BIT, precision, scale);
}
static int
mr_setval_bit (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision, src_length, src_number_of_bits = 0;
char *new_ = NULL;
const char *src_string = NULL;
assert (!db_value_is_corrupted (src));
if (src == NULL || DB_IS_NULL (src))
{
db_value_domain_init (dest, DB_TYPE_BIT, DB_DEFAULT_PRECISION, 0);
}
else
{
/* Get information from the value */
src_string = db_get_bit (src, &src_number_of_bits);
src_precision = db_value_precision (src);
src_length = db_get_string_size (src); /* size in bytes */
db_value_domain_init (dest, DB_TYPE_BIT, src_precision, 0);
/* shouldn't see a NULL string at this point, treat as NULL */
if (src_string != NULL)
{
if (!copy)
{
db_make_bit (dest, src_precision, src_string, src_number_of_bits);
}
else
{
/* make sure the copy gets a NULL terminator */
new_ = (char *) db_private_alloc (NULL, src_length + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, src_string, src_length);
db_make_bit (dest, src_precision, new_, src_number_of_bits);
dest->need_clear = true;
}
}
}
}
return error;
}
static int
mr_index_lengthmem_bit (void *memptr, TP_DOMAIN * domain)
{
int mem_length;
assert (!IS_FLOATING_PRECISION (domain->precision) || memptr != NULL);
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
if (!IS_FLOATING_PRECISION (domain->precision))
{
mem_length = domain->precision;
return STR_SIZE (mem_length, TP_DOMAIN_CODESET (domain));
}
else
{
memcpy (&mem_length, memptr, OR_INT_SIZE);
return STR_SIZE (mem_length, TP_DOMAIN_CODESET (domain)) + OR_INT_SIZE;
}
}
static int
mr_index_lengthval_bit (DB_VALUE * value)
{
return mr_data_lengthval_bit (value, 1);
}
static int
mr_data_lengthval_bit (DB_VALUE * value, int disk)
{
int packed_length, src_precision;
const char *src = db_get_string (value);
if (src == NULL)
{
return 0;
}
src_precision = db_value_precision (value);
if (!IS_FLOATING_PRECISION (src_precision))
{
assert (db_get_string_codeset (value) == INTL_CODESET_RAW_BITS);
packed_length = STR_SIZE (src_precision, db_get_string_codeset (value));
}
else
{
/*
* Precision is "floating", calculate the effective precision based on the
* string length.
*/
packed_length = db_get_string_size (value);
/* add in storage for a size prefix on the packed value. */
packed_length += OR_INT_SIZE;
}
/*
* NOTE: We do NOT perform padding here, if this is used in the context
* of a packed value, the or_put_value() family of functions must handle
* their own padding, this is because "lengthval" and "writeval" can be
* used to place values into the disk representation of instances and
* there can be no padding in there.
*/
return packed_length;
}
static int
mr_index_writeval_bit (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_bit_internal (buf, value, CHAR_ALIGNMENT);
}
/*
* See commentary in mr_data_lengthval_bit.
*/
static int
mr_data_writeval_bit (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_bit_internal (buf, value, INT_ALIGNMENT);
}
static int
mr_writeval_bit_internal (OR_BUF * buf, DB_VALUE * value, int align)
{
int src_precision, src_length, packed_length, pad;
const char *src;
int rc = NO_ERROR;
src = db_get_string (value);
if (src == NULL)
{
return rc;
}
src_precision = db_value_precision (value);
src_length = db_get_string_size (value); /* size in bytes */
if (!IS_FLOATING_PRECISION (src_precision))
{
assert (db_get_string_codeset (value) == INTL_CODESET_RAW_BITS);
packed_length = STR_SIZE (src_precision, db_get_string_codeset (value));
if (packed_length < src_length)
{
/* should have caught this by now, truncate silently */
or_put_data (buf, src, packed_length);
}
else
{
rc = or_put_data (buf, src, src_length);
if (rc == NO_ERROR)
{
/* Check for padding */
pad = packed_length - src_length;
if (pad)
{
int i;
for (i = src_length; i < packed_length; i++)
{
rc = or_put_byte (buf, (int) '\0');
}
}
}
}
}
else
{
/*
* This is a "floating" precision value. Pack what we can based on the
* string size. Note that for this to work, this can only be packed
* as part of a domain tagged value and we must include a length
* prefix after the domain.
*/
packed_length = db_get_string_length (value);
/* store the size prefix */
if (align == INT_ALIGNMENT)
{
rc = or_put_int (buf, packed_length);
}
else
{
rc = or_put_data (buf, (char *) (&packed_length), OR_INT_SIZE);
}
if (rc == NO_ERROR)
{
/* store the data */
rc = or_put_data (buf, src, BITS_TO_BYTES (packed_length));
/* there is no blank padding in this case */
}
}
return rc;
}
static int
mr_index_readval_bit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_bit_internal (buf, value, domain, disk_size, copy, copy_buf, copy_buf_len, CHAR_ALIGNMENT);
}
static int
mr_data_readval_bit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_bit_internal (buf, value, domain, disk_size, copy, copy_buf, copy_buf_len, INT_ALIGNMENT);
}
static int
mr_readval_bit_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int disk_size, bool copy, char *copy_buf,
int copy_buf_len, int align)
{
int mem_length, padding;
int bit_length;
char *new_;
int rc = NO_ERROR;
if (IS_FLOATING_PRECISION (domain->precision))
{
if (align == INT_ALIGNMENT)
{
bit_length = or_get_int (buf, &rc);
}
else
{
rc = or_get_data (buf, (char *) (&bit_length), OR_INT_SIZE);
}
if (rc != NO_ERROR)
{
return ER_FAILED;
}
mem_length = BITS_TO_BYTES (bit_length);
if (value == NULL)
{
rc = or_advance (buf, mem_length);
}
else if (!copy)
{
db_make_bit (value, TP_FLOATING_PRECISION_VALUE, buf->ptr, bit_length);
value->need_clear = false;
rc = or_advance (buf, mem_length);
}
else
{
if (copy_buf && copy_buf_len >= mem_length + 1)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/*
* Allocate storage for the string including the kludge NULL
* terminator
*/
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), TP_FLOATING_PRECISION_VALUE, 0);
return ER_FAILED;
}
else
{
rc = or_get_data (buf, new_, mem_length);
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return rc;
}
new_[mem_length] = '\0'; /* append the kludge NULL terminator */
db_make_bit (value, TP_FLOATING_PRECISION_VALUE, new_, bit_length);
value->need_clear = (new_ != copy_buf) ? true : false;
}
}
}
else
{
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
if (disk_size != -1 && mem_length > disk_size)
{
/*
* If we're low here, we could just read what we have and make a
* smaller value. Still the domain should match at this point.
*/
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_SM_CORRUPTED, 0);
assert (false);
return ER_FAILED;
}
if (value == NULL)
{
rc = or_advance (buf, mem_length);
}
else if (!copy)
{
db_make_bit (value, domain->precision, buf->ptr, domain->precision);
value->need_clear = false;
rc = or_advance (buf, mem_length);
}
else
{
if (copy_buf && copy_buf_len >= mem_length + 1)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/*
* Allocate storage for the string including the kludge NULL
* terminator
*/
new_ = (char *) db_private_alloc (NULL, mem_length + 1);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), domain->precision, 0);
return ER_FAILED;
}
else
{
rc = or_get_data (buf, new_, mem_length);
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return rc;
}
new_[mem_length] = '\0'; /* append the kludge NULL terminator */
db_make_bit (value, domain->precision, new_, domain->precision);
value->need_clear = (new_ != copy_buf) ? true : false;
}
}
if (rc == NO_ERROR)
{
/*
* We should only see padding if the string is contained within a
* packed value that had extra padding to ensure alignment. If we see
* these, just pop them out of the buffer.
*/
if (disk_size != -1)
{
padding = disk_size - mem_length;
if (padding > 0)
{
rc = or_advance (buf, padding);
}
}
}
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_bit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_cmpdisk_bit_internal (mem1, mem2, domain, do_coercion, total_order, start_colp, CHAR_ALIGNMENT);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_bit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_cmpdisk_bit_internal (mem1, mem2, domain, do_coercion, total_order, start_colp, INT_ALIGNMENT);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpdisk_bit_internal (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp,
int align)
{
DB_VALUE_COMPARE_RESULT c;
int bit_length1, mem_length1, bit_length2, mem_length2, bitc;
if (IS_FLOATING_PRECISION (domain->precision))
{
if (align == INT_ALIGNMENT)
{
bit_length1 = OR_GET_INT (mem1);
bit_length2 = OR_GET_INT (mem2);
}
else
{
memcpy (&bit_length1, mem1, OR_INT_SIZE);
memcpy (&bit_length2, mem2, OR_INT_SIZE);
}
mem1 = (char *) mem1 + OR_INT_SIZE;
mem_length1 = BITS_TO_BYTES (bit_length1);
mem2 = (char *) mem2 + OR_INT_SIZE;
mem_length2 = BITS_TO_BYTES (bit_length2);
}
else
{
assert (TP_DOMAIN_CODESET (domain) == INTL_CODESET_RAW_BITS);
mem_length1 = mem_length2 = STR_SIZE (domain->precision, TP_DOMAIN_CODESET (domain));
}
bitc = bit_compare ((unsigned char *) mem1, mem_length1, (unsigned char *) mem2, mem_length2);
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_bit (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
DB_VALUE_COMPARE_RESULT c;
int bitc;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
bitc = bit_compare (string1, (int) db_get_string_size (value1), string2, (int) db_get_string_size (value2));
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_bit2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
int len1, len2, string_size;
int bitc;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
string_size = (int) db_get_string_size (value1);
len1 = MIN (string_size, length);
string_size = (int) db_get_string_size (value2);
len2 = MIN (string_size, length);
bitc = bit_compare (string1, len1, string2, len2);
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
const PR_TYPE tp_Bit = {
"bit", DB_TYPE_BIT, 0, 0, 0, 1,
mr_initmem_bit,
mr_initval_bit,
mr_setmem_bit,
mr_getmem_bit,
mr_setval_bit,
mr_data_lengthmem_bit,
mr_data_lengthval_bit,
mr_data_writemem_bit,
mr_data_readmem_bit,
mr_data_writeval_bit,
mr_data_readval_bit,
mr_index_lengthmem_bit,
mr_index_lengthval_bit,
mr_index_writeval_bit,
mr_index_readval_bit,
mr_index_cmpdisk_bit,
mr_freemem_bit,
mr_data_cmpdisk_bit,
mr_cmpval_bit
};
const PR_TYPE *tp_Type_bit = &tp_Bit;
/*
* TYPE VARBIT
*/
static void
mr_initmem_varbit (void *mem, TP_DOMAIN * domain)
{
*(char **) mem = NULL;
}
/*
* The main difference between "memory" strings and "value" strings is that
* the length tag is stored as an in-line prefix in the memory block allocated
* to hold the string characters.
*/
static int
mr_setmem_varbit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
const char *src;
char *cur, *new_, **mem;
int src_precision, src_length, src_length_bits, new_length;
/* get the current memory contents */
mem = (char **) memptr;
cur = *mem;
if (value == NULL || (src = db_get_string (value)) == NULL)
{
/* remove the current value */
if (cur != NULL)
{
db_private_free_and_init (NULL, cur);
mr_initmem_varbit (memptr, domain);
}
}
else
{
/*
* Get information from the value. Ignore precision for the time being
* since we really only care about the byte size of the value for varbit.
* Whether or not the value "fits" should have been checked by now.
*/
src_precision = db_value_precision (value);
src_length = db_get_string_size (value); /* size in bytes */
src_length_bits = db_get_string_length (value); /* size in bits */
new_length = src_length + sizeof (int);
new_ = (char *) db_private_alloc (NULL, new_length);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
if (cur != NULL)
{
db_private_free_and_init (NULL, cur);
}
/* pack in the length prefix */
*(int *) new_ = src_length_bits;
cur = new_ + sizeof (int);
/* store the string */
memcpy (cur, src, src_length);
*mem = new_;
}
}
return error;
}
static int
mr_getmem_varbit (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
int mem_bit_length;
char **mem, *cur, *new_;
/* get to the current value */
mem = (char **) memptr;
cur = *mem;
if (cur == NULL)
{
db_value_domain_init (value, DB_TYPE_VARBIT, domain->precision, 0);
value->need_clear = false;
}
else
{
/* extract the length prefix and the pointer to the actual string data */
mem_bit_length = *(int *) cur;
cur += sizeof (int);
if (!copy)
{
db_make_varbit (value, domain->precision, cur, mem_bit_length);
value->need_clear = false;
}
else
{
/* return it */
new_ = (char *) db_private_alloc (NULL, BITS_TO_BYTES (mem_bit_length) + 1);
if (new_ == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, cur, BITS_TO_BYTES (mem_bit_length));
db_make_varbit (value, domain->precision, new_, mem_bit_length);
value->need_clear = true;
}
}
}
return error;
}
/*
* For the disk representation, we may be adding pad bytes
* to round up to a word boundary.
*/
static int
mr_data_lengthmem_varbit (void *memptr, TP_DOMAIN * domain, int disk)
{
char **mem, *cur;
int len;
len = 0;
if (!disk)
{
len = tp_VarBit.size;
}
else if (memptr != NULL)
{
mem = (char **) memptr;
cur = *mem;
if (cur != NULL)
{
len = *(int *) cur;
len = or_packed_varbit_length (len);
}
}
return len;
}
static int
mr_index_lengthmem_varbit (void *memptr, TP_DOMAIN * domain)
{
OR_BUF buf;
int bitlen;
int rc = NO_ERROR;
or_init (&buf, (char *) memptr, -1);
bitlen = or_get_varbit_length (&buf, &rc);
return or_varbit_length (bitlen);
}
static void
mr_data_writemem_varbit (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
char **mem, *cur;
int bitlen;
mem = (char **) memptr;
cur = *mem;
if (cur != NULL)
{
bitlen = *(int *) cur;
cur += sizeof (int);
or_packed_put_varbit (buf, cur, bitlen);
}
}
/*
* The amount of memory requested is currently calculated based on the
* stored size prefix. If we ever go to a system where we avoid storing the
* size, then we could use the size argument passed in to this function but
* that may also include any padding byte that added to bring us up to a word
* boundary. Might want some way to determine which bytes at the end of a
* string are padding.
*/
static void
mr_data_readmem_varbit (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
char **mem, *cur, *new_;
int bit_len;
int mem_length, pad;
char *start;
int rc = NO_ERROR;
/* Must have an explicit size here - can't be determined from the domain */
if (size < 0)
{
return;
}
if (memptr == NULL)
{
if (size)
{
or_advance (buf, size);
}
}
else
{
mem = (char **) memptr;
cur = *mem;
/* should we be checking for existing strings ? */
#if 0
if (cur != NULL)
db_private_free_and_init (NULL, cur);
#endif
new_ = NULL;
if (size)
{
start = buf->ptr;
/* KLUDGE, we have some knowledge of how the thing is stored here in order have some control over the
* conversion between the packed length prefix and the full word memory length prefix. Might want to put this
* in another specialized or_ function. */
/* Get just the length prefix. */
bit_len = or_get_varbit_length (buf, &rc);
/*
* Allocate storage for this string, including our own full word size
* prefix.
*/
mem_length = BITS_TO_BYTES (bit_len) + sizeof (int);
new_ = (char *) db_private_alloc (NULL, mem_length);
if (new_ == NULL)
{
return;
}
else
{
/* store the length in our memory prefix */
*(int *) new_ = bit_len;
cur = new_ + sizeof (int);
/* read the string */
or_get_data (buf, cur, BITS_TO_BYTES (bit_len));
/* align like or_get_varchar */
or_get_align32 (buf);
}
/*
* If we were given a size, check to see if for some reason this is
* larger than the already word aligned string that we have now
* extracted. This shouldn't be the case but since we've got a
* length, we may as well obey it.
*/
pad = size - (int) (buf->ptr - start);
if (pad > 0)
{
or_advance (buf, pad);
}
}
*mem = new_;
}
}
static void
mr_freemem_varbit (void *memptr)
{
char *cur;
if (memptr != NULL)
{
cur = *(char **) memptr;
if (cur != NULL)
{
db_private_free_and_init (NULL, cur);
}
}
}
static void
mr_initval_varbit (DB_VALUE * value, int precision, int scale)
{
db_make_varbit (value, precision, NULL, 0);
value->need_clear = false;
}
static int
mr_setval_varbit (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
int src_precision, src_length, src_bit_length;
char *new_;
const char *src_str;
assert (!db_value_is_corrupted (src));
if (src == NULL || DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_VARBIT, DB_DEFAULT_PRECISION, 0);
}
else if ((src_str = db_get_string (src)) == NULL)
{
error = db_value_domain_init (dest, DB_TYPE_VARBIT, db_value_precision (src), 0);
}
else
{
/* Get information from the value. */
src_precision = db_value_precision (src);
src_length = db_get_string_size (src);
src_bit_length = db_get_string_length (src);
/* should we be paying attention to this? it is extremely dangerous */
if (!copy)
{
error = db_make_varbit (dest, src_precision, src_str, src_bit_length);
}
else
{
new_ = (char *) db_private_alloc (NULL, src_length + 1);
if (new_ == NULL)
{
db_value_domain_init (dest, DB_TYPE_VARBIT, src_precision, 0);
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
else
{
memcpy (new_, src_str, src_length);
db_make_varbit (dest, src_precision, new_, src_bit_length);
dest->need_clear = true;
}
}
}
return error;
}
static int
mr_index_lengthval_varbit (DB_VALUE * value)
{
return mr_lengthval_varbit_internal (value, 1, CHAR_ALIGNMENT);
}
static int
mr_index_writeval_varbit (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_varbit_internal (buf, value, CHAR_ALIGNMENT);
}
static int
mr_index_readval_varbit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_varbit_internal (buf, value, domain, size, copy, copy_buf, copy_buf_len, CHAR_ALIGNMENT);
}
static int
mr_data_lengthval_varbit (DB_VALUE * value, int disk)
{
return mr_lengthval_varbit_internal (value, disk, INT_ALIGNMENT);
}
static int
mr_data_writeval_varbit (OR_BUF * buf, DB_VALUE * value)
{
return mr_writeval_varbit_internal (buf, value, INT_ALIGNMENT);
}
static int
mr_data_readval_varbit (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
return mr_readval_varbit_internal (buf, value, domain, size, copy, copy_buf, copy_buf_len, INT_ALIGNMENT);
}
static int
mr_lengthval_varbit_internal (DB_VALUE * value, int disk, int align)
{
int bit_length, len;
len = 0;
if (value != NULL && db_get_string (value) != NULL)
{
bit_length = db_get_string_length (value); /* size in bits */
if (align == INT_ALIGNMENT)
{
len = or_packed_varbit_length (bit_length);
}
else
{
len = or_varbit_length (bit_length);
}
}
return len;
}
static int
mr_writeval_varbit_internal (OR_BUF * buf, DB_VALUE * value, int align)
{
int src_bit_length;
const char *str;
int rc = NO_ERROR;
if (value != NULL && (str = db_get_string (value)) != NULL)
{
src_bit_length = db_get_string_length (value); /* size in bits */
if (align == INT_ALIGNMENT)
{
rc = or_packed_put_varbit (buf, str, src_bit_length);
}
else
{
rc = or_put_varbit (buf, str, src_bit_length);
}
}
assert (buf->ptr <= buf->endptr); /* safety check in heap_file.c */
return rc;
}
/*
* Size can come in as negative here to create a value with a pointer
* directly to disk.
*
* Note that we have a potential conflict with this as -1 is a valid size
* to use here when the string has been packed with a domain/length prefix
* and we can determine the size from there. In current practice, this
* isn't a problem because due to word alignment, we'll never get a
* negative size here that is greater than -4.
*/
static int
mr_readval_varbit_internal (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len, int align)
{
int pad, precision;
int str_bit_length, str_length;
char *new_, *start = NULL;
int rc = NO_ERROR;
if (value == NULL)
{
if (size == -1)
{
rc = or_skip_varbit (buf, align);
}
else
{
if (size)
rc = or_advance (buf, size);
}
}
else
{
if (domain != NULL)
{
precision = domain->precision;
}
else
{
precision = DB_MAX_VARBIT_PRECISION;
}
if (size == 0)
{
/* its NULL */
db_value_domain_init (value, DB_TYPE_VARBIT, precision, 0);
}
else if (!copy)
{
str_bit_length = or_get_varbit_length (buf, &rc);
if (rc == NO_ERROR)
{
db_make_varbit (value, precision, buf->ptr, str_bit_length);
value->need_clear = false;
rc = or_skip_varbit_remainder (buf, str_bit_length, align);
}
}
else
{
if (size == -1)
{
/* Standard packed varbit with a size prefix */
; /* do nothing */
}
else
{ /* size != -1 */
/* Standard packed varbit within an area of fixed size, usually this means we're looking at the disk
* representation of an attribute. Just like the -1 case except we advance past the additional
* padding. */
start = buf->ptr;
} /* size != -1 */
str_bit_length = or_get_varbit_length (buf, &rc);
if (rc != NO_ERROR)
{
return ER_FAILED;
}
/* get the string byte length */
str_length = BITS_TO_BYTES (str_bit_length);
if (copy_buf && copy_buf_len >= str_length + 1)
{
/* read buf image into the copy_buf */
new_ = copy_buf;
}
else
{
/*
* Allocate storage for the string including the kludge NULL
* terminator
*/
new_ = (char *) db_private_alloc (NULL, str_length + 1);
}
if (new_ == NULL)
{
/* need to be able to return errors ! */
if (domain)
{
db_value_domain_init (value, TP_DOMAIN_TYPE (domain), TP_FLOATING_PRECISION_VALUE, 0);
}
return ER_FAILED;
}
else
{
/* do not read the kludge NULL terminator */
rc = or_get_data (buf, new_, str_length);
if (rc == NO_ERROR && align == INT_ALIGNMENT)
{
/* round up to a word boundary */
rc = or_get_align32 (buf);
}
if (rc != NO_ERROR)
{
if (new_ != copy_buf)
{
db_private_free_and_init (NULL, new_);
}
return ER_FAILED;
}
new_[str_length] = '\0'; /* append the kludge NULL terminator */
db_make_varbit (value, precision, new_, str_bit_length);
value->need_clear = (new_ != copy_buf) ? true : false;
if (size == -1)
{
/* Standard packed varbit with a size prefix */
; /* do nothing */
}
else
{ /* size != -1 */
/* Standard packed varbit within an area of fixed size, usually this means we're looking at the
* disk representation of an attribute. Just like the -1 case except we advance past the
* additional padding. */
pad = size - (int) (buf->ptr - start);
if (pad > 0)
{
rc = or_advance (buf, pad);
}
} /* size != -1 */
} /* else */
}
}
return rc;
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_varbit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
assert (domain != NULL);
return mr_data_cmpdisk_varbit (mem1, mem2, domain, do_coercion, total_order, start_colp);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_varbit (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
int bit_length1, bit_length2;
int mem_length1, mem_length2, bitc;
OR_BUF buf1, buf2;
int error = NO_ERROR;
assert (domain != NULL);
or_init (&buf1, (char *) mem1, 0);
bit_length1 = or_get_varbit_length (&buf1, &error);
mem_length1 = BITS_TO_BYTES (bit_length1);
assert (error == NO_ERROR);
or_init (&buf2, (char *) mem2, 0);
bit_length2 = or_get_varbit_length (&buf2, &error);
mem_length2 = BITS_TO_BYTES (bit_length2);
assert (error == NO_ERROR);
bitc = varbit_compare ((unsigned char *) buf1.ptr, mem_length1, (unsigned char *) buf2.ptr, mem_length2);
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_varbit (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
DB_VALUE_COMPARE_RESULT c;
int bitc;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
bitc = varbit_compare (string1, (int) db_get_string_size (value1), string2, (int) db_get_string_size (value2));
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_varbit2 (DB_VALUE * value1, DB_VALUE * value2, int length, int do_coercion, int total_order, int *start_colp)
{
DB_VALUE_COMPARE_RESULT c;
int len1, len2, string_size;
int bitc;
const unsigned char *string1 = REINTERPRET_CAST (const unsigned char *, db_get_string (value1));
const unsigned char *string2 = REINTERPRET_CAST (const unsigned char *, db_get_string (value2));
if (string1 == NULL || string2 == NULL)
{
return DB_UNK;
}
string_size = (int) db_get_string_size (value1);
len1 = MIN (string_size, length);
string_size = (int) db_get_string_size (value2);
len2 = MIN (string_size, length);
bitc = varbit_compare (string1, len1, string2, len2);
c = MR_CMP_RETURN_CODE (bitc);
return c;
}
const PR_TYPE tp_VarBit = {
"bit varying", DB_TYPE_VARBIT, 1, sizeof (const char *), 0, 1,
mr_initmem_varbit,
mr_initval_varbit,
mr_setmem_varbit,
mr_getmem_varbit,
mr_setval_varbit,
mr_data_lengthmem_varbit,
mr_data_lengthval_varbit,
mr_data_writemem_varbit,
mr_data_readmem_varbit,
mr_data_writeval_varbit,
mr_data_readval_varbit,
mr_index_lengthmem_varbit,
mr_index_lengthval_varbit,
mr_index_writeval_varbit,
mr_index_readval_varbit,
mr_index_cmpdisk_varbit,
mr_freemem_varbit,
mr_data_cmpdisk_varbit,
mr_cmpval_varbit
};
const PR_TYPE *tp_Type_varbit = &tp_VarBit;
static void
mr_initmem_enumeration (void *mem, TP_DOMAIN * domain)
{
*(unsigned short *) mem = 0;
}
static void
mr_initval_enumeration (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_ENUMERATION, precision, scale);
db_make_enumeration (value, 0, NULL, 0, LANG_SYS_CODESET, LANG_SYS_COLLATION);
}
static int
mr_setmem_enumeration (void *mem, TP_DOMAIN * domain, DB_VALUE * value)
{
if (value == NULL)
{
mr_initmem_enumeration (mem, domain);
}
else
{
*(unsigned short *) mem = db_get_enum_short (value);
}
return NO_ERROR;
}
static int
mr_getmem_enumeration (void *mem, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
unsigned short short_val = 0;
short_val = *(short *) mem;
return mr_setval_enumeration_internal (value, domain, short_val, 0, copy, NULL, 0);
}
static int
mr_setval_enumeration (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
const char *str = NULL;
bool need_clear = false;
if (src == NULL || DB_IS_NULL (src))
{
return db_value_domain_init (dest, DB_TYPE_ENUMERATION, DB_DEFAULT_PRECISION, DB_DEFAULT_SCALE);
}
if (db_get_enum_string (src) != NULL)
{
if (copy)
{
char *str_tmp = (char *) db_private_alloc (NULL, db_get_enum_string_size (src) + 1);
if (str_tmp == NULL)
{
assert (er_errid () != NO_ERROR);
return er_errid ();
}
memcpy (str_tmp, db_get_enum_string (src), db_get_enum_string_size (src));
str_tmp[db_get_enum_string_size (src)] = 0;
need_clear = true;
str = str_tmp;
}
else
{
str = db_get_enum_string (src);
}
}
/* get proper codeset from src */
db_make_enumeration (dest, db_get_enum_short (src), str, db_get_enum_string_size (src), db_get_enum_codeset (src),
db_get_enum_collation (src));
dest->need_clear = need_clear;
return NO_ERROR;
}
static void
mr_data_writemem_enumeration (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
unsigned short *mem = (unsigned short *) memptr;
or_put_short (buf, *mem);
}
static void
mr_data_readmem_enumeration (OR_BUF * buf, void *mem, TP_DOMAIN * domain, int size)
{
int rc = NO_ERROR;
if (mem == NULL)
{
or_advance (buf, tp_Enumeration.disksize);
}
else
{
*(unsigned short *) mem = (unsigned short) or_get_short (buf, &rc);
}
}
/*
* mr_setval_enumeration_internal () - make an enumeration value based on
* index and domain.
* return: NO_ERROR or error code.
* value(in/out):
* domain(in):
* index(in): index of enumeration string
* size(in):
* copy(in):
* copy_buf(in):
* copy_buf_len(in):
*/
static int
mr_setval_enumeration_internal (DB_VALUE * value, TP_DOMAIN * domain, unsigned short index, int size, bool copy,
char *copy_buf, int copy_buf_len)
{
bool need_clear = false;
int str_size;
const char *str = NULL;
DB_ENUM_ELEMENT *db_elem = NULL;
if (domain == NULL || DOM_GET_ENUM_ELEMS_COUNT (domain) == 0 || index == 0 || index == DB_ENUM_OVERFLOW_VAL)
{
db_make_enumeration (value, index, NULL, 0, TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = false;
return NO_ERROR;
}
if (index > DOM_GET_ENUM_ELEMS_COUNT (domain) && DOM_GET_ENUM_ELEMS_COUNT (domain) > 0)
{
assert (false);
return ER_FAILED;
}
db_elem = &DOM_GET_ENUM_ELEM (domain, index);
str_size = DB_GET_ENUM_ELEM_STRING_SIZE (db_elem);
if (!copy)
{
str = DB_GET_ENUM_ELEM_STRING (db_elem);
}
else
{
char *str_tmp = NULL;
if (copy_buf && copy_buf_len >= str_size + 1)
{
/* read buf image into the copy_buf */
str_tmp = copy_buf;
need_clear = false;
}
else
{
str_tmp = (char *) db_private_alloc (NULL, str_size + 1);
if (str_tmp == NULL)
{
return ER_FAILED;
}
need_clear = true;
}
memcpy (str_tmp, DB_GET_ENUM_ELEM_STRING (db_elem), str_size);
str_tmp[str_size] = 0;
str = str_tmp;
}
db_make_enumeration (value, index, str, str_size, TP_DOMAIN_CODESET (domain), TP_DOMAIN_COLLATION (domain));
value->need_clear = need_clear;
return NO_ERROR;
}
static int
mr_data_readval_enumeration (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
unsigned short s;
if (value == NULL)
{
rc = or_advance (buf, tp_Enumeration.disksize);
return rc;
}
s = (unsigned short) or_get_short (buf, &rc);
if (rc != NO_ERROR)
{
return rc;
}
return mr_setval_enumeration_internal (value, domain, s, size, copy, copy_buf, copy_buf_len);
}
static int
mr_data_writeval_enumeration (OR_BUF * buf, DB_VALUE * value)
{
return or_put_short (buf, db_get_enum_short (value));
}
static int
mr_index_writeval_enumeration (OR_BUF * buf, DB_VALUE * value)
{
unsigned short s = db_get_enum_short (value);
return or_put_data (buf, (char *) (&s), tp_Enumeration.disksize);
}
static int
mr_index_readval_enumeration (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
int rc = NO_ERROR;
unsigned short s;
if (value == NULL)
{
rc = or_advance (buf, tp_Enumeration.disksize);
return rc;
}
rc = or_get_data (buf, (char *) (&s), tp_Enumeration.disksize);
if (rc != NO_ERROR)
{
return rc;
}
return mr_setval_enumeration_internal (value, domain, s, size, copy, copy_buf, copy_buf_len);
}
static DB_VALUE_COMPARE_RESULT
mr_index_cmpdisk_enumeration (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
unsigned short s1, s2;
assert (domain != NULL);
COPYMEM (unsigned short, &s1, mem1);
COPYMEM (unsigned short, &s2, mem2);
return MR_CMP (s1, s2);
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_enumeration (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order,
int *start_colp)
{
unsigned short s1, s2;
assert (domain != NULL);
s1 = (unsigned short) OR_GET_SHORT (mem1);
s2 = (unsigned short) OR_GET_SHORT (mem2);
return MR_CMP (s1, s2);
}
static DB_VALUE_COMPARE_RESULT
mr_cmpval_enumeration (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp,
int collation)
{
unsigned short s1, s2;
s1 = db_get_enum_short (value1);
s2 = db_get_enum_short (value2);
return MR_CMP (s1, s2);
}
/*
* pr_get_compressed_data_from_buffer () - Uncompresses a data stored in buffer.
*
* return() : NO_ERROR or error code.
* buf(in) : The buffer from which is needed decompression.
* data(out) : The result of the decompression. !!! Needs to be alloc'ed !!!
* compressed_size(in) : The compressed data size.
* expected_decompressed_sizes(in) : The expected uncompressed data size.
*/
int
pr_get_compressed_data_from_buffer (struct or_buf *buf, char *data, int compressed_size, int expected_decompressed_size)
{
int rc = NO_ERROR;
/* Check if the string needs decompression */
if (compressed_size > 0)
{
int decompressed_size = 0;
/* Handle decompression */
/* decompressing the string */
// *INDENT-OFF*
decompressed_size =
cubcompress::decompress<cubcompress::LZ4> (buf->ptr, compressed_size, data, expected_decompressed_size);
// *INDENT-ON*
if (decompressed_size < 0)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_IO_LZ4_DECOMPRESS_FAIL, 0);
return ER_IO_LZ4_DECOMPRESS_FAIL;
}
assert (decompressed_size == expected_decompressed_size);
data[decompressed_size] = '\0';
}
else
{
/* String is not compressed and buf->ptr is pointing towards an array of chars of length equal to
* decompressed_size */
rc = or_get_data (buf, data, expected_decompressed_size);
data[expected_decompressed_size] = '\0';
}
return rc;
}
/*
* pr_get_compression_length() - Simulate a compression to find its length to be stored on the disk.
*
* return() : The length of the compression, based on the new encoding of varchar.
* If the compression fails, then it returns charlen.
* string(in) : The string to be compressed.
* str_length(in) : The length of the string to be compressed.
*/
int
pr_get_compression_length (const char *string, int str_length)
{
char *compressed_string = NULL;
int compressed_length = 0;
int rc = NO_ERROR;
int length = 0, compress_buffer_size;
assert (str_length >= OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION);
if (!pr_Enable_string_compression || str_length > LZ4_MAX_INPUT_SIZE) /* compression is not set */
{
return str_length;
}
/* Alloc memory for the compressed string */
// *INDENT-OFF*
compress_buffer_size = cubcompress::bound<cubcompress::LZ4> (str_length);
// *INDENT-ON*
compressed_string = (char *) malloc (compress_buffer_size);
if (compressed_string == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, (size_t) compress_buffer_size);
return str_length;
}
/* Compress the string */
// *INDENT-OFF*
compressed_length =
cubcompress::compress<cubcompress::LZ4> (string, str_length, compressed_string, compress_buffer_size);
// *INDENT-ON*
if (compressed_length <= 0)
{
/* We should not be having any kind of errors here. Because if this compression fails, there is not warranty
* that the compression from putting data into buffer will fail as well. This needs to be checked but for now
* we leave it as it is.
*/
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_IO_LZ4_COMPRESS_FAIL, 4, FILEIO_ZIP_LZ4_METHOD,
fileio_get_zip_method_string (FILEIO_ZIP_LZ4_METHOD), FILEIO_ZIP_LZ4_DEFAULT_LEVEL,
fileio_get_zip_level_string (FILEIO_ZIP_LZ4_DEFAULT_LEVEL));
goto cleanup;
}
assert (compressed_length <= compress_buffer_size);
if (compressed_length < str_length - 8)
{
/* Compression successful */
length = compressed_length;
}
else
{
/* Compression failed */
length = str_length;
}
cleanup:
if (compressed_string != NULL)
{
free_and_init (compressed_string);
}
return length;
}
/*
* pr_get_size_and_write_string_to_buffer ()
* : Writes a VARCHAR to buffer and gets the correct size on the disk.
*
* buf(out) : Buffer to be written to.
* val_p(in) : Memory area to be written to.
* value(in) : DB_VALUE to be written.
* val_size(out) : Disk size of the DB_VALUE.
* align(in) :
*
* Note:
* We use this to avoid double compression when it is required to have the size of the DB_VALUE, previous
* to the write of the DB_VALUE in the buffer.
*/
int
pr_get_size_and_write_string_to_buffer (struct or_buf *buf, char *val_p, DB_VALUE * value, int *val_size, int align)
{
const char *string = NULL, *str = NULL;
char *compressed_string = NULL;
int rc = NO_ERROR, str_length = 0, length = 0;
int compression_length = 0, compress_buffer_size;
bool compressed = false;
/* Checks to be sure that we have the correct input */
assert (DB_VALUE_DOMAIN_TYPE (value) == DB_TYPE_STRING);
assert (db_get_string_size (value) >= OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION);
string = db_get_string (value);
str_length = db_get_string_size (value);
*val_size = 0;
if (!pr_Enable_string_compression || db_get_string_size (value) > LZ4_MAX_INPUT_SIZE) /* compression is not set */
{
length = str_length;
compression_length = 0;
str = string;
goto after_compression;
}
/* Step 1 : Compress, if possible, the dbvalue */
/* Alloc memory for the compressed string */
// *INDENT-OFF*
compress_buffer_size = cubcompress::bound<cubcompress::LZ4> (str_length);
// *INDENT-ON*
compressed_string = (char *) malloc (compress_buffer_size);
if (compressed_string == NULL)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, compress_buffer_size);
rc = ER_OUT_OF_VIRTUAL_MEMORY;
goto cleanup;
}
// *INDENT-OFF*
compression_length =
cubcompress::compress<cubcompress::LZ4> (string, str_length, compressed_string, compress_buffer_size);
// *INDENT-ON*
if (compression_length <= 0)
{
/* We should not be having any kind of errors here. Because if this compression fails, there is not warranty
* that the compression from putting data into buffer will fail as well. This needs to be checked but for now
* we leave it as it is.
*/
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_IO_LZ4_COMPRESS_FAIL, 4, FILEIO_ZIP_LZ4_METHOD,
fileio_get_zip_method_string (FILEIO_ZIP_LZ4_METHOD), FILEIO_ZIP_LZ4_DEFAULT_LEVEL,
fileio_get_zip_level_string (FILEIO_ZIP_LZ4_DEFAULT_LEVEL));
rc = ER_IO_LZ4_COMPRESS_FAIL;
goto cleanup;
}
assert (compression_length <= compress_buffer_size);
if (compression_length < str_length - 8)
{
/* Compression successful */
length = (int) compression_length;
compressed = true;
str = compressed_string;
}
else
{
/* Compression failed */
length = str_length;
compression_length = 0;
str = string;
}
after_compression:
/*
* Step 2 : Compute the disk size of the dbvalue.
* We are sure that the initial string length is greater than 255, which means that the new encoding applies.
*/
switch (DB_VALUE_DOMAIN_TYPE (value))
{
case DB_TYPE_VARCHAR:
*val_size = or_packed_varchar_length (length + PRIM_TEMPORARY_DISK_SIZE) - PRIM_TEMPORARY_DISK_SIZE;
break;
default:
/* It should not happen */
assert (false);
rc = ER_FAILED;
goto cleanup;
}
/* Step 3 : Insert the disk representation of the dbvalue in the buffer */
switch (DB_VALUE_DOMAIN_TYPE (value))
{
case DB_TYPE_STRING:
rc = pr_write_compressed_string_to_buffer (buf, str, (int) compression_length, str_length, align);
break;
default:
/* It should not happen. */
assert (false);
rc = ER_FAILED;
goto cleanup;
}
cleanup:
if (compressed_string != NULL)
{
free_and_init (compressed_string);
}
return rc;
}
/* pr_write_compressed_string_to_buffer() : Similar function to the previous implementation of
* or_put_varchar_internal.
*
* buf(in/out) : Buffer to be written the string.
* compressed_string(in) : The string to be written.
* compressed_length(in) : Compressed length of the string. If it is 0, then no
* compression happened.
* decompressed_length(in) : Decompressed length of the string.
* align(in) :
*/
static int
pr_write_compressed_string_to_buffer (OR_BUF * buf, const char *compressed_string, int compressed_length,
int decompressed_length, int align)
{
int storage_length = 0;
int rc = NO_ERROR;
assert (decompressed_length >= OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION
&& (compressed_length <= 0 || decompressed_length <= LZ4_MAX_INPUT_SIZE));
/* store the size prefix */
rc = or_put_byte (buf, 0xFF);
if (rc != NO_ERROR)
{
return rc;
}
/* Store the compressed size */
OR_PUT_INT (&storage_length, compressed_length);
rc = or_put_data (buf, (char *) &storage_length, OR_INT_SIZE);
if (rc != NO_ERROR)
{
return rc;
}
/* Store the decompressed size */
OR_PUT_INT (&storage_length, decompressed_length);
rc = or_put_data (buf, (char *) &storage_length, OR_INT_SIZE);
if (rc != NO_ERROR)
{
return rc;
}
/* Get the string disk size */
if (compressed_length > 0)
{
storage_length = compressed_length;
}
else
{
storage_length = decompressed_length;
}
/* store the string bytes */
rc = or_put_data (buf, compressed_string, storage_length);
if (rc != NO_ERROR)
{
return rc;
}
if (align == INT_ALIGNMENT)
{
/* kludge, temporary NULL terminator */
rc = or_put_byte (buf, 0);
if (rc != NO_ERROR)
{
return rc;
}
/* round up to a word boundary */
rc = or_put_align32 (buf);
}
return rc;
}
/*
* pr_write_uncompressed_string_to_buffer() :- Writes a string with a size less than
* OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION to buffer.
*
* return :- NO_ERROR or error code.
* buf(in/out) :- Buffer to be written to.
* string(in) :- String to be written.
* size(in) :- Size of the string.
* align() :-
*/
static int
pr_write_uncompressed_string_to_buffer (OR_BUF * buf, const char *string, int size, int align)
{
int rc = NO_ERROR;
assert (size < OR_MINIMUM_STRING_LENGTH_FOR_COMPRESSION);
/* Store the size prefix */
rc = or_put_byte (buf, size);
if (rc != NO_ERROR)
{
return rc;
}
/* store the string bytes */
rc = or_put_data (buf, string, size);
if (rc != NO_ERROR)
{
return rc;
}
if (align == INT_ALIGNMENT)
{
/* kludge, temporary NULL terminator */
rc = or_put_byte (buf, 0);
if (rc != NO_ERROR)
{
return rc;
}
/* round up to a word boundary */
rc = or_put_align32 (buf);
}
return rc;
}
/*
* pr_data_compress_string() :- Does compression for a string.
*
* return :- NO_ERROR or error code.
* string(in) :- String to be compressed.
* str_length(in) :- The size of the string.
* compressed_string(out) :- The compressed string. Needs to be alloced!!!!!
* compress_buffer_size(in) :- The compressed string buffer size.
* compressed_length(out) :- The compressed string length.
*
*/
int
pr_data_compress_string (const char *string, int str_length, char *compressed_string, int compress_buffer_size,
int *compressed_length)
{
int compressed_length_local = 0;
assert (string != NULL && compressed_string != NULL && compressed_length != NULL && str_length >= 0
&& compress_buffer_size >= 0);
if (!OR_IS_STRING_LENGTH_COMPRESSABLE (str_length))
{
*compressed_length = 0;
return NO_ERROR;
}
if (!pr_Enable_string_compression) /* compression is not set */
{
*compressed_length = -1;
return NO_ERROR;
}
/* Compress the string */
// *INDENT-OFF*
compressed_length_local =
cubcompress::compress<cubcompress::LZ4> (string, str_length, compressed_string, compress_buffer_size);
// *INDENT-ON*
if (compressed_length_local <= 0)
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_IO_LZ4_COMPRESS_FAIL, 4, FILEIO_ZIP_LZ4_METHOD,
fileio_get_zip_method_string (FILEIO_ZIP_LZ4_METHOD), FILEIO_ZIP_LZ4_DEFAULT_LEVEL,
fileio_get_zip_level_string (FILEIO_ZIP_LZ4_DEFAULT_LEVEL));
return ER_IO_LZ4_COMPRESS_FAIL;
}
assert (compressed_length_local <= compress_buffer_size);
if (compressed_length_local >= str_length - 8)
{
/* Compression successful but its length exceeds the original length of the string. */
/* We will also be freeing the compressed_string since we will not need it anymore. */
*compressed_length = -1;
}
else
{
/* Compression successful */
*compressed_length = compressed_length_local;
}
return NO_ERROR;
}
/*
* pr_clear_compressed_string() :- Clears the compressed string that might have been stored in a DB_VALUE.
* This needs to succeed only for VARCHAR type.
*
* return () :- NO_ERROR or error code.
* value(in/out) :- The DB_VALUE that needs the clearing.
*/
int
pr_clear_compressed_string (DB_VALUE * value)
{
char *data = NULL;
DB_TYPE db_type;
if (value == NULL || DB_IS_NULL (value))
{
return NO_ERROR; /* do nothing */
}
db_type = DB_VALUE_DOMAIN_TYPE (value);
/* Make sure we clear only for VARCHAR type. */
if (db_type != DB_TYPE_VARCHAR)
{
return NO_ERROR; /* do nothing */
}
if (value->data.ch.info.compressed_need_clear == false)
{
return NO_ERROR;
}
if (value->data.ch.medium.compressed_size <= 0)
{
return NO_ERROR; /* do nothing */
}
data = value->data.ch.medium.compressed_buf;
if (data != NULL)
{
db_private_free_and_init (NULL, data);
}
db_set_compressed_string (value, NULL, DB_NOT_YET_COMPRESSED, false);
return NO_ERROR;
}
/*
* pr_do_db_value_string_compression() :- Test a DB_VALUE for VARCHAR type and do string compression
* :- for such types.
*
* return() :- NO_ERROR or error code.
* value(in/out) :- The DB_VALUE to be tested.
*/
int
pr_do_db_value_string_compression (DB_VALUE * value)
{
DB_TYPE db_type;
const char *string;
char *compressed_string;
int rc = NO_ERROR;
int src_size = 0, compressed_size, compressed_length;
if (value == NULL || DB_IS_NULL (value))
{
return rc; /* do nothing */
}
db_type = DB_VALUE_DOMAIN_TYPE (value);
/* Make sure we clear only for VARCHAR type. */
if (db_type != DB_TYPE_VARCHAR)
{
return rc; /* do nothing */
}
/* Make sure the value has not been through a compression before */
if (value->data.ch.medium.compressed_size != DB_NOT_YET_COMPRESSED)
{
return rc;
}
string = db_get_string (value);
src_size = db_get_string_size (value);
if (!pr_Enable_string_compression || !OR_IS_STRING_LENGTH_COMPRESSABLE (src_size))
{
/* Either compression was disabled or the source size is less than the compression threshold. */
value->data.ch.medium.compressed_buf = NULL;
value->data.ch.medium.compressed_size = DB_UNCOMPRESSABLE;
return rc;
}
/* Alloc memory for compression */
// *INDENT-OFF*
compressed_size = cubcompress::bound<cubcompress::LZ4> (src_size);
// *INDENT-ON*
compressed_string = (char *) db_private_alloc (NULL, compressed_size);
if (compressed_string == NULL)
{
rc = ER_OUT_OF_VIRTUAL_MEMORY;
return rc;
}
rc = pr_data_compress_string (string, src_size, compressed_string, compressed_size, &compressed_length);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
goto error;
}
if (compressed_length > 0)
{
/* Compression successful */
db_set_compressed_string (value, compressed_string, compressed_length, true);
return rc;
}
else
{
/* Compression failed */
db_set_compressed_string (value, NULL, DB_UNCOMPRESSABLE, false);
goto error;
}
error:
if (compressed_string != NULL)
{
db_private_free_and_init (NULL, compressed_string);
}
return rc;
}
const PR_TYPE tp_Json = {
"json", DB_TYPE_JSON, 1, sizeof (DB_JSON), 0, 1,
mr_initmem_json,
mr_initval_json,
mr_setmem_json,
mr_getmem_json,
mr_setval_json,
mr_data_lengthmem_json,
mr_data_lengthval_json,
mr_data_writemem_json,
mr_data_readmem_json,
mr_data_writeval_json,
mr_data_readval_json,
NULL, /* index_lengthmem */
NULL, /* index_lengthval */
NULL, /* index_writeval */
NULL, /* index_readval */
NULL, /* index_cmpdisk */
mr_freemem_json,
mr_data_cmpdisk_json,
mr_cmpval_json
};
const PR_TYPE *tp_Type_json = &tp_Json;
static void
mr_initmem_json (void *mem, TP_DOMAIN * domain)
{
DB_JSON *json = (DB_JSON *) mem;
if (json != NULL)
{
json->document = NULL;
json->schema_raw = NULL;
}
else
{
assert (false);
}
}
static int
mr_setmem_json (void *memptr, TP_DOMAIN * domain, DB_VALUE * value)
{
int error = NO_ERROR;
DB_JSON *json;
JSON_DOC *doc;
json = (DB_JSON *) memptr;
if (json != NULL)
{
mr_freemem_json (memptr);
}
else
{
assert (false);
}
if (value == NULL)
{
return NO_ERROR;
}
doc = db_get_json_document (value);
if (doc != NULL)
{
error = db_get_deep_copy_of_json (&value->data.json, json);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
return error;
}
}
return error;
}
static int
mr_getmem_json (void *memptr, TP_DOMAIN * domain, DB_VALUE * value, bool copy)
{
int error = NO_ERROR;
const char *json_schema = NULL;
DB_JSON *json, json_copy;
JSON_DOC *new_doc = NULL;
json = (DB_JSON *) memptr;
if (json == NULL)
{
db_make_null (value);
db_value_domain_init (value, DB_TYPE_JSON, domain->precision, 0);
value->need_clear = false;
return NO_ERROR;
}
if (!copy)
{
json_schema = json->schema_raw;
new_doc = json->document;
}
else
{
error = db_init_db_json_pointers (&json_copy);
if (error != NO_ERROR)
{
return error;
}
error = db_get_deep_copy_of_json (json, &json_copy);
if (error != NO_ERROR)
{
return error;
}
json_schema = json_copy.schema_raw;
new_doc = json_copy.document;
}
db_make_json (value, new_doc, copy);
db_get_json_schema (value) = json_schema;
return error;
}
static int
mr_data_lengthmem_json (void *memptr, TP_DOMAIN * domain, int disk)
{
int len = 0;
DB_JSON *json;
if (!disk)
{
len = tp_Json.size;
}
else
{
if (memptr != NULL)
{
json = (DB_JSON *) memptr;
if (json->document == NULL)
{
return 0;
}
return (int) db_json_serialize_length (*json->document);
}
}
return len;
}
static void
mr_data_writemem_json (OR_BUF * buf, void *memptr, TP_DOMAIN * domain)
{
DB_JSON *json;
int rc = NO_ERROR;
json = (DB_JSON *) memptr;
if (json == NULL || json->document == NULL)
{
return;
}
rc = db_json_serialize (*json->document, *buf);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
}
}
static void
mr_data_readmem_json (OR_BUF * buf, void *memptr, TP_DOMAIN * domain, int size)
{
DB_JSON *json;
int rc = NO_ERROR;
json = (DB_JSON *) memptr;
if (json == NULL)
{
if (size != 0)
{
if (or_advance (buf, size) != NO_ERROR)
{
assert (false);
}
}
return;
}
if (size < 0)
{
assert (false);
return;
}
if (size == 0)
{
mr_initmem_json (memptr, domain);
return;
}
rc = db_json_deserialize (buf, json->document);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
db_json_delete_doc (json->document);
}
}
static void
mr_freemem_json (void *memptr)
{
DB_JSON *cur;
cur = (DB_JSON *) memptr;
if (cur != NULL)
{
if (cur->schema_raw != NULL)
{
db_private_free (NULL, const_cast < char *>(cur->schema_raw));
cur->schema_raw = NULL;
}
if (cur->document != NULL)
{
db_json_delete_doc (cur->document);
cur->document = NULL;
}
}
}
static void
mr_initval_json (DB_VALUE * value, int precision, int scale)
{
db_value_domain_init (value, DB_TYPE_JSON, precision, scale);
value->need_clear = false;
}
static int
mr_setval_json (DB_VALUE * dest, const DB_VALUE * src, bool copy)
{
int error = NO_ERROR;
if (src == NULL || DB_IS_NULL (src))
{
error = db_value_domain_init (dest, DB_TYPE_JSON, DB_DEFAULT_PRECISION, 0);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
return error;
}
}
else
{
db_value_domain_init (dest, DB_TYPE_JSON, DB_DEFAULT_PRECISION, 0);
dest->domain.general_info.is_null = 0;
if (copy)
{
dest->data.json.document = db_json_get_copy_of_doc (src->data.json.document);
dest->data.json.schema_raw = db_private_strdup (NULL, src->data.json.schema_raw);
dest->need_clear = true;
}
else
{
dest->data.json.document = src->data.json.document;
dest->data.json.schema_raw = src->data.json.schema_raw;
dest->need_clear = false;
}
}
return error;
}
static int
mr_data_lengthval_json (DB_VALUE * value, int disk)
{
if (!disk)
{
return tp_Json.size;
}
if (value->data.json.document != NULL)
{
return (int) db_json_serialize_length (*value->data.json.document);
}
else
{
return 0;
}
}
static int
mr_data_writeval_json (OR_BUF * buf, DB_VALUE * value)
{
int rc = NO_ERROR;
if (value->data.json.document == NULL || DB_IS_NULL (value))
{
assert (false);
return ER_FAILED;
}
#if !defined(NDEBUG)
int estimated_length = mr_data_lengthval_json (value, true);
if (buf->ptr + estimated_length > buf->endptr)
{
assert (false);
}
#endif
JSON_DOC *json_doc = db_get_json_document (value);
rc = db_json_serialize (*json_doc, *buf);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
}
return rc;
}
static int
mr_data_readval_json (OR_BUF * buf, DB_VALUE * value, TP_DOMAIN * domain, int size, bool copy, char *copy_buf,
int copy_buf_len)
{
JSON_DOC *doc = NULL;
char *json_raw = NULL;
int rc = NO_ERROR;
db_make_null (value);
if (size == 0)
{
/* early out, means json is NULL */
return NO_ERROR;
}
rc = db_json_deserialize (buf, doc);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
return rc;
}
db_make_json (value, doc, true);
return NO_ERROR;
}
static DB_VALUE_COMPARE_RESULT
mr_data_cmpdisk_json (void *mem1, void *mem2, TP_DOMAIN * domain, int do_coercion, int total_order, int *start_colp)
{
char *first, *second;
OR_BUF first_buf, second_buf;
DB_VALUE json1, json2;
JSON_DOC *doc1 = NULL, *doc2 = NULL;
int rc = NO_ERROR;
DB_VALUE_COMPARE_RESULT res = DB_UNK;
first = (char *) mem1;
second = (char *) mem2;
or_init (&first_buf, first, 0);
or_init (&second_buf, second, 0);
rc = db_json_deserialize (&first_buf, doc1);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
return res;
}
rc = db_json_deserialize (&second_buf, doc2);
if (rc != NO_ERROR)
{
ASSERT_ERROR ();
return res;
}
db_make_json (&json1, doc1, true);
db_make_json (&json2, doc2, true);
res = mr_cmpval_json (&json1, &json2, do_coercion, total_order, 0, 0);
pr_clear_value (&json1);
pr_clear_value (&json2);
return res;
}
/* when total_order is true,
* we force to string uncomparable types.
* this is because "order by" uses total_order=true
* and we don't want to fail. The standard says that
* only scalar and nulls are comparable.
*
* we only return DB_UNK when either one is null and
* total_order is false
*/
static DB_VALUE_COMPARE_RESULT
mr_cmpval_json (DB_VALUE * value1, DB_VALUE * value2, int do_coercion, int total_order, int *start_colp, int collation)
{
JSON_DOC *doc1 = NULL, *doc2 = NULL;
DB_JSON_TYPE type1 = DB_JSON_UNKNOWN;
DB_JSON_TYPE type2 = DB_JSON_UNKNOWN;
DB_VALUE scalar_value1, scalar_value2;
DB_VALUE_COMPARE_RESULT cmp_result;
bool is_value1_null = true, is_value2_null = true;
int error_code;
doc1 = db_get_json_document (value1);
doc2 = db_get_json_document (value2);
is_value1_null = DB_IS_NULL (value1) || ((type1 = db_json_get_type (doc1)) == DB_JSON_NULL);
is_value2_null = DB_IS_NULL (value2) || ((type2 = db_json_get_type (doc2)) == DB_JSON_NULL);
if (is_value1_null || is_value2_null)
{
if (!total_order)
{
return DB_UNK;
}
if (is_value1_null && is_value2_null)
{
return DB_EQ;
}
return is_value1_null ? DB_LT : DB_GT;
}
/* db_json_get_type shouldn't return DB_JSON_UNKNOWN, this represents a bug */
assert (type1 != DB_JSON_UNKNOWN && type2 != DB_JSON_UNKNOWN);
db_make_null (&scalar_value1);
db_make_null (&scalar_value2);
if (db_json_doc_is_uncomparable (doc1) || db_json_doc_is_uncomparable (doc2))
{
/* force string comp */
char *str1 = NULL, *str2 = NULL;
str1 = db_json_get_json_body_from_document (*doc1);
str2 = db_json_get_json_body_from_document (*doc2);
db_make_string (&scalar_value1, str1);
db_make_string (&scalar_value2, str2);
scalar_value1.need_clear = true;
scalar_value2.need_clear = true;
}
else
{
/* This is not according to standard, in SQL/JSON standard
* different types should not be compared, but rather throw
* an error. We chose to also compare different scalar types
* even when total_order is false.
*/
error_code = db_convert_json_into_scalar (value1, &scalar_value1);
if (error_code != NO_ERROR)
{
/* this shouldn't happen */
assert (false);
pr_clear_value (&scalar_value1);
return DB_UNK;
}
error_code = db_convert_json_into_scalar (value2, &scalar_value2);
if (error_code != NO_ERROR)
{
/* this shouldn't happen */
assert (false);
pr_clear_value (&scalar_value1);
pr_clear_value (&scalar_value2);
return DB_UNK;
}
}
cmp_result = tp_value_compare_with_error (&scalar_value1, &scalar_value2, do_coercion, total_order, NULL);
pr_clear_value (&scalar_value1);
pr_clear_value (&scalar_value2);
return cmp_result;
}