File cas_common_function.c¶
File List > broker > cas_common_function.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.
*
*/
/*
* cas_common_function.c
*/
#ident "$Id$"
#include "cas_common_function.h"
#include "cas_log.h"
#include "cas_net_buf.h"
#include "cas_error.h"
#include "intl_support.h"
#include "object_primitive.h"
#include "broker_cas_cci.h"
#include "dbtype.h"
static const char *type_str_tbl[] = {
"NULL", /* CCI_U_TYPE_NULL */
"CHAR", /* CCI_U_TYPE_CHAR */
"VARCHAR", /* CCI_U_TYPE_STRING */
/* 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.
*/
"NCHAR", /* CCI_U_TYPE_NCHAR_DEPRECATED */
"VARNCHAR", /* CCI_U_TYPE_VARNCHAR_DEPRECATED */
"BIT", /* CCI_U_TYPE_BIT */
"VARBIT", /* CCI_U_TYPE_VARBIT */
"NUMERIC", /* CCI_U_TYPE_NUMERIC */
"INT", /* CCI_U_TYPE_INT */
"SHORT", /* CCI_U_TYPE_SHORT */
"MONETARY", /* CCI_U_TYPE_MONETARY */
"FLOAT", /* CCI_U_TYPE_FLOAT */
"DOUBLE", /* CCI_U_TYPE_DOUBLE */
"DATE", /* CCI_U_TYPE_DATE */
"TIME", /* CCI_U_TYPE_TIME */
"TIMESTAMP", /* CCI_U_TYPE_TIMESTAMP */
"SET", /* CCI_U_TYPE_SET */
"MULTISET", /* CCI_U_TYPE_MULTISET */
"SEQUENCE", /* CCI_U_TYPE_SEQUENCE */
"OBJECT", /* CCI_U_TYPE_OBJECT */
"RESULTSET", /* CCI_U_TYPE_RESULTSET */
"BIGINT", /* CCI_U_TYPE_BIGINT */
"DATETIME", /* CCI_U_TYPE_DATETIME */
"BLOB", /* CCI_U_TYPE_BLOB */
"CLOB", /* CCI_U_TYPE_CLOB */
"ENUM", /* CCI_U_TYPE_ENUM */
"USHORT", /* CCI_U_TYPE_USHORT */
"UINT", /* CCI_U_TYPE_UINT */
"UBIGINT", /* CCI_U_TYPE_UBIGINT */
"TIMESTAMPTZ", /* CCI_U_TYPE_TIMESTAMPTZ */
"TIMESTAMPLTZ", /* CCI_U_TYPE_TIMESTAMPLTZ */
"DATETIMETZ", /* CCI_U_TYPE_DATETIMETZ */
"DATETIMELTZ", /* CCI_U_TYPE_DATETIMELTZ */
"TIMETZ", /* CCI_U_TYPE_TIMETZ */
"JSON", /* CCI_U_TYPE_JSON */
};
void
cas_common_bind_value_print (char type, void *net_value, bool slow_log, INTL_CODESET charset)
{
int data_size;
void (*write2_func) (const char *, ...);
void (*fwrite_func) (char *value, int size);
if (slow_log)
{
write2_func = cas_slow_log_write2;
fwrite_func = cas_slow_log_write_value_string;
}
else
{
write2_func = cas_log_write2_nonl;
fwrite_func = cas_log_write_value_string;
}
net_arg_get_size (&data_size, net_value);
if (data_size <= 0)
{
type = CCI_U_TYPE_NULL;
data_size = 0;
}
switch (type)
{
case CCI_U_TYPE_CHAR:
case CCI_U_TYPE_STRING:
case CCI_U_TYPE_ENUM:
case CCI_U_TYPE_JSON:
{
char *str_val;
int val_size;
int num_chars = 0;
net_arg_get_str (&str_val, &val_size, net_value);
if (val_size > 0)
{
/* CAS protocol: string payload carries a trailing NUL that is counted in val_size. */
assert (str_val[val_size - 1] == '\0');
intl_char_count ((const unsigned char *) str_val, val_size - 1, charset, &num_chars);
}
write2_func ("(%d)", num_chars);
fwrite_func (str_val, val_size - 1);
}
break;
case CCI_U_TYPE_BIT:
case CCI_U_TYPE_VARBIT:
case CCI_U_TYPE_NUMERIC:
{
char *str_val;
int val_size;
net_arg_get_str (&str_val, &val_size, net_value);
if (type != CCI_U_TYPE_NUMERIC)
{
write2_func ("(%d)", val_size);
fwrite_func (str_val, val_size);
}
else
{
fwrite_func (str_val, val_size - 1);
}
}
break;
case CCI_U_TYPE_BIGINT:
{
INT64 bi_val;
net_arg_get_bigint (&bi_val, net_value);
write2_func ("%lld", (long long) bi_val);
}
break;
case CCI_U_TYPE_UBIGINT:
{
UINT64 ubi_val;
net_arg_get_bigint ((INT64 *) (&ubi_val), net_value);
write2_func ("%llu", (unsigned long long) ubi_val);
}
break;
case CCI_U_TYPE_INT:
{
int i_val;
net_arg_get_int (&i_val, net_value);
write2_func ("%d", i_val);
}
break;
case CCI_U_TYPE_UINT:
{
unsigned int ui_val;
net_arg_get_int ((int *) &ui_val, net_value);
write2_func ("%u", ui_val);
}
break;
case CCI_U_TYPE_SHORT:
{
short s_val;
net_arg_get_short (&s_val, net_value);
write2_func ("%d", s_val);
}
break;
case CCI_U_TYPE_USHORT:
{
unsigned short us_val;
net_arg_get_short ((short *) &us_val, net_value);
write2_func ("%u", us_val);
}
break;
case CCI_U_TYPE_MONETARY:
case CCI_U_TYPE_DOUBLE:
{
double d_val;
net_arg_get_double (&d_val, net_value);
write2_func ("%.15e", d_val);
}
break;
case CCI_U_TYPE_FLOAT:
{
float f_val;
net_arg_get_float (&f_val, net_value);
write2_func ("%.6e", f_val);
}
break;
case CCI_U_TYPE_DATE:
case CCI_U_TYPE_TIME:
case CCI_U_TYPE_TIMESTAMP:
case CCI_U_TYPE_DATETIME:
{
short yr, mon, day, hh, mm, ss, ms;
net_arg_get_datetime (&yr, &mon, &day, &hh, &mm, &ss, &ms, net_value);
if (type == CCI_U_TYPE_DATE)
write2_func ("%d-%d-%d", yr, mon, day);
else if (type == CCI_U_TYPE_TIME)
write2_func ("%d:%d:%d", hh, mm, ss);
else if (type == CCI_U_TYPE_TIMESTAMP)
write2_func ("%d-%d-%d %d:%d:%d", yr, mon, day, hh, mm, ss);
else
write2_func ("%d-%d-%d %d:%d:%d.%03d", yr, mon, day, hh, mm, ss, ms);
}
break;
case CCI_U_TYPE_TIMESTAMPTZ:
case CCI_U_TYPE_DATETIMETZ:
{
short yr, mon, day, hh, mm, ss, ms;
char *tz_str_p;
int tz_size;
char tz_str[CCI_TZ_SIZE + 1];
net_arg_get_datetimetz (&yr, &mon, &day, &hh, &mm, &ss, &ms, &tz_str_p, &tz_size, net_value);
tz_size = MIN (CCI_TZ_SIZE, tz_size);
strncpy (tz_str, tz_str_p, tz_size);
tz_str[tz_size] = '\0';
if (type == CCI_U_TYPE_TIMESTAMPTZ)
{
write2_func ("%d-%d-%d %d:%d:%d %s", yr, mon, day, hh, mm, ss, tz_str);
}
else
{
write2_func ("%d-%d-%d %d:%d:%d.%03d %s", yr, mon, day, hh, mm, ss, ms, tz_str);
}
}
break;
case CCI_U_TYPE_SET:
case CCI_U_TYPE_MULTISET:
case CCI_U_TYPE_SEQUENCE:
{
int remain_size = data_size;
int ele_size;
char ele_type;
char *cur_p = (char *) net_value;
char print_comma = 0;
cur_p += 4;
ele_type = *cur_p;
cur_p++;
remain_size--;
if (ele_type <= CCI_U_TYPE_FIRST || ele_type > CCI_U_TYPE_LAST)
break;
write2_func ("(%s) {", type_str_tbl[(int) ele_type]);
while (remain_size > 0)
{
net_arg_get_size (&ele_size, cur_p);
if (ele_size + 4 > remain_size)
break;
if (print_comma)
write2_func (", ");
else
print_comma = 1;
cas_common_bind_value_print (ele_type, cur_p, slow_log, charset);
ele_size += 4;
cur_p += ele_size;
remain_size -= ele_size;
}
write2_func ("}");
}
break;
case CCI_U_TYPE_OBJECT:
{
int pageid;
short slotid, volid;
net_arg_get_cci_object (&pageid, &slotid, &volid, net_value);
write2_func ("%d|%d|%d", pageid, slotid, volid);
}
break;
case CCI_U_TYPE_BLOB:
case CCI_U_TYPE_CLOB:
{
DB_VALUE db_val;
DB_ELO *db_elo;
net_arg_get_lob_value (&db_val, net_value);
db_elo = db_get_elo (&db_val);
if (db_elo)
{
write2_func ("%s|%lld|%s|%s|%d", (type == CCI_U_TYPE_BLOB) ? "BLOB" : "CLOB", db_elo->size, db_elo->locator,
db_elo->meta_data, db_elo->type);
}
else
{
write2_func ("invalid LOB");
}
db_value_clear (&db_val);
}
break;
default:
write2_func ("NULL");
break;
}
}
void
cas_common_bind_value_log (struct timeval *log_time, int start, int argc, void **argv, int param_size, char *param_mode,
unsigned int query_seq_num, bool slow_log, INTL_CODESET charset)
{
int idx;
char type;
int num_bind;
void *net_value;
const char *param_mode_str;
void (*write2_func) (const char *, ...);
if (slow_log)
{
write2_func = cas_slow_log_write2;
}
else
{
write2_func = cas_log_write2_nonl;
}
num_bind = 1;
idx = start;
while (idx < argc)
{
net_arg_get_char (type, argv[idx++]);
net_value = argv[idx++];
param_mode_str = "";
if (param_mode != NULL && param_size >= num_bind)
{
if (param_mode[num_bind - 1] == CCI_PARAM_MODE_IN)
param_mode_str = "(IN) ";
else if (param_mode[num_bind - 1] == CCI_PARAM_MODE_OUT)
param_mode_str = "(OUT) ";
else if (param_mode[num_bind - 1] == CCI_PARAM_MODE_INOUT)
param_mode_str = "(INOUT) ";
}
if (slow_log)
{
cas_slow_log_write (log_time, query_seq_num, false, "bind %d %s: ", num_bind++, param_mode_str);
}
else
{
cas_log_write_nonl (query_seq_num, false, "bind %d %s: ", num_bind++, param_mode_str);
}
if (type > CCI_U_TYPE_FIRST && type <= CCI_U_TYPE_LAST)
{
/* Since the existing test code uses CCI_U_TYPE_NCHAR and CCI_U_TYPE_VARNCHAR, the assert() is commented out. */
//assert (type != CCI_U_TYPE_NCHAR_DEPRECATED && type != CCI_U_TYPE_VARNCHAR_DEPRECATED);
write2_func ("%s ", type_str_tbl[(int) type]);
cas_common_bind_value_print (type, net_value, slow_log, charset);
}
else
{
write2_func ("NULL");
}
write2_func ("\n");
}
}
FN_RETURN
fn_not_supported (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
ERROR_INFO_SET (CAS_ER_NOT_IMPLEMENTED, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_deprecated (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
#if defined(CAS_FOR_DBMS)
ERROR_INFO_SET (CAS_ER_NOT_IMPLEMENTED, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
#else /* CAS_FOR_DBMS */
net_buf_cp_int (net_buf, CAS_ER_NOT_IMPLEMENTED, NULL);
#endif /* CAS_FOR_DBMS */
return FN_KEEP_CONN;
}