/*
 * Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution. 
 *
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met: 
 *
 * - Redistributions of source code must retain the above copyright notice, 
 *   this list of conditions and the following disclaimer. 
 *
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution. 
 *
 * - Neither the name of the <ORGANIZATION> nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software without 
 *   specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE. 
 *
 */


/*
 * cci_query_execute.c -
 */

#ident "$Id$"

/************************************************************************
 * IMPORTED SYSTEM HEADER FILES						*
 ************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>

#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif

/************************************************************************
 * OTHER IMPORTED HEADER FILES						*
 ************************************************************************/

#include "cas_protocol.h"
#include "cci_common.h"
#include "cci_query_execute.h"
#include "cci_network.h"
#include "cci_net_buf.h"
#include "cci_handle_mng.h"
#include "cci_util.h"
#include "cci_t_set.h"

/************************************************************************
 * PRIVATE DEFINITIONS							*
 ************************************************************************/

#define ALLOC_COPY_INT(PTR, VALUE)	\
	do {				\
	  PTR = MALLOC(sizeof(int));	\
	  if (PTR != NULL) {		\
	    *((int*) (PTR)) = VALUE;	\
	  }				\
	} while (0)

#define ALLOC_COPY_FLOAT(PTR, VALUE)	\
	do {				\
	  PTR = MALLOC(sizeof(float));	\
	  if (PTR != NULL) {		\
	    *((float*) (PTR)) = VALUE;	\
	  }				\
	} while (0)

#define ALLOC_COPY_DOUBLE(PTR, VALUE)	\
	do {				\
	  PTR = MALLOC(sizeof(double));	\
	  if (PTR != NULL) {		\
	    *((double*) (PTR)) = VALUE;	\
	  }				\
	} while (0)

#define ALLOC_COPY_DATE(PTR, VALUE)		\
	do {					\
	  PTR = MALLOC(sizeof(T_CCI_DATE));	\
	  if (PTR != NULL) {			\
	    *((T_CCI_DATE*) (PTR)) = VALUE;	\
	  }					\
	} while (0)

#define ALLOC_COPY_OBJECT(PTR, VALUE)		\
	do {					\
	  PTR = MALLOC(sizeof(T_OBJECT));	\
	  if (PTR != NULL) {			\
	    *((T_OBJECT*) (PTR)) = VALUE;	\
	  }					\
	} while (0)

#define ALLOC_COPY_BIT(DEST, SRC, SIZE)		\
	do {					\
	  DEST = MALLOC(SIZE);			\
	  if (DEST != NULL) {			\
	    memcpy(DEST, SRC, SIZE);		\
	  }					\
	} while (0)

#define EXECUTE_ARRAY	0
#define EXECUTE_BATCH	1
#define EXECUTE_EXEC	2

/************************************************************************
 * PRIVATE TYPE DEFINITIONS						*
 ************************************************************************/

typedef enum
{
  FETCH_FETCH,
  FETCH_OID_GET,
  FETCH_COL_GET
} T_FETCH_TYPE;

/************************************************************************
 * PRIVATE FUNCTION PROTOTYPES						*
 ************************************************************************/

static int prepare_info_decode (char *buf, int size,
				T_REQ_HANDLE * req_handle);
static int get_cursor_pos (T_REQ_HANDLE * req_handle, int offset,
			   char origin);
static int fetch_info_decode (char *buf, int size, int num_cols,
			      T_TUPLE_VALUE ** tuple_value,
			      T_FETCH_TYPE fetch_type);
static void stream_to_obj (char *buf, T_OBJECT * obj);

static int get_data_set (T_CCI_U_TYPE u_type, char *col_value_p,
			 T_SET ** value, int data_size);
static int get_file_size (char *filename);
static int get_column_info (char *buf_p, int remain_size,
			    T_CCI_COL_INFO ** ret_col_info,
			    char **next_buf_p, char prepare_flag);
static int oid_get_info_decode (char *buf_p, int remain_size,
				T_REQ_HANDLE * req_handle);
static int schema_info_decode (char *buf_p, int size,
			       T_REQ_HANDLE * req_handle);
static int col_get_info_decode (char *buf_p, int remain_size, int *col_size,
				int *col_type, T_REQ_HANDLE * req_handle);

static int next_result_info_decode (char *buf, int size,
				    T_REQ_HANDLE * req_handle);
static int bind_value_conversion (T_CCI_A_TYPE a_type, T_CCI_U_TYPE u_type,
				  char flag, void *value,
				  T_BIND_VALUE * bind_value);
static void bind_value_to_net_buf (T_NET_BUF * net_buf, char u_type,
				   void *value, int size);
static int execute_array_info_decode (char *buf, int size, char flag,
				      T_CCI_QUERY_RESULT ** qr,
				      int *res_remain_size);
static T_CCI_U_TYPE get_basic_utype (T_CCI_U_TYPE u_type);
static int parameter_info_decode (char *buf, int size, int num_param,
				  T_CCI_PARAM_INFO ** res_param);
static int decode_fetch_result (T_REQ_HANDLE * req_handle,
				char *result_msg_org, char *result_msg_start,
				int result_msg_size);

#ifdef CCI_XA
static void add_arg_xid (T_NET_BUF * net_buf, XID * xid);
static int xa_prepare_info_decode (char *buf, int buf_size, int count,
				   XID * xid, int num_xid_buf);
static void net_str_to_xid (char *buf, XID * xid);
#endif

/************************************************************************
 * INTERFACE VARIABLES							*
 ************************************************************************/

/************************************************************************
 * PUBLIC VARIABLES							*
 ************************************************************************/

/************************************************************************
 * PRIVATE VARIABLES							*
 ************************************************************************/

static unsigned char myip[4] = { 0, 0, 0, 0 };

/************************************************************************
 * IMPLEMENTATION OF INTERFACE FUNCTIONS 				*
 ************************************************************************/

/************************************************************************
 * IMPLEMENTATION OF PUBLIC FUNCTIONS	 				*
 ************************************************************************/

#if 0
int
test_func ()
{
  return 0;
}
#endif

int
qe_con_close (T_CON_HANDLE * con_handle)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_CON_CLOSE;

  hm_req_handle_free_all (con_handle);

  if (con_handle->sock_fd < 0)
    return 0;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  if (net_buf.err_code < 0)
    goto con_close_end;

  if (net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size) < 0)
    goto con_close_end;

  net_recv_msg (con_handle->sock_fd, NULL, NULL, NULL);

con_close_end:

  net_buf_clear (&net_buf);
  CLOSE_SOCKET (con_handle->sock_fd);
  con_handle->sock_fd = -1;

  return 0;
}

int
qe_end_tran (T_CON_HANDLE * con_handle, char type, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_END_TRAN;
  int err_code;
#ifdef END_TRAN2
  char type_str[2];
#endif

  if (con_handle->sock_fd < 0)
    {
      hm_req_handle_free_all (con_handle);
      return 0;
    }

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

#ifdef END_TRAN2
  type_str[0] = type_str[1] = type;
  ADD_ARG_BYTES (&net_buf, type_str, 2);
#else
  ADD_ARG_BYTES (&net_buf, &type, 1);
#endif

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  if (type != CCI_TRAN_ROLLBACK)
    {
      err_code = net_recv_msg (con_handle->sock_fd, NULL, NULL, err_buf);
    }

  if (BROKER_INFO_STATEMENT_POOLING (con_handle->broker_info) !=
      CAS_STATEMENT_POOLING_ON)
    {
      hm_req_handle_free_all (con_handle);
    }

  if (BROKER_INFO_KEEP_CONNECTION (con_handle->broker_info) ==
      CAS_KEEP_CONNECTION_ON)
    {
      con_handle->con_status = CCI_CON_STATUS_OUT_TRAN;
    }
  else
    {
      CLOSE_SOCKET (con_handle->sock_fd);
      con_handle->sock_fd = -1;
    }

  return err_code;
}

int
qe_prepare (T_REQ_HANDLE * req_handle, int sock_fd, char *sql_stmt, char flag,
	    T_CCI_ERROR * err_buf, int reuse)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_PREPARE;
  int sql_stmt_size;
  int err_code;
  char *result_msg = NULL;
  int result_msg_size;
  int result_code;

  if (!reuse)
    ALLOC_COPY (req_handle->sql_text, sql_stmt);

  sql_stmt_size = strlen (req_handle->sql_text) + 1;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_STR (&net_buf, req_handle->sql_text, sql_stmt_size);
  ADD_ARG_BYTES (&net_buf, &flag, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  result_code =
    net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (result_code < 0)
    {
      return result_code;
    }

  err_code =
    prepare_info_decode (result_msg + 4, result_msg_size - 4, req_handle);
  if (err_code < 0)
    {
      FREE_MEM (result_msg);
      return err_code;
    }

  FREE_MEM (result_msg);

  req_handle->handle_type = HANDLE_PREPARE;
  req_handle->server_handle_id = result_code;
  req_handle->cur_fetch_tuple_index = -1;
  if (flag == CCI_PREPARE_UPDATABLE)
    flag |= CCI_PREPARE_INCLUDE_OID;
  req_handle->prepare_flag = flag;
  req_handle->cursor_pos = 0;
  req_handle->valid = 1;

  if (!reuse)
    {
      if (req_handle->num_bind > 0)
	{
	  req_handle->bind_value = (T_BIND_VALUE *)
	    MALLOC (sizeof (T_BIND_VALUE) * req_handle->num_bind);

	  if (req_handle->bind_value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;

	  memset (req_handle->bind_value,
		  0, sizeof (T_BIND_VALUE) * req_handle->num_bind);

	  req_handle->bind_mode = (char *) MALLOC (req_handle->num_bind);
	  if (req_handle->bind_mode == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  memset (req_handle->bind_mode, CCI_PARAM_MODE_UNKNOWN,
		  req_handle->num_bind);
	}
    }

  return 0;
}

int
qe_bind_param (T_REQ_HANDLE * req_handle, int index, T_CCI_A_TYPE a_type,
	       void *value, T_CCI_U_TYPE u_type, char flag)
{
  int err_code;

  index--;

  if (index < 0 || index >= req_handle->num_bind)
    return CCI_ER_BIND_INDEX;

  if (req_handle->bind_value[index].flag == BIND_PTR_DYNAMIC)
    {
      FREE_MEM (req_handle->bind_value[index].value);
      memset (&(req_handle->bind_value[index]), 0, sizeof (T_BIND_VALUE));
    }

  req_handle->bind_mode[index] = CCI_PARAM_MODE_IN;

  if (value == NULL || u_type == CCI_U_TYPE_NULL)
    {
      req_handle->bind_value[index].u_type = CCI_U_TYPE_NULL;
      return 0;
    }

  err_code =
    bind_value_conversion (a_type, u_type, flag, value,
			   &(req_handle->bind_value[index]));

  return err_code;
}

int
qe_execute (T_REQ_HANDLE * req_handle, int sock_fd, char flag,
	    int max_col_size, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_EXECUTE;
  int i;
  int err_code = 0;
  int res_count;
  char *result_msg = NULL;
  int result_msg_size;
  T_CCI_QUERY_RESULT *qr = NULL;
  char fetch_flag;
  char auto_commit_mode;
  char forward_only_cursor;
  int remain_msg_size;

  QUERY_RESULT_FREE (req_handle);

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_BYTES (&net_buf, &flag, 1);
  ADD_ARG_INT (&net_buf, max_col_size);
  ADD_ARG_INT (&net_buf, req_handle->max_row);
  if (req_handle->stmt_type == CUBRID_STMT_CALL_SP)
    {
      ADD_ARG_BYTES (&net_buf, req_handle->bind_mode, req_handle->num_bind);
    }
  else
    {
      ADD_ARG_BYTES (&net_buf, NULL, 0);
    }

  if (req_handle->stmt_type == CUBRID_STMT_SELECT)
    {
      fetch_flag = 1;
    }
  else
    {
      fetch_flag = 0;
    }
  ADD_ARG_BYTES (&net_buf, &fetch_flag, 1);

  /* Set AutoCommit Mode is FALSE, Forward_Only_Cursor is FALSE */
  auto_commit_mode = 0;
  forward_only_cursor = 0;

  ADD_ARG_BYTES (&net_buf, &auto_commit_mode, 1);
  ADD_ARG_BYTES (&net_buf, &forward_only_cursor, 1);

  ADD_ARG_CACHE_TIME (&net_buf, 0, 0);

  for (i = 0; i < req_handle->num_bind; i++)
    {
      bind_value_to_net_buf (&net_buf,
			     (char) req_handle->bind_value[i].u_type,
			     req_handle->bind_value[i].value,
			     req_handle->bind_value[i].size);
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      goto execute_error;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  if (err_code < 0)
    goto execute_error;

  net_buf_clear (&net_buf);

  res_count = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (res_count < 0)
    {
      err_code = res_count;
      goto execute_error;
    }

  err_code = execute_array_info_decode (result_msg + 4, result_msg_size - 4,
					EXECUTE_EXEC, &qr, &remain_msg_size);
  if (err_code < 0)
    {
      req_handle->num_query_res = 0;
      req_handle->qr = NULL;
    }
  else
    {
      req_handle->num_query_res = err_code;
      req_handle->qr = qr;
    }

  if (req_handle->stmt_type == CUBRID_STMT_SELECT
      || req_handle->stmt_type == CUBRID_STMT_GET_STATS
      || req_handle->stmt_type == CUBRID_STMT_CALL
      || req_handle->stmt_type == CUBRID_STMT_EVALUATE)
    {
      if (flag & CCI_EXEC_ASYNC)
	req_handle->num_tuple = -1;
      else
	req_handle->num_tuple = res_count;
    }
  else if (req_handle->stmt_type == CUBRID_STMT_CALL_SP)
    {
      req_handle->num_tuple = res_count;
    }
  else
    {
      req_handle->num_tuple = -1;
    }

  req_handle->execute_flag = flag;

  hm_req_handle_fetch_buf_free (req_handle);
  req_handle->cursor_pos = 0;


  /* If fetch_flag is 1, executing query and fetching data
     is processed together.
     So, fetching results are included in result_msg.
   */
  if (fetch_flag)
    {
      int num_tuple;

      req_handle->cursor_pos = 1;
      num_tuple = decode_fetch_result (req_handle,
				       result_msg,
				       result_msg + (result_msg_size -
						     remain_msg_size) + 4,
				       remain_msg_size - 4);
      req_handle->cursor_pos = 0;
      if (num_tuple < 0)
	{
	  FREE_MEM (result_msg);
	  return num_tuple;
	}
    }
  else
    {
      FREE_MEM (result_msg);
    }


  return res_count;

execute_error:
  net_buf_clear (&net_buf);
  return err_code;
}

void
qe_bind_value_free (int num_bind, T_BIND_VALUE * bind_value)
{
  int i;

  if (bind_value == NULL)
    return;

  for (i = 0; i < num_bind; i++)
    {
      if (bind_value[i].flag == BIND_PTR_DYNAMIC)
	FREE_MEM (bind_value[i].value);
    }
  FREE_MEM (bind_value);
}

int
qe_get_db_parameter (T_CON_HANDLE * con_handle, T_CCI_DB_PARAM param_name,
		     void *ret_val, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GET_DB_PARAMETER;
  char *result_msg = NULL;
  int result_msg_size;
  int err_code;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, param_name);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code =
    net_recv_msg (con_handle->sock_fd, &result_msg, &result_msg_size,
		  err_buf);

  result_msg_size -= 4;

  if (err_code >= 0)
    {
      switch (param_name)
	{
	case CCI_PARAM_ISOLATION_LEVEL:
	case CCI_PARAM_LOCK_TIMEOUT:
	case CCI_PARAM_MAX_STRING_LENGTH:
	  {
	    int val;
	    if (result_msg_size < 4)
	      {
		err_code = CCI_ER_COMMUNICATION;
	      }
	    else
	      {
		NET_STR_TO_INT (val, result_msg + 4);
		if (ret_val)
		  memcpy (ret_val, (char *) &val, 4);
	      }
	  }
	  break;
	default:
	  break;
	}
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_set_db_parameter (T_CON_HANDLE * con_handle, T_CCI_DB_PARAM param_name,
		     void *value, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_SET_DB_PARAMETER;
  int err_code;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, param_name);

  switch (param_name)
    {
    case CCI_PARAM_ISOLATION_LEVEL:
    case CCI_PARAM_LOCK_TIMEOUT:
      {
	int i_val;
	i_val = *((int *) value);
	ADD_ARG_INT (&net_buf, i_val);
      }
      break;
    default:
      net_buf_clear (&net_buf);
      return CCI_ER_PARAM_NAME;
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (con_handle->sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_close_req_handle (T_REQ_HANDLE * req_handle, int sock_fd)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_CLOSE_REQ_HANDLE;
  int err_code;

  /* same to qe_close_con.
     when statement pool is on,
     (cci_end_tran -> cci_close_req_handle) can be appeared.
     If connection was closed in cci_end_tran (keep_connection=off),
     failure(using closed socket) returns while sending a message in this function.
     So, if sockect is closed at this point, messages must not be sent to server.
   */
  if (sock_fd < 0 || !req_handle->valid)
    {
      return 0;
    }

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, NULL);

  return err_code;
}

int
qe_cursor (T_REQ_HANDLE * req_handle, int sock_fd, int offset, char origin,
	   T_CCI_ERROR * err_buf)
{
  char func_code = CAS_FC_CURSOR;
  int err_code;
  char *result_msg = NULL;
  int result_msg_size;
  T_NET_BUF net_buf;
  char *cur_p;
  int tuple_num;
  int cursor_pos;

  if (req_handle->handle_type == HANDLE_PREPARE)
    {
      if (req_handle->stmt_type == CUBRID_STMT_SELECT ||
	  req_handle->stmt_type == CUBRID_STMT_GET_STATS ||
	  req_handle->stmt_type == CUBRID_STMT_CALL ||
	  req_handle->stmt_type == CUBRID_STMT_CALL_SP ||
	  req_handle->stmt_type == CUBRID_STMT_EVALUATE)
	{
	  if (req_handle->num_tuple >= 0)
	    {
	      cursor_pos = get_cursor_pos (req_handle, offset, origin);
	      if (cursor_pos <= 0 || cursor_pos > req_handle->num_tuple)
		{
		  if (cursor_pos <= 0)
		    req_handle->cursor_pos = 0;
		  else if (cursor_pos > req_handle->num_tuple)
		    req_handle->cursor_pos = req_handle->num_tuple + 1;

		  return CCI_ER_NO_MORE_DATA;
		}
	      req_handle->cursor_pos = cursor_pos;
	      return 0;
	    }
	  else
	    {			/* async query */
	      if (origin != CCI_CURSOR_LAST)
		{
		  cursor_pos = get_cursor_pos (req_handle, offset, origin);
		  req_handle->cursor_pos = cursor_pos;
		  if (req_handle->fetched_tuple_begin > 0 &&
		      cursor_pos >= req_handle->fetched_tuple_begin &&
		      cursor_pos <= req_handle->fetched_tuple_end)
		    {
		      return 0;
		    }
		  if (cursor_pos <= 0)
		    {
		      req_handle->cursor_pos = 0;
		      return CCI_ER_NO_MORE_DATA;
		    }
		}
	    }
	}
      else
	{
	  return CCI_ER_NO_MORE_DATA;
	}
    }
  else if (req_handle->handle_type == HANDLE_SCHEMA_INFO ||
	   req_handle->handle_type == HANDLE_COL_GET)
    {
      cursor_pos = get_cursor_pos (req_handle, offset, origin);
      if (cursor_pos <= 0 || cursor_pos > req_handle->num_tuple)
	{
	  if (cursor_pos <= 0)
	    req_handle->cursor_pos = 0;
	  else if (cursor_pos > req_handle->num_tuple)
	    req_handle->cursor_pos = req_handle->num_tuple + 1;

	  return CCI_ER_NO_MORE_DATA;
	}
      req_handle->cursor_pos = cursor_pos;
      return 0;
    }
  else if (req_handle->handle_type == HANDLE_OID_GET)
    return 0;

  if (origin == CCI_CURSOR_FIRST || origin == CCI_CURSOR_LAST)
    {
      cursor_pos = offset;
    }
  else if (origin == CCI_CURSOR_CURRENT)
    {
      cursor_pos = req_handle->cursor_pos;
      origin = CCI_CURSOR_FIRST;
    }
  else
    return CCI_ER_INVALID_CURSOR_POS;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_INT (&net_buf, cursor_pos);
  ADD_ARG_BYTES (&net_buf, &origin, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      goto cursor_error;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  if (err_code < 0)
    goto cursor_error;
  net_buf_clear (&net_buf);

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  cur_p = result_msg + 4;
  result_msg_size -= 4;

  if (result_msg_size < 4)
    {
      FREE_MEM (result_msg);
      return CCI_ER_COMMUNICATION;
    }
  NET_STR_TO_INT (tuple_num, cur_p);
  req_handle->num_tuple = tuple_num;
  FREE_MEM (result_msg);

  if (origin == CCI_CURSOR_FIRST)
    {
      if (req_handle->num_tuple >= 0 &&
	  req_handle->cursor_pos > req_handle->num_tuple)
	{
	  req_handle->cursor_pos = req_handle->num_tuple + 1;
	  return CCI_ER_NO_MORE_DATA;
	}
      req_handle->cursor_pos = cursor_pos;
    }
  else
    {
      if (req_handle->num_tuple <= 0 ||
	  req_handle->num_tuple - cursor_pos + 1 <= 0)
	{
	  req_handle->cursor_pos = 0;
	  return CCI_ER_NO_MORE_DATA;
	}
      req_handle->cursor_pos = req_handle->num_tuple - cursor_pos + 1;
    }

  return 0;

cursor_error:
  net_buf_clear (&net_buf);
  return err_code;
}

int
qe_fetch (T_REQ_HANDLE * req_handle, int sock_fd, char flag,
	  int result_set_index, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  int err_code;
  char func_code = CAS_FC_FETCH;
  char *result_msg = NULL;
  int result_msg_size;
  int num_tuple;

  if (req_handle->cursor_pos <= 0)
    return CCI_ER_NO_MORE_DATA;

  if (req_handle->fetched_tuple_begin > 0 &&
      req_handle->cursor_pos >= req_handle->fetched_tuple_begin &&
      req_handle->cursor_pos <= req_handle->fetched_tuple_end)
    {
      req_handle->cur_fetch_tuple_index = req_handle->cursor_pos -
	req_handle->fetched_tuple_begin;
      if (flag)
	{
	  if (ut_is_deleted_oid
	      (&
	       (req_handle->tuple_value[req_handle->cur_fetch_tuple_index].
		tuple_oid)))
	    {
	      return CCI_ER_DELETED_TUPLE;
	    }
	}
      return 0;
    }

  hm_req_handle_fetch_buf_free (req_handle);

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_INT (&net_buf, req_handle->cursor_pos);
  ADD_ARG_INT (&net_buf, req_handle->fetch_size);
  ADD_ARG_BYTES (&net_buf, &flag, 1);
  ADD_ARG_INT (&net_buf, result_set_index);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  num_tuple = decode_fetch_result (req_handle,
				   result_msg,
				   result_msg + 4, result_msg_size - 4);
  if (num_tuple < 0)
    {
      FREE_MEM (result_msg);
      return num_tuple;
    }

  if (num_tuple != 0)
    {
      if (flag)
	{
	  if (ut_is_deleted_oid (&(req_handle->tuple_value[0].tuple_oid)))
	    {
	      return CCI_ER_DELETED_TUPLE;
	    }
	}
    }

  return 0;
}

int
qe_get_data (T_REQ_HANDLE * req_handle, int col_no, int a_type, void *value,
	     int *indicator)
{
  char *col_value_p;
  T_CCI_U_TYPE u_type;
  int data_size;
  int err_code;
  int num_cols;

  if (req_handle->stmt_type == CUBRID_STMT_CALL_SP)
    {
      num_cols = req_handle->num_bind + 1;
      col_no++;
    }
  else
    {
      num_cols = req_handle->num_col_info;
    }

  if (col_no <= 0 || col_no > num_cols)
    return CCI_ER_COLUMN_INDEX;

  if (req_handle->cur_fetch_tuple_index < 0)
    return CCI_ER_INVALID_CURSOR_POS;

  col_value_p =
    req_handle->tuple_value[req_handle->cur_fetch_tuple_index].
    column_ptr[col_no - 1];

  if (req_handle->stmt_type == CUBRID_STMT_CALL_SP)
    u_type = CCI_U_TYPE_NULL;
  else
    u_type = CCI_GET_RESULT_INFO_TYPE (req_handle->col_info, col_no);


  NET_STR_TO_INT (data_size, col_value_p);
  if (data_size <= 0)
    {
      *indicator = -1;
      return 0;
    }

  if (CCI_IS_SET_TYPE (u_type))
    u_type = CCI_U_TYPE_SET;
  else if (CCI_IS_MULTISET_TYPE (u_type))
    u_type = CCI_U_TYPE_MULTISET;
  else if (CCI_IS_SEQUENCE_TYPE (u_type))
    u_type = CCI_U_TYPE_SEQUENCE;

  col_value_p += 4;
  if (u_type == CCI_U_TYPE_NULL)
    {
      u_type = (T_CCI_U_TYPE) * col_value_p;
      col_value_p++;
      data_size--;
    }

  *indicator = 0;

  switch (a_type)
    {
    case CCI_A_TYPE_STR:
      err_code = qe_get_data_str (&(req_handle->conv_value_buffer), u_type,
				  col_value_p, data_size, value, indicator);
      break;
    case CCI_A_TYPE_INT:
      err_code = qe_get_data_int (u_type, col_value_p, value);
      break;
    case CCI_A_TYPE_FLOAT:
      err_code = qe_get_data_float (u_type, col_value_p, value);
      break;
    case CCI_A_TYPE_DOUBLE:
      err_code = qe_get_data_double (u_type, col_value_p, value);
      break;
    case CCI_A_TYPE_BIT:
      err_code = qe_get_data_bit (u_type, col_value_p, data_size, value);
      break;
    case CCI_A_TYPE_DATE:
      err_code = qe_get_data_date (u_type, col_value_p, value);
      break;
    case CCI_A_TYPE_SET:
      err_code =
	get_data_set (u_type, col_value_p, (T_SET **) value, data_size);
      break;
    default:
      return CCI_ER_ATYPE;
    }

  return err_code;
}

int
qe_get_cur_oid (T_REQ_HANDLE * req_handle, char *oid_str_buf)
{
  if (req_handle->cur_fetch_tuple_index < 0)
    return CCI_ER_INVALID_CURSOR_POS;

  if (req_handle->prepare_flag & CCI_PREPARE_INCLUDE_OID)
    {
      ut_oid_to_str (&
		     (req_handle->
		      tuple_value[req_handle->cur_fetch_tuple_index].
		      tuple_oid), oid_str_buf);
    }
  else
    strcpy (oid_str_buf, "");
  return 0;
}

int
qe_glo_new (T_CON_HANDLE * con_handle, char *class_name, char *filename,
	    char *oid_str, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GLO_NEW;
  int err_code = 0;
  char flag;
  int file_size = 0;
  char *result_msg = NULL;
  int result_msg_size;
  int sock_fd = con_handle->sock_fd;
  T_OBJECT glo_oid;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_STR (&net_buf, class_name, strlen (class_name) + 1);
  if (memcmp (myip, con_handle->ip_addr, 4) == 0 || filename == NULL)
    {
      flag = 0;
      ADD_ARG_BYTES (&net_buf, &flag, 1);
      ADD_ARG_BYTES (&net_buf, filename,
		     ((filename) ? strlen (filename) + 1 : 0));
      ADD_ARG_INT (&net_buf, file_size);
    }
  else
    {
      flag = 1;
      ADD_ARG_BYTES (&net_buf, &flag, 1);
      ADD_ARG_BYTES (&net_buf, NULL, 0);
      file_size = get_file_size (filename);
      ADD_ARG_INT (&net_buf, file_size);

      if (file_size < 0)
	{
	  net_buf_clear (&net_buf);
	  return CCI_ER_FILE;
	}
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  if (file_size > 0)
    {
      err_code = net_send_file (sock_fd, filename, file_size);
      if (err_code < 0)
	return err_code;
    }

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  if (result_msg_size < SIZE_OBJECT + 4)
    {
      FREE_MEM (result_msg);
      return CCI_ER_COMMUNICATION;
    }

  NET_STR_TO_OBJECT (glo_oid, result_msg + 4);
  ut_oid_to_str (&glo_oid, oid_str);

  FREE_MEM (result_msg);
  return err_code;
}

int
qe_glo_save (T_CON_HANDLE * con_handle, char *oid_str, char *filename,
	     T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GLO_SAVE;
  int err_code = 0;
  char flag;
  int file_size = 0;
  int sock_fd = con_handle->sock_fd;
  T_OBJECT glo_oid;

  if (ut_str_to_oid (oid_str, &glo_oid) < 0)
    return CCI_ER_OBJECT;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_OBJECT (&net_buf, &glo_oid);
  if (memcmp (myip, con_handle->ip_addr, 4) == 0)
    {
      flag = 0;
      ADD_ARG_BYTES (&net_buf, &flag, 1);
      ADD_ARG_STR (&net_buf, filename, strlen (filename) + 1);
      ADD_ARG_INT (&net_buf, file_size);
    }
  else
    {
      flag = 1;
      ADD_ARG_BYTES (&net_buf, &flag, 1);
      ADD_ARG_BYTES (&net_buf, NULL, 0);
      file_size = get_file_size (filename);
      ADD_ARG_INT (&net_buf, file_size);

      if (file_size < 0)
	{
	  net_buf_clear (&net_buf);
	  return CCI_ER_FILE;
	}
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  if (file_size > 0)
    {
      err_code = net_send_file (sock_fd, filename, file_size);
      if (err_code < 0)
	return err_code;
    }

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);
  if (err_code < 0)
    return err_code;

  return err_code;
}

int
qe_glo_load (T_CON_HANDLE * con_handle, char *oid_str, int out_fd,
	     T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GLO_LOAD;
  int err_code = 0;
  int sock_fd = con_handle->sock_fd;
  T_OBJECT glo_oid;
  char *result_msg = NULL;
  int result_msg_size;
  int file_size;

  if (ut_str_to_oid (oid_str, &glo_oid) < 0)
    return CCI_ER_OBJECT;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_OBJECT (&net_buf, &glo_oid);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  result_msg_size -= 4;
  if (result_msg_size < 4)
    {
      FREE_MEM (result_msg);
      return CCI_ER_COMMUNICATION;
    }

  NET_STR_TO_INT (file_size, result_msg + 4);

  err_code = net_recv_file (sock_fd, file_size, out_fd);

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_schema_info (T_REQ_HANDLE * req_handle, int sock_fd, int type,
		char *class_name, char *attr_name, char flag,
		T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_SCHEMA_INFO;
  int err_code;
  int result_code;
  char *result_msg;
  int result_msg_size;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, type);
  if (class_name == NULL)
    ADD_ARG_BYTES (&net_buf, NULL, 0);
  else
    ADD_ARG_STR (&net_buf, class_name, strlen (class_name) + 1);
  if (attr_name == NULL)
    ADD_ARG_BYTES (&net_buf, NULL, 0);
  else
    ADD_ARG_STR (&net_buf, attr_name, strlen (attr_name) + 1);
  ADD_ARG_BYTES (&net_buf, &flag, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  result_code =
    net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (result_code < 0)
    return result_code;

  err_code =
    schema_info_decode (result_msg + 4, result_msg_size - 4, req_handle);
  FREE_MEM (result_msg);
  if (err_code < 0)
    return err_code;

  req_handle->handle_type = HANDLE_SCHEMA_INFO;
  req_handle->server_handle_id = result_code;
  req_handle->cur_fetch_tuple_index = -1;
  req_handle->cursor_pos = 0;

  return 0;
}

int
qe_oid_get (T_REQ_HANDLE * req_handle, int sock_fd, char *oid_str,
	    char **attr_name, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_OID_GET;
  int err_code;
  char *result_msg = NULL;
  int result_msg_size;
  int result_code;
  int i;
  T_OBJECT oid;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_OBJECT (&net_buf, &oid);
  if (attr_name)
    {
      for (i = 0; attr_name[i] != NULL; i++)
	{
	  ADD_ARG_STR (&net_buf, attr_name[i], strlen (attr_name[i]) + 1);
	}
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  result_code =
    net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (result_code < 0)
    return result_code;

  err_code =
    oid_get_info_decode (result_msg + 4, result_msg_size - 4, req_handle);
  if (err_code < 0)
    {
      FREE_MEM (result_msg);
      return err_code;
    }

  req_handle->handle_type = HANDLE_OID_GET;
  req_handle->msg_buf = result_msg;
  return 0;
}

int
qe_oid_put (int sock_fd, char *oid_str, char **attr_name, char **new_val,
	    T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_OID_PUT;
  int err_code;
  int i;
  T_OBJECT oid;
  char u_type = CCI_U_TYPE_STRING;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_OBJECT (&net_buf, &oid);
  for (i = 0; attr_name[i] != NULL; i++)
    {
      ADD_ARG_STR (&net_buf, attr_name[i], strlen (attr_name[i]) + 1);
      ADD_ARG_BYTES (&net_buf, &u_type, 1);
      if (new_val[i] == NULL)
	ADD_ARG_BYTES (&net_buf, NULL, 0);
      else
	ADD_ARG_STR (&net_buf, new_val[i], strlen (new_val[i]) + 1);
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_oid_put2 (int sock_fd, char *oid_str, char **attr_name, void **new_val,
	     int *a_type, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_OID_PUT;
  int err_code;
  int i, data_size;
  T_OBJECT oid;
  char u_type;
  void *value;
  T_BIND_VALUE tmp_cell;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    {
      return CCI_ER_OBJECT;
    }

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_OBJECT (&net_buf, &oid);
  for (i = 0; attr_name[i] != NULL; i++)
    {
      tmp_cell.flag = BIND_PTR_STATIC;
      tmp_cell.value = NULL;

      ADD_ARG_STR (&net_buf, attr_name[i], strlen (attr_name[i]) + 1);

      value = NULL;

      if (new_val[i] == NULL)
	{
	  u_type = CCI_U_TYPE_NULL;
	}
      else
	{
	  switch (a_type[i])
	    {
	    case CCI_A_TYPE_STR:
	      data_size = strlen ((char *) (new_val[i])) + 1;
	      u_type = CCI_U_TYPE_STRING;
	      value = new_val[i];
	      break;
	    case CCI_A_TYPE_INT:
	      data_size = 4;
	      u_type = CCI_U_TYPE_INT;
	      value = new_val[i];
	      break;
	    case CCI_A_TYPE_FLOAT:
	      data_size = 4;
	      u_type = CCI_U_TYPE_FLOAT;
	      value = new_val[i];
	      break;
	    case CCI_A_TYPE_DOUBLE:
	      data_size = 8;
	      u_type = CCI_U_TYPE_DOUBLE;
	      value = new_val[i];
	      break;
	    case CCI_A_TYPE_BIT:
	      data_size = ((T_CCI_BIT *) (new_val[i]))->size;
	      u_type = CCI_U_TYPE_BIT;
	      value = ((T_CCI_BIT *) (new_val[i]))->buf;
	      break;
	    case CCI_A_TYPE_DATE:
	      data_size = 12;
	      u_type = CCI_U_TYPE_TIMESTAMP;
	      value = new_val[i];
	      break;
	    case CCI_A_TYPE_SET:
	      err_code = bind_value_conversion (CCI_A_TYPE_SET,
						CCI_U_TYPE_SEQUENCE,
						CCI_BIND_PTR,
						new_val[i], &tmp_cell);
	      if (err_code < 0)
		{
		  net_buf_clear (&net_buf);
		  return err_code;
		}
	      data_size = tmp_cell.size;
	      value = tmp_cell.value;
	      u_type = CCI_U_TYPE_SEQUENCE;
	      break;
	    default:
	      net_buf_clear (&net_buf);
	      return CCI_ER_ATYPE;
	    }
	}

      bind_value_to_net_buf (&net_buf, u_type, value, data_size);

      if (tmp_cell.flag == BIND_PTR_DYNAMIC)
	{
	  FREE_MEM (tmp_cell.value);
	}
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_get_db_version (T_CON_HANDLE * con_handle, char *out_buf, int buf_size)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GET_DB_VERSION;
  char *result_msg = NULL;
  char auto_commit_mode;
  int result_msg_size;
  int err_code;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);

  auto_commit_mode = 0;
  ADD_ARG_BYTES (&net_buf, &auto_commit_mode, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code =
    net_recv_msg (con_handle->sock_fd, &result_msg, &result_msg_size, NULL);
  result_msg_size -= 4;

  if (err_code >= 0)
    {
      if (out_buf)
	{
	  buf_size = MIN (buf_size - 1, result_msg_size);
	  strncpy (out_buf, result_msg + 4, buf_size);
	  out_buf[buf_size] = '\0';
	}
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_get_class_num_objs (T_CON_HANDLE * con_handle, char *class_name, char flag,
		       int *num_objs, int *num_pages, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GET_CLASS_NUM_OBJS;
  char *result_msg = NULL;
  int result_msg_size;
  int err_code = 0;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_STR (&net_buf, class_name, strlen (class_name) + 1);
  ADD_ARG_BYTES (&net_buf, &flag, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code =
    net_recv_msg (con_handle->sock_fd, &result_msg, &result_msg_size,
		  err_buf);
  if (err_code >= 0)
    {
      int tmp_i_value;

      result_msg_size -= 4;
      if (result_msg_size < 4)
	err_code = CCI_ER_COMMUNICATION;
      else
	{
	  NET_STR_TO_INT (tmp_i_value, result_msg + 4);
	  *num_objs = tmp_i_value;
	  result_msg_size -= 4;
	}

      if (result_msg_size < 4)
	err_code = CCI_ER_COMMUNICATION;
      else
	{
	  NET_STR_TO_INT (tmp_i_value, result_msg + 8);
	  *num_pages = tmp_i_value;
	}
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_oid_cmd (int sock_fd, char cmd, char *oid_str, char *out_buf,
	    int out_buf_size, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  T_OBJECT oid;
  int err_code;
  char func_code = CAS_FC_OID_CMD;
  char *result_msg = NULL;
  int result_msg_size;

  if (cmd < CCI_OID_CMD_FIRST || cmd > CCI_OID_CMD_LAST)
    return CCI_ER_OID_CMD;
  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &cmd, 1);
  ADD_ARG_OBJECT (&net_buf, &oid);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  if (cmd == CCI_OID_CLASS_NAME)
    {
      if (out_buf)
	{
	  out_buf_size = MIN (out_buf_size - 1, result_msg_size - 4);
	  strncpy (out_buf, result_msg + 4, out_buf_size);
	  out_buf[out_buf_size] = '\0';
	}
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_col_get (T_REQ_HANDLE * req_handle, int sock_fd, char *oid_str,
	    char *col_attr, int *col_size, int *col_type,
	    T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_COLLECTION;
  char col_cmd = CCI_COL_GET;
  int err_code;
  T_OBJECT oid;
  char *result_msg = NULL;
  int result_msg_size;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;
  if (col_attr == NULL)
    col_attr = "";

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &col_cmd, 1);
  ADD_ARG_OBJECT (&net_buf, &oid);
  ADD_ARG_STR (&net_buf, col_attr, strlen (col_attr) + 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  err_code =
    col_get_info_decode (result_msg + 4, result_msg_size - 4, col_size,
			 col_type, req_handle);
  if (err_code < 0)
    {
      FREE_MEM (result_msg);
      return err_code;
    }

  req_handle->handle_type = HANDLE_COL_GET;
  req_handle->msg_buf = result_msg;
  req_handle->cursor_pos = 0;

  return 0;
}

int
qe_col_size (int sock_fd, char *oid_str, char *col_attr, int *set_size,
	     T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_COLLECTION;
  char col_cmd = CCI_COL_SIZE;
  int err_code;
  T_OBJECT oid;
  char *result_msg = NULL;
  int result_msg_size;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;
  if (col_attr == NULL)
    col_attr = "";

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &col_cmd, 1);
  ADD_ARG_OBJECT (&net_buf, &oid);
  ADD_ARG_STR (&net_buf, col_attr, strlen (col_attr) + 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  if (result_msg_size < 4)
    {
      FREE_MEM (result_msg);
      return CCI_ER_COMMUNICATION;
    }

  NET_STR_TO_INT (*set_size, result_msg + 4);
  FREE_MEM (result_msg);

  return 0;
}

int
qe_col_set_add_drop (int sock_fd, char col_cmd, char *oid_str, char *col_attr,
		     char *value, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_COLLECTION;
  int err_code;
  T_OBJECT oid;
  char u_type = CCI_U_TYPE_STRING;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;

  if (col_attr == NULL)
    col_attr = "";

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &col_cmd, 1);
  ADD_ARG_OBJECT (&net_buf, &oid);
  ADD_ARG_STR (&net_buf, col_attr, strlen (col_attr) + 1);
  ADD_ARG_BYTES (&net_buf, &u_type, 1);
  if (value == NULL)
    ADD_ARG_BYTES (&net_buf, NULL, 0);
  else
    ADD_ARG_STR (&net_buf, value, strlen (value) + 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);
  return err_code;
}

int
qe_col_seq_op (int sock_fd, char col_cmd, char *oid_str, char *col_attr,
	       int index, char *value, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_COLLECTION;
  int err_code;
  T_OBJECT oid;
  char u_type = CCI_U_TYPE_STRING;

  if (ut_str_to_oid (oid_str, &oid) < 0)
    return CCI_ER_OBJECT;

  if (col_attr == NULL)
    col_attr = "";

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &col_cmd, 1);
  ADD_ARG_OBJECT (&net_buf, &oid);
  ADD_ARG_INT (&net_buf, index);
  ADD_ARG_STR (&net_buf, col_attr, strlen (col_attr) + 1);
  if (col_cmd == CCI_COL_SEQ_INSERT || col_cmd == CCI_COL_SEQ_PUT)
    {
      ADD_ARG_BYTES (&net_buf, &u_type, 1);
      if (value == NULL)
	{
	  ADD_ARG_BYTES (&net_buf, NULL, 0);
	}
      else
	{
	  ADD_ARG_STR (&net_buf, value, strlen (value) + 1);
	}
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);
  return err_code;
}

int
qe_next_result (T_REQ_HANDLE * req_handle, char flag, int sock_fd,
		T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_NEXT_RESULT;
  int err_code;
  char *result_msg = NULL;
  int result_msg_size;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_BYTES (&net_buf, &flag, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  err_code =
    next_result_info_decode (result_msg + 4, result_msg_size - 4, req_handle);

  FREE_MEM (result_msg);

  hm_req_handle_fetch_buf_free (req_handle);
  req_handle->cursor_pos = 0;

  return err_code;
}

int
qe_execute_array (T_REQ_HANDLE * req_handle, int sock_fd,
		  T_CCI_QUERY_RESULT ** qr, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_EXECUTE_ARRAY;
  int err_code = 0;
  T_BIND_VALUE cur_cell;
  int row, idx;
  char *result_msg = NULL;
  int result_msg_size;
  int remain_size;
  char auto_commit_mode;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_BYTES (&net_buf, &auto_commit_mode, 1);

  for (row = 0; row < req_handle->bind_array_size; row++)
    {
      for (idx = 0; idx < req_handle->num_bind; idx++)
	{
	  cur_cell.flag = BIND_PTR_STATIC;
	  cur_cell.value = NULL;

	  if (req_handle->bind_value[idx].value == NULL)
	    {
	      cur_cell.u_type = CCI_U_TYPE_NULL;
	    }
	  else if (req_handle->bind_value[idx].null_ind[row])
	    {
	      cur_cell.u_type = CCI_U_TYPE_NULL;
	    }
	  else
	    {
	      char a_type;
	      T_CCI_U_TYPE u_type;

	      a_type = req_handle->bind_value[idx].size;
	      u_type = req_handle->bind_value[idx].u_type;
	      err_code = 0;

	      switch (a_type)
		{
		case CCI_A_TYPE_STR:
		  {
		    char **value;
		    value = (char **) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, value[row],
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_INT:
		  {
		    int *value;
		    value = (int *) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, &(value[row]),
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_FLOAT:
		  {
		    float *value;
		    value = (float *) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, &(value[row]),
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_DOUBLE:
		  {
		    double *value;
		    value = (double *) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, &(value[row]),
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_BIT:
		  {
		    T_CCI_BIT *value;
		    value = (T_CCI_BIT *) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, &(value[row]),
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_DATE:
		  {
		    T_CCI_DATE *value;
		    value = (T_CCI_DATE *) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, &(value[row]),
					     &cur_cell);
		  }
		  break;
		case CCI_A_TYPE_SET:
		  {
		    T_SET **value;
		    value = (T_SET **) req_handle->bind_value[idx].value;
		    err_code =
		      bind_value_conversion ((T_CCI_A_TYPE) a_type, u_type,
					     CCI_BIND_PTR, value[row],
					     &cur_cell);
		  }
		  break;
		default:
		  err_code = CCI_ER_ATYPE;
		}		/* end of switch */
	      if (err_code < 0)
		{
		  net_buf_clear (&net_buf);
		  return err_code;
		}
	    }
	  bind_value_to_net_buf (&net_buf, (char) cur_cell.u_type,
				 cur_cell.value, cur_cell.size);
	  if (cur_cell.flag == BIND_PTR_DYNAMIC)
	    {
	      FREE_MEM (cur_cell.value);
	    }
	}			/* end of for (idx) */
    }				/* end of for (row) */

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  err_code =
    execute_array_info_decode (result_msg + 4, result_msg_size - 4,
			       EXECUTE_ARRAY, qr, &remain_size);

  FREE_MEM (result_msg);

  return err_code;
}

void
qe_query_result_free (int num_q, T_CCI_QUERY_RESULT * qr)
{
  int i;

  if (qr)
    {
      for (i = 0; i < num_q; i++)
	FREE_MEM (qr[i].err_msg);
      FREE_MEM (qr);
    }
}

int
qe_query_result_copy (T_REQ_HANDLE * req_handle, T_CCI_QUERY_RESULT ** res_qr)
{
  T_CCI_QUERY_RESULT *qr = NULL;
  int num_query = req_handle->num_query_res;
  int i;

  *res_qr = NULL;

  if (req_handle->qr == NULL || num_query == 0)
    return 0;

  qr =
    (T_CCI_QUERY_RESULT *) malloc (sizeof (T_CCI_QUERY_RESULT) * num_query);
  if (qr == NULL)
    return CCI_ER_NO_MORE_MEMORY;
  memset (qr, 0, sizeof (T_CCI_QUERY_RESULT) * num_query);

  for (i = 0; i < num_query; i++)
    {
      qr[i].result_count = req_handle->qr[i].result_count;
      qr[i].stmt_type = req_handle->qr[i].stmt_type;
      ALLOC_COPY (qr[i].err_msg, req_handle->qr[i].err_msg);
      strcpy (qr[i].oid, req_handle->qr[i].oid);
    }

  *res_qr = qr;

  return num_query;
}

int
qe_cursor_update (T_REQ_HANDLE * req_handle, int sock_fd, int cursor_pos,
		  int index, T_CCI_A_TYPE a_type, void *value,
		  T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_CURSOR_UPDATE;
  int err_code;
  T_BIND_VALUE bind_value;
  char u_type;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_INT (&net_buf, cursor_pos);
  ADD_ARG_INT (&net_buf, index);

  if (value == NULL)
    {
      bind_value.flag = BIND_PTR_STATIC;
      bind_value.value = NULL;
      bind_value.size = 0;
      bind_value.u_type = CCI_U_TYPE_NULL;
    }
  else
    {
      u_type = get_basic_utype (req_handle->col_info[index - 1].type);

      if (req_handle->col_info == NULL ||
	  u_type <= CCI_U_TYPE_FIRST || u_type > CCI_U_TYPE_LAST)
	{
	  net_buf_clear (&net_buf);
	  return CCI_ER_TYPE_CONVERSION;
	}

      bind_value.flag = BIND_PTR_STATIC;
      bind_value.value = NULL;

      err_code =
	bind_value_conversion (a_type, (T_CCI_U_TYPE) u_type, CCI_BIND_PTR,
			       value, &bind_value);
      if (err_code < 0)
	{
	  net_buf_clear (&net_buf);
	  return err_code;
	}
    }

  bind_value_to_net_buf (&net_buf, (char) bind_value.u_type, bind_value.value,
			 bind_value.size);
  if (bind_value.flag == BIND_PTR_DYNAMIC)
    {
      FREE_MEM (bind_value.value);
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_execute_batch (int sock_fd, int num_query, char **sql_stmt,
		  T_CCI_QUERY_RESULT ** qr, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_EXECUTE_BATCH;
  int err_code;
  char *result_msg = NULL;
  char auto_commit_mode;
  int result_msg_size;
  int sql_len;
  int i;
  int remain_size;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  /* set AutoCommitMode is FALSE */
  auto_commit_mode = 0;
  ADD_ARG_BYTES (&net_buf, &auto_commit_mode, 1);

  for (i = 0; i < num_query; i++)
    {
      sql_len = strlen (sql_stmt[i]) + 1;
      ADD_ARG_STR (&net_buf, sql_stmt[i], sql_len);
    }

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  err_code =
    execute_array_info_decode (result_msg + 4, result_msg_size - 4,
			       EXECUTE_BATCH, qr, &remain_size);

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_get_data_str (T_VALUE_BUF * conv_val_buf, T_CCI_U_TYPE u_type,
		 char *col_value_p, int col_val_size, void *value,
		 int *indicator)
{
  switch (u_type)
    {
    case CCI_U_TYPE_CHAR:
    case CCI_U_TYPE_STRING:
    case CCI_U_TYPE_NCHAR:
    case CCI_U_TYPE_VARNCHAR:
    case CCI_U_TYPE_NUMERIC:
      {
#ifdef UNICODE_DATA
	char *tmp_p;
	tmp_p = ut_unicode_to_ansi (col_value_p);
	if (tmp_p == NULL)
	  {
	    return CCI_ER_NO_MORE_MEMORY;
	  }
	if (hm_conv_value_buf_alloc (conv_val_buf, strlen (tmp_p) + 1) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	strcpy (conv_val_buf->data, tmp_p);
	FREE_MEM (tmp_p);
	*((char **) value) = conv_val_buf->data;
	*indicator = strlen (conv_val_buf->data);
#else
	*((char **) value) = col_value_p;
	*indicator = col_val_size - 1;
#endif
      }
      return 0;
    case CCI_U_TYPE_BIT:
    case CCI_U_TYPE_VARBIT:
      {
	if (hm_conv_value_buf_alloc (conv_val_buf, col_val_size * 2 + 2) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	ut_bit_to_str (col_value_p, col_val_size,
		       (char *) conv_val_buf->data);
      }
      break;
    case CCI_U_TYPE_INT:
    case CCI_U_TYPE_SHORT:
      {
	int data;

	qe_get_data_int (u_type, col_value_p, &data);

	if (hm_conv_value_buf_alloc (conv_val_buf, 128) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	ut_int_to_str (data, (char *) conv_val_buf->data);
      }
      break;
    case CCI_U_TYPE_MONETARY:
    case CCI_U_TYPE_DOUBLE:
      {
	double data;

	qe_get_data_double (u_type, col_value_p, &data);

	if (hm_conv_value_buf_alloc (conv_val_buf, 128) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	ut_double_to_str (data, (char *) conv_val_buf->data);
      }
      break;
    case CCI_U_TYPE_FLOAT:
      {
	float data;

	qe_get_data_float (u_type, col_value_p, &data);

	if (hm_conv_value_buf_alloc (conv_val_buf, 128) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	ut_float_to_str (data, (char *) conv_val_buf->data);
      }
      break;
    case CCI_U_TYPE_DATE:
    case CCI_U_TYPE_TIME:
    case CCI_U_TYPE_TIMESTAMP:
      {
	T_CCI_DATE data;

	qe_get_data_date (u_type, col_value_p, &data);

	if (hm_conv_value_buf_alloc (conv_val_buf, 128) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	ut_date_to_str (&data, u_type, (char *) conv_val_buf->data);
      }
      break;
    case CCI_U_TYPE_SET:
    case CCI_U_TYPE_MULTISET:
    case CCI_U_TYPE_SEQUENCE:
      {
	int err_code;
	T_SET *set;

	err_code = get_data_set (u_type, col_value_p, &set, col_val_size);
	if (err_code < 0)
	  return err_code;

	err_code = t_set_to_str (set, conv_val_buf);
	t_set_free (set);
	if (err_code < 0)
	  {
	    return err_code;
	  }
      }
      break;
    case CCI_U_TYPE_OBJECT:
      {
	T_OBJECT data;
	if (hm_conv_value_buf_alloc (conv_val_buf, 128) < 0)
	  return CCI_ER_NO_MORE_MEMORY;
	NET_STR_TO_OBJECT (data, col_value_p);
	ut_oid_to_str (&data, (char *) conv_val_buf->data);
      }
      break;
    default:
      return CCI_ER_TYPE_CONVERSION;
    }

  *((char **) value) = (char *) conv_val_buf->data;
  *indicator = strlen ((char *) conv_val_buf->data);

  return 0;
}

int
qe_get_data_int (T_CCI_U_TYPE u_type, char *col_value_p, void *value)
{
  int data;

  switch (u_type)
    {
    case CCI_U_TYPE_CHAR:
    case CCI_U_TYPE_STRING:
    case CCI_U_TYPE_NCHAR:
    case CCI_U_TYPE_VARNCHAR:
    case CCI_U_TYPE_NUMERIC:
      if (ut_str_to_int (col_value_p, &data) < 0)
	return CCI_ER_TYPE_CONVERSION;
      break;
    case CCI_U_TYPE_INT:
      NET_STR_TO_INT (data, col_value_p);
      break;
    case CCI_U_TYPE_SHORT:
      {
	short s_val;
	NET_STR_TO_SHORT (s_val, col_value_p);
	data = (int) s_val;
      }
      break;
    case CCI_U_TYPE_MONETARY:
    case CCI_U_TYPE_DOUBLE:
      {
	double d_val;
	NET_STR_TO_DOUBLE (d_val, col_value_p);
	data = (int) d_val;
      }
      break;
    case CCI_U_TYPE_FLOAT:
      {
	float f_val;
	NET_STR_TO_FLOAT (f_val, col_value_p);
	data = (int) f_val;
      }
      break;
    default:
      return CCI_ER_TYPE_CONVERSION;
    }

  *((int *) value) = data;

  return 0;
}

int
qe_get_data_float (T_CCI_U_TYPE u_type, char *col_value_p, void *value)
{
  float data;

  switch (u_type)
    {
    case CCI_U_TYPE_CHAR:
    case CCI_U_TYPE_STRING:
    case CCI_U_TYPE_NCHAR:
    case CCI_U_TYPE_VARNCHAR:
    case CCI_U_TYPE_NUMERIC:
      if (ut_str_to_float (col_value_p, &data) < 0)
	return CCI_ER_TYPE_CONVERSION;
      break;
    case CCI_U_TYPE_INT:
      {
	int i_val;
	NET_STR_TO_INT (i_val, col_value_p);
	data = (float) i_val;
      }
      break;
    case CCI_U_TYPE_SHORT:
      {
	short s_val;
	NET_STR_TO_SHORT (s_val, col_value_p);
	data = (float) s_val;
      }
      break;
    case CCI_U_TYPE_MONETARY:
    case CCI_U_TYPE_DOUBLE:
      {
	double d_val;
	NET_STR_TO_DOUBLE (d_val, col_value_p);
	data = (float) d_val;
      }
      break;
    case CCI_U_TYPE_FLOAT:
      {
	NET_STR_TO_FLOAT (data, col_value_p);
      }
      break;
    default:
      return CCI_ER_TYPE_CONVERSION;
    }

  *((float *) value) = data;
  return 0;
}

int
qe_get_data_double (T_CCI_U_TYPE u_type, char *col_value_p, void *value)
{
  double data;

  switch (u_type)
    {
    case CCI_U_TYPE_CHAR:
    case CCI_U_TYPE_STRING:
    case CCI_U_TYPE_NCHAR:
    case CCI_U_TYPE_VARNCHAR:
    case CCI_U_TYPE_NUMERIC:
      if (ut_str_to_double (col_value_p, &data) < 0)
	return CCI_ER_TYPE_CONVERSION;
      break;
    case CCI_U_TYPE_INT:
      {
	int i_val;
	NET_STR_TO_INT (i_val, col_value_p);
	data = (double) i_val;
      }
      break;
    case CCI_U_TYPE_SHORT:
      {
	short s_val;
	NET_STR_TO_SHORT (s_val, col_value_p);
	data = (double) s_val;
      }
      break;
    case CCI_U_TYPE_MONETARY:
    case CCI_U_TYPE_DOUBLE:
      {
	NET_STR_TO_DOUBLE (data, col_value_p);
      }
      break;
    case CCI_U_TYPE_FLOAT:
      {
	float f_val;
	NET_STR_TO_FLOAT (f_val, col_value_p);
	data = (double) f_val;
      }
      break;
    default:
      return CCI_ER_TYPE_CONVERSION;
    }

  *((double *) value) = data;
  return 0;
}

int
qe_get_data_date (T_CCI_U_TYPE u_type, char *col_value_p, void *value)
{
  T_CCI_DATE data;

  memset ((char *) &data, 0, sizeof (T_CCI_DATE));

  switch (u_type)
    {
    case CCI_U_TYPE_DATE:
      NET_STR_TO_DATE (data, col_value_p);
      break;
    case CCI_U_TYPE_TIME:
      NET_STR_TO_TIME (data, col_value_p);
      break;
    case CCI_U_TYPE_TIMESTAMP:
      NET_STR_TO_TIMESTAMP (data, col_value_p);
      break;
    default:
      return CCI_ER_TYPE_CONVERSION;
    }

  *((T_CCI_DATE *) value) = data;
  return 0;
}

int
qe_get_data_bit (T_CCI_U_TYPE u_type, char *col_value_p, int col_val_size,
		 void *value)
{
  if (u_type == CCI_U_TYPE_BIT || u_type == CCI_U_TYPE_VARBIT)
    {
      ((T_CCI_BIT *) value)->size = col_val_size;
      ((T_CCI_BIT *) value)->buf = col_value_p;
      return 0;
    }

  return CCI_ER_TYPE_CONVERSION;
}

int
qe_get_attr_type_str (int sock_fd, char *class_name, char *attr_name,
		      char *buf, int buf_size, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  int err_code;
  char func_code = CAS_FC_GET_ATTR_TYPE_STR;
  char *result_msg = NULL;
  int result_msg_size;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_STR (&net_buf, class_name, strlen (class_name) + 1);
  ADD_ARG_STR (&net_buf, attr_name, strlen (attr_name) + 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (err_code < 0)
    return err_code;

  if (buf)
    {
      buf_size = MIN (buf_size - 1, result_msg_size - 4);
      strncpy (buf, result_msg + 4, buf_size);
      buf[buf_size] = '\0';
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_get_query_info (T_REQ_HANDLE * req_handle, int sock_fd, char log_type,
		   char **out_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_GET_QUERY_INFO;
  int err_code;
  char *result_msg = NULL;
  int result_msg_size;

  net_buf_init (&net_buf);
  net_buf_cp_str (&net_buf, &func_code, 1);
  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);
  ADD_ARG_BYTES (&net_buf, &log_type, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, &result_msg, &result_msg_size, NULL);
  if (err_code < 0)
    return err_code;

  if (out_buf)
    {
      char *tmp_buf;
      tmp_buf = (char *) malloc (result_msg_size - 4);
      if (tmp_buf == NULL)
	{
	  FREE_MEM (result_msg);
	  return CCI_ER_NO_MORE_MEMORY;
	}
      memcpy (tmp_buf, result_msg + 4, result_msg_size - 4);
      *out_buf = tmp_buf;
    }

  FREE_MEM (result_msg);

  return err_code;
}

int
qe_savepoint_cmd (int sock_fd, char cmd, char *savepoint_name,
		  T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  int err_code;
  char func_code = CAS_FC_SAVEPOINT;

  if (savepoint_name == NULL)
    savepoint_name = "";

  if (cmd < CCI_SP_CMD_FIRST || cmd > CCI_SP_CMD_LAST)
    return CCI_ER_SAVEPOINT_CMD;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_BYTES (&net_buf, &cmd, 1);
  ADD_ARG_STR (&net_buf, savepoint_name, strlen (savepoint_name) + 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_get_param_info (T_REQ_HANDLE * req_handle, int sock_fd,
		   T_CCI_PARAM_INFO ** res_param, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_PARAMETER_INFO;
  char *result_msg = NULL;
  int result_msg_size;
  int err_code;
  int num_param;

  if (res_param)
    *res_param = NULL;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  ADD_ARG_INT (&net_buf, req_handle->server_handle_id);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code = net_send_msg (sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    {
      return err_code;
    }

  num_param = net_recv_msg (sock_fd, &result_msg, &result_msg_size, err_buf);
  if (num_param < 0)
    {
      return num_param;
    }

  if (res_param)
    {
      err_code = parameter_info_decode (result_msg + 4, result_msg_size - 4,
					num_param, res_param);
      if (err_code < 0)
	{
	  num_param = err_code;
	}
    }

  FREE_MEM (result_msg);

  return num_param;
}

void
qe_param_info_free (T_CCI_PARAM_INFO * param)
{
  FREE_MEM (param);
}

#ifdef CCI_XA
int
qe_xa_prepare (T_CON_HANDLE * con_handle, XID * xid, T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_XA_PREPARE;
  int err_code;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);
  add_arg_xid (&net_buf, xid);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (con_handle->sock_fd, NULL, NULL, err_buf);

  return err_code;
}

int
qe_xa_recover (T_CON_HANDLE * con_handle, XID * xid, int num_xid,
	       T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_XA_RECOVER;
  int res;
  char *result_msg = NULL;
  int result_msg_size = 0;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  if (net_buf.err_code < 0)
    {
      res = net_buf.err_code;
      net_buf_clear (&net_buf);
      return res;
    }

  res = net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (res < 0)
    return res;

  res =
    net_recv_msg (con_handle->sock_fd, &result_msg, &result_msg_size,
		  err_buf);
  if (res < 0)
    return res;

  res =
    xa_prepare_info_decode (result_msg + 4, result_msg_size - 4, res, xid,
			    num_xid);
  FREE_MEM (result_msg);
  return res;
}

int
qe_xa_end_tran (T_CON_HANDLE * con_handle, XID * xid, char type,
		T_CCI_ERROR * err_buf)
{
  T_NET_BUF net_buf;
  char func_code = CAS_FC_XA_END_TRAN;
  int err_code;

  net_buf_init (&net_buf);

  net_buf_cp_str (&net_buf, &func_code, 1);

  add_arg_xid (&net_buf, xid);
  ADD_ARG_BYTES (&net_buf, &type, 1);

  if (net_buf.err_code < 0)
    {
      err_code = net_buf.err_code;
      net_buf_clear (&net_buf);
      return err_code;
    }

  err_code =
    net_send_msg (con_handle->sock_fd, net_buf.data, net_buf.data_size);
  net_buf_clear (&net_buf);
  if (err_code < 0)
    return err_code;

  err_code = net_recv_msg (con_handle->sock_fd, NULL, NULL, err_buf);

  CLOSE_SOCKET (con_handle->sock_fd);
  con_handle->sock_fd = -1;

  return err_code;
}
#endif

/************************************************************************
 * IMPLEMENTATION OF PRIVATE FUNCTIONS	 				*
 ************************************************************************/

static int
prepare_info_decode (char *buf, int size, T_REQ_HANDLE * req_handle)
{
  int num_bind_info;
  int num_col_info;
  int remain_size = size;
  char stmt_type;
  char updatable_flag = 0;
  char *cur_p = buf;
  T_CCI_COL_INFO *col_info = NULL;
  int result_cache_lifetime;

  if (remain_size < 4)
    return CCI_ER_COMMUNICATION;
  NET_STR_TO_INT (result_cache_lifetime, cur_p);
  remain_size -= 4;
  cur_p += 4;

  if (remain_size < 1)
    return CCI_ER_COMMUNICATION;
  stmt_type = *cur_p;
  remain_size -= 1;
  cur_p += 1;

  if (remain_size < 4)
    {
      return CCI_ER_COMMUNICATION;
    }
  NET_STR_TO_INT (num_bind_info, cur_p);
  remain_size -= 4;
  cur_p += 4;

  if (remain_size < 1)
    return CCI_ER_COMMUNICATION;
  updatable_flag = *cur_p;
  remain_size -= 1;
  cur_p += 1;

  num_col_info = get_column_info (cur_p, remain_size, &col_info, NULL, 1);
  if (num_col_info < 0)
    return num_col_info;

  req_handle->num_bind = num_bind_info;
  req_handle->num_col_info = num_col_info;
  req_handle->col_info = col_info;
  req_handle->stmt_type = (T_CCI_CUBRID_STMT) stmt_type;
  req_handle->updatable_flag = updatable_flag;

  return 0;
}

static int
get_cursor_pos (T_REQ_HANDLE * req_handle, int offset, char origin)
{
  if (origin == CCI_CURSOR_FIRST)
    {
      return offset;
    }
  else if (origin == CCI_CURSOR_LAST)
    {
      return (req_handle->num_tuple - offset + 1);
    }
  return (req_handle->cursor_pos + offset);
}

static int
fetch_info_decode (char *buf, int size, int num_cols,
		   T_TUPLE_VALUE ** tuple_value, T_FETCH_TYPE fetch_type)
{
  int remain_size = size;
  char *cur_p = buf;
  int err_code;
  int num_tuple, i, j;
  T_TUPLE_VALUE *tmp_tuple_value = NULL;

  if (fetch_type == FETCH_FETCH || fetch_type == FETCH_COL_GET)
    {
      if (remain_size < 4)
	return CCI_ER_COMMUNICATION;

      NET_STR_TO_INT (num_tuple, cur_p);
      remain_size -= 4;
      cur_p += 4;
    }
  else
    {
      num_tuple = 1;
    }

  if (num_tuple <= 0)
    return 0;

  tmp_tuple_value =
    (T_TUPLE_VALUE *) MALLOC (sizeof (T_TUPLE_VALUE) * num_tuple);
  if (tmp_tuple_value == NULL)
    return CCI_ER_NO_MORE_MEMORY;
  memset ((char *) tmp_tuple_value, 0, sizeof (T_TUPLE_VALUE) * num_tuple);

  for (i = 0; i < num_tuple; i++)
    {
      if (fetch_type == FETCH_FETCH)
	{
	  if (remain_size < 4)
	    {
	      err_code = CCI_ER_COMMUNICATION;
	      goto fetch_info_decode_error;
	    }
	  NET_STR_TO_INT (tmp_tuple_value[i].tuple_index, cur_p);
	  cur_p += 4;
	  remain_size -= 4;

	  if (remain_size < SIZE_OBJECT)
	    {
	      err_code = CCI_ER_COMMUNICATION;
	      goto fetch_info_decode_error;
	    }
	  stream_to_obj (cur_p, &(tmp_tuple_value[i].tuple_oid));
	  cur_p += SIZE_OBJECT;
	  remain_size -= SIZE_OBJECT;
	}

      tmp_tuple_value[i].column_ptr =
	(char **) MALLOC (sizeof (char *) * num_cols);
      if (tmp_tuple_value[i].column_ptr == NULL)
	{
	  err_code = CCI_ER_NO_MORE_MEMORY;
	  goto fetch_info_decode_error;
	}
      for (j = 0; j < num_cols; j++)
	{
	  int data_size;
	  char *col_p;

	  col_p = cur_p;
	  if (remain_size < 4)
	    {
	      err_code = CCI_ER_COMMUNICATION;
	      goto fetch_info_decode_error;
	    }
	  NET_STR_TO_INT (data_size, cur_p);
	  remain_size -= 4;
	  cur_p += 4;

	  if (remain_size < data_size)
	    {
	      err_code = CCI_ER_COMMUNICATION;
	      goto fetch_info_decode_error;
	    }
	  tmp_tuple_value[i].column_ptr[j] = col_p;

	  if (data_size > 0)
	    {
	      cur_p += data_size;
	      remain_size -= data_size;
	    }
	}			/* end of for j */
    }				/* end of for i */

  *tuple_value = tmp_tuple_value;

  return num_tuple;

fetch_info_decode_error:
  if (tmp_tuple_value)
    {
      for (i = 0; i < num_tuple; i++)
	FREE_MEM (tmp_tuple_value[i].column_ptr);
      FREE_MEM (tmp_tuple_value);
    }
  return err_code;
}

static void
stream_to_obj (char *buf, T_OBJECT * obj)
{
  int pageid;
  short volid, slotid;

  NET_STR_TO_INT (pageid, buf);
  NET_STR_TO_SHORT (slotid, buf + 4);
  NET_STR_TO_SHORT (volid, buf + 6);

  obj->pageid = pageid;
  obj->slotid = slotid;
  obj->volid = volid;
}

static int
get_data_set (T_CCI_U_TYPE u_type, char *col_value_p, T_SET ** value,
	      int data_size)
{
  T_SET *set;
  int ele_type;
  int num_element;
  int err_code;

  if ((err_code = t_set_alloc (&set)) < 0)
    {
      return err_code;
    }

  if (!(CCI_IS_COLLECTION_TYPE (u_type)))
    {
      return CCI_ER_TYPE_CONVERSION;
    }

  ele_type = *col_value_p;
  col_value_p++;
  data_size--;
  NET_STR_TO_INT (num_element, col_value_p);
  col_value_p += 4;
  data_size -= 4;

  set->type = ele_type;
  set->num_element = num_element;

  set->data_buf = MALLOC (data_size);
  if (set->data_buf == NULL)
    {
      t_set_free (set);
      return CCI_ER_NO_MORE_MEMORY;
    }
  memcpy (set->data_buf, col_value_p, data_size);
  set->data_size = data_size;
  if ((err_code = t_set_decode (set)) < 0)
    {
      t_set_free (set);
      return err_code;
    }

  *value = set;
  return 0;
}

static int
get_file_size (char *filename)
{
  struct stat stat_buf;

  if (stat (filename, &stat_buf) >= 0)
    {
      return (stat_buf.st_size);
    }

  return -1;
}

static int
get_column_info (char *buf_p, int remain_size, T_CCI_COL_INFO ** ret_col_info,
		 char **next_buf_p, char prepare_flag)
{
  char *cur_p = buf_p;
  int num_col_info = 0;
  T_CCI_COL_INFO *col_info = NULL;
  int i;

  if (ret_col_info)
    *ret_col_info = NULL;

  if (remain_size < 4)
    {
      return CCI_ER_COMMUNICATION;
    }
  NET_STR_TO_INT (num_col_info, cur_p);
  remain_size -= 4;
  cur_p += 4;

  col_info =
    (T_CCI_COL_INFO *) MALLOC (sizeof (T_CCI_COL_INFO) * num_col_info);
  if (col_info == NULL)
    {
      return CCI_ER_NO_MORE_MEMORY;
    }
  memset ((char *) col_info, 0, sizeof (T_CCI_COL_INFO) * num_col_info);

  for (i = 0; i < num_col_info; i++)
    {
      int name_size;

      if (remain_size < 1)
	goto get_column_info_error;
      col_info[i].type = (T_CCI_U_TYPE) * cur_p;
      remain_size -= 1;
      cur_p += 1;

      if (remain_size < 2)
	goto get_column_info_error;
      NET_STR_TO_SHORT (col_info[i].scale, cur_p);
      remain_size -= 2;
      cur_p += 2;

      if (remain_size < 4)
	goto get_column_info_error;
      NET_STR_TO_INT (col_info[i].precision, cur_p);
      remain_size -= 4;
      cur_p += 4;

      if (remain_size < 4)
	goto get_column_info_error;
      NET_STR_TO_INT (name_size, cur_p);
      remain_size -= 4;
      cur_p += 4;

      if (remain_size < name_size)
	goto get_column_info_error;
      ALLOC_N_COPY (col_info[i].col_name, cur_p, name_size, char *);
      if (col_info[i].col_name == NULL)
	goto get_column_info_error;
      remain_size -= name_size;
      cur_p += name_size;

      if (prepare_flag)
	{
	  if (remain_size < 4)
	    goto get_column_info_error;
	  NET_STR_TO_INT (name_size, cur_p);
	  remain_size -= 4;
	  cur_p += 4;

	  if (remain_size < name_size)
	    goto get_column_info_error;
	  ALLOC_N_COPY (col_info[i].real_attr, cur_p, name_size, char *);
	  remain_size -= name_size;
	  cur_p += name_size;

	  if (remain_size < 4)
	    goto get_column_info_error;
	  NET_STR_TO_INT (name_size, cur_p);
	  remain_size -= 4;
	  cur_p += 4;

	  if (remain_size < name_size)
	    goto get_column_info_error;
	  ALLOC_N_COPY (col_info[i].class_name, cur_p, name_size, char *);
	  remain_size -= name_size;
	  cur_p += name_size;

	  if (remain_size < 1)
	    goto get_column_info_error;
	  col_info[i].is_non_null = *cur_p;
	  remain_size -= 1;
	  cur_p += 1;
	}
    }

  if (ret_col_info)
    *ret_col_info = col_info;
  if (next_buf_p)
    *next_buf_p = cur_p;

  return num_col_info;

get_column_info_error:
  if (col_info)
    {
      for (i = 0; i < num_col_info; i++)
	{
	  FREE_MEM (col_info[i].col_name);
	  FREE_MEM (col_info[i].class_name);
	}
      FREE_MEM (col_info);
    }
  return CCI_ER_COMMUNICATION;
}

static int
oid_get_info_decode (char *buf_p, int remain_size, T_REQ_HANDLE * req_handle)
{
  int num_col_info;
  int class_name_size;
  int err_code;
  char *class_name;
  char *cur_p = buf_p;
  char *next_buf_p;
  T_CCI_COL_INFO *col_info = NULL;

  if (remain_size < 4)
    return CCI_ER_COMMUNICATION;
  NET_STR_TO_INT (class_name_size, cur_p);
  remain_size -= 4;
  cur_p += 4;

  if (remain_size < class_name_size || class_name_size <= 0)
    return CCI_ER_COMMUNICATION;

  class_name = cur_p;
  remain_size -= class_name_size;
  cur_p += class_name_size;

  num_col_info =
    get_column_info (cur_p, remain_size, &col_info, &next_buf_p, 0);
  if (num_col_info < 0)
    return num_col_info;

  req_handle->col_info = col_info;
  req_handle->num_col_info = num_col_info;

  remain_size -= (next_buf_p - cur_p);
  err_code = fetch_info_decode (next_buf_p, remain_size, num_col_info,
				&(req_handle->tuple_value), FETCH_OID_GET);
  if (err_code < 0)
    {
      return err_code;
    }

  req_handle->fetched_tuple_end = req_handle->fetched_tuple_begin = 1;
  req_handle->cur_fetch_tuple_index = 0;
  req_handle->cursor_pos = 1;
  return 0;
}

static int
schema_info_decode (char *buf_p, int size, T_REQ_HANDLE * req_handle)
{
  T_CCI_COL_INFO *col_info = NULL;
  int remain_size = size;
  char *cur_p = buf_p;
  int num_tuple;
  int num_col_info;

  if (remain_size < 4)
    return CCI_ER_COMMUNICATION;
  NET_STR_TO_INT (num_tuple, cur_p);
  remain_size -= 4;
  cur_p += 4;

  num_col_info = get_column_info (cur_p, remain_size, &col_info, NULL, 0);
  if (num_col_info < 0)
    return num_col_info;

  req_handle->num_col_info = num_col_info;
  req_handle->col_info = col_info;
  req_handle->num_tuple = num_tuple;

  return 0;
}

static int
col_get_info_decode (char *buf_p, int remain_size, int *col_size,
		     int *col_type, T_REQ_HANDLE * req_handle)
{
  int num_col_info;
  char *cur_p = buf_p;
  char *next_buf_p;
  T_CCI_COL_INFO *col_info = NULL;
  int num_tuple;

  if (remain_size < 1)
    return CCI_ER_COMMUNICATION;
  *col_type = *cur_p;
  remain_size -= 1;
  cur_p += 1;

  num_col_info =
    get_column_info (cur_p, remain_size, &col_info, &next_buf_p, 0);
  if (num_col_info < 0)
    return num_col_info;

  req_handle->col_info = col_info;
  req_handle->num_col_info = num_col_info;

  remain_size -= (next_buf_p - cur_p);
  cur_p = next_buf_p;

  num_tuple = fetch_info_decode (cur_p, remain_size, 1,
				 &(req_handle->tuple_value), FETCH_COL_GET);
  if (num_tuple < 0)
    return num_tuple;

  *col_size = num_tuple;
  req_handle->num_tuple = num_tuple;
  if (num_tuple == 0)
    {
      req_handle->fetched_tuple_begin = 0;
      req_handle->fetched_tuple_end = 0;
      req_handle->cur_fetch_tuple_index = -1;
    }
  else
    {
      req_handle->fetched_tuple_begin = 1;
      req_handle->fetched_tuple_end = num_tuple;
      req_handle->cur_fetch_tuple_index = 0;
    }

  return 0;
}

static int
next_result_info_decode (char *buf, int size, T_REQ_HANDLE * req_handle)
{
  int remain_size = size;
  char *cur_p = buf;
  int result_count;
  int num_col_info;
  char stmt_type;
  char updatable_flag;
  T_CCI_COL_INFO *col_info = NULL;

  if (remain_size < 4)
    {
      return CCI_ER_COMMUNICATION;
    }
  NET_STR_TO_INT (result_count, cur_p);
  remain_size -= 4;
  cur_p += 4;

  if (remain_size < 1)
    {
      return CCI_ER_COMMUNICATION;
    }
  stmt_type = *cur_p;
  remain_size -= 1;
  cur_p += 1;

  if (remain_size < 1)
    {
      return CCI_ER_COMMUNICATION;
    }
  updatable_flag = *cur_p;
  remain_size -= 1;
  cur_p += 1;

  num_col_info = get_column_info (cur_p, remain_size, &col_info, NULL, 1);
  if (num_col_info < 0)
    {
      return num_col_info;
    }

  req_handle_col_info_free (req_handle);

  req_handle->num_tuple = result_count;
  if (stmt_type == CUBRID_STMT_SELECT ||
      stmt_type == CUBRID_STMT_GET_STATS ||
      stmt_type == CUBRID_STMT_CALL || stmt_type == CUBRID_STMT_EVALUATE)
    {
      if (req_handle->execute_flag & CCI_EXEC_ASYNC)
	req_handle->num_tuple = -1;
    }

  req_handle->num_col_info = num_col_info;
  req_handle->col_info = col_info;
  req_handle->stmt_type = (T_CCI_CUBRID_STMT) stmt_type;
  req_handle->updatable_flag = updatable_flag;

  return result_count;
}

static int
bind_value_conversion (T_CCI_A_TYPE a_type, T_CCI_U_TYPE u_type, char flag,
		       void *value, T_BIND_VALUE * bind_value)
{
  int err_code;

  if (a_type == CCI_A_TYPE_STR)
    {
      switch (u_type)
	{
	case CCI_U_TYPE_CHAR:
	case CCI_U_TYPE_STRING:
	case CCI_U_TYPE_NCHAR:
	case CCI_U_TYPE_VARNCHAR:
	case CCI_U_TYPE_NUMERIC:
	  if (flag == CCI_BIND_PTR)
	    {
	      bind_value->value = value;
	      bind_value->flag = BIND_PTR_STATIC;
	    }
	  else
	    {
	      ALLOC_COPY (bind_value->value, value);
	      if (bind_value->value == NULL)
		return CCI_ER_NO_MORE_MEMORY;
	      bind_value->flag = BIND_PTR_DYNAMIC;
	    }
	  bind_value->size = strlen ((char *) value) + 1;
	  break;
	case CCI_U_TYPE_INT:
	case CCI_U_TYPE_SHORT:
	  {
	    int i_val;

	    err_code = ut_str_to_int ((char *) value, &i_val);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_INT (bind_value->value, i_val);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (int);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_FLOAT:
	  {
	    float f_val;

	    err_code = ut_str_to_float ((char *) value, &f_val);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_FLOAT (bind_value->value, f_val);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (float);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_MONETARY:
	case CCI_U_TYPE_DOUBLE:
	  {
	    double d_val;
	    err_code = ut_str_to_double ((char *) value, &d_val);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_DOUBLE (bind_value->value, d_val);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (double);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_DATE:
	  {
	    T_CCI_DATE date;
	    err_code = ut_str_to_date ((char *) value, &date);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_DATE (bind_value->value, date);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (T_CCI_DATE);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_TIME:
	  {
	    T_CCI_DATE date;
	    err_code = ut_str_to_time ((char *) value, &date);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_DATE (bind_value->value, date);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (T_CCI_DATE);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_TIMESTAMP:
	  {
	    T_CCI_DATE date;
	    err_code = ut_str_to_timestamp ((char *) value, &date);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_DATE (bind_value->value, date);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (T_CCI_DATE);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_OBJECT:
	  {
	    T_OBJECT obj;
	    err_code = ut_str_to_oid ((char *) value, &obj);
	    if (err_code < 0)
	      return err_code;
	    ALLOC_COPY_OBJECT (bind_value->value, obj);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	case CCI_U_TYPE_SET:
	case CCI_U_TYPE_MULTISET:
	case CCI_U_TYPE_SEQUENCE:
	  /* NOT IMPLEMENTED */
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
    }
  else if (a_type == CCI_A_TYPE_INT)
    {
      int i_value;

      memcpy ((char *) &i_value, value, sizeof (int));

      switch (u_type)
	{
	case CCI_U_TYPE_CHAR:
	case CCI_U_TYPE_STRING:
	case CCI_U_TYPE_NCHAR:
	case CCI_U_TYPE_VARNCHAR:
	case CCI_U_TYPE_NUMERIC:
	  {
	    char buf[64];
	    ut_int_to_str (i_value, buf);
	    ALLOC_COPY (bind_value->value, buf);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = strlen (buf) + 1;
	  }
	  break;
	case CCI_U_TYPE_INT:
	case CCI_U_TYPE_SHORT:
	  ALLOC_COPY_INT (bind_value->value, i_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_MONETARY:
	case CCI_U_TYPE_DOUBLE:
	  ALLOC_COPY_DOUBLE (bind_value->value, (double) i_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_FLOAT:
	  ALLOC_COPY_FLOAT (bind_value->value, (float) i_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
      bind_value->flag = BIND_PTR_DYNAMIC;
    }
  else if (a_type == CCI_A_TYPE_FLOAT)
    {
      float f_value;

      memcpy ((char *) &f_value, value, sizeof (float));

      switch (u_type)
	{
	case CCI_U_TYPE_CHAR:
	case CCI_U_TYPE_STRING:
	case CCI_U_TYPE_NCHAR:
	case CCI_U_TYPE_VARNCHAR:
	case CCI_U_TYPE_NUMERIC:
	  {
	    char buf[256];
	    ut_float_to_str (f_value, buf);
	    ALLOC_COPY (bind_value->value, buf);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = strlen (buf) + 1;
	  }
	  break;
	case CCI_U_TYPE_INT:
	case CCI_U_TYPE_SHORT:
	  ALLOC_COPY_INT (bind_value->value, (int) f_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_MONETARY:
	case CCI_U_TYPE_DOUBLE:
	  ALLOC_COPY_DOUBLE (bind_value->value, (double) f_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_FLOAT:
	  ALLOC_COPY_FLOAT (bind_value->value, f_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
      bind_value->flag = BIND_PTR_DYNAMIC;
    }
  else if (a_type == CCI_A_TYPE_DOUBLE)
    {
      double d_value;
      memcpy ((char *) &d_value, value, sizeof (double));
      switch (u_type)
	{
	case CCI_U_TYPE_CHAR:
	case CCI_U_TYPE_STRING:
	case CCI_U_TYPE_NCHAR:
	case CCI_U_TYPE_VARNCHAR:
	case CCI_U_TYPE_NUMERIC:
	  {
	    char buf[256];
	    ut_double_to_str (d_value, buf);
	    ALLOC_COPY (bind_value->value, buf);
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = strlen (buf) + 1;
	  }
	  break;
	case CCI_U_TYPE_INT:
	case CCI_U_TYPE_SHORT:
	  ALLOC_COPY_INT (bind_value->value, (int) d_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_MONETARY:
	case CCI_U_TYPE_DOUBLE:
	  ALLOC_COPY_DOUBLE (bind_value->value, d_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	case CCI_U_TYPE_FLOAT:
	  ALLOC_COPY_FLOAT (bind_value->value, (float) d_value);
	  if (bind_value->value == NULL)
	    return CCI_ER_NO_MORE_MEMORY;
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
      bind_value->flag = BIND_PTR_DYNAMIC;
    }
  else if (a_type == CCI_A_TYPE_BIT)
    {
      switch (u_type)
	{
	case CCI_U_TYPE_BIT:
	case CCI_U_TYPE_VARBIT:
	  {
	    T_CCI_BIT *bit_value = (T_CCI_BIT *) value;

	    if (flag == CCI_BIND_PTR)
	      {
		bind_value->value = bit_value->buf;
		bind_value->flag = BIND_PTR_STATIC;
	      }
	    else
	      {
		ALLOC_COPY_BIT (bind_value->value, bit_value->buf,
				bit_value->size);
		if (bind_value->value == NULL)
		  return CCI_ER_NO_MORE_MEMORY;
		bind_value->flag = BIND_PTR_DYNAMIC;
	      }
	    bind_value->size = bit_value->size;
	  }
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
    }
  else if (a_type == CCI_A_TYPE_SET)
    {
      switch (u_type)
	{
	case CCI_U_TYPE_SET:
	case CCI_U_TYPE_MULTISET:
	case CCI_U_TYPE_SEQUENCE:
	  {
	    T_SET *set;
	    set = (T_SET *) value;
	    bind_value->value = MALLOC (set->data_size + 1);
	    if (bind_value->value == NULL)
	      {
		return CCI_ER_NO_MORE_MEMORY;
	      }
	    *((char *) (bind_value->value)) = set->type;
	    memcpy ((char *) (bind_value->value) + 1, set->data_buf,
		    set->data_size);
	    bind_value->size = set->data_size + 1;
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
    }
  else if (a_type == CCI_A_TYPE_DATE)
    {
      switch (u_type)
	{
	case CCI_U_TYPE_DATE:
	case CCI_U_TYPE_TIME:
	case CCI_U_TYPE_TIMESTAMP:
	  {
	    ALLOC_COPY_DATE (bind_value->value, *((T_CCI_DATE *) value));
	    if (bind_value->value == NULL)
	      return CCI_ER_NO_MORE_MEMORY;
	    bind_value->size = sizeof (T_CCI_DATE);
	    bind_value->flag = BIND_PTR_DYNAMIC;
	  }
	  break;
	default:
	  return CCI_ER_TYPE_CONVERSION;
	}
    }
  else
    {
      return CCI_ER_ATYPE;
    }

  bind_value->u_type = u_type;
  if (u_type == CCI_U_TYPE_SHORT)
    bind_value->u_type = CCI_U_TYPE_INT;

  if (u_type == CCI_U_TYPE_INT || u_type == CCI_U_TYPE_SHORT)
    bind_value->size = SIZE_INT;
  else if (u_type == CCI_U_TYPE_MONETARY || u_type == CCI_U_TYPE_DOUBLE)
    bind_value->size = SIZE_DOUBLE;
  else if (u_type == CCI_U_TYPE_FLOAT)
    bind_value->size = SIZE_FLOAT;
  else if (u_type == CCI_U_TYPE_DATE)
    bind_value->size = SIZE_DATE;
  else if (u_type == CCI_U_TYPE_TIME)
    bind_value->size = SIZE_TIME;
  else if (u_type == CCI_U_TYPE_TIMESTAMP)
    bind_value->size = SIZE_TIMESTAMP;
  else if (u_type == CCI_U_TYPE_OBJECT)
    bind_value->size = SIZE_OBJECT;

  return 0;
}

static void
bind_value_to_net_buf (T_NET_BUF * net_buf, char u_type, void *value,
		       int size)
{
  if (u_type < CCI_U_TYPE_FIRST || u_type > CCI_U_TYPE_LAST)
    u_type = CCI_U_TYPE_NULL;

  ADD_ARG_BYTES (net_buf, &u_type, 1);

  switch (u_type)
    {
    case CCI_U_TYPE_CHAR:
    case CCI_U_TYPE_STRING:
    case CCI_U_TYPE_NCHAR:
    case CCI_U_TYPE_VARNCHAR:
      ADD_ARG_STR (net_buf, value, size);
      break;
    case CCI_U_TYPE_NUMERIC:
    case CCI_U_TYPE_SET:
    case CCI_U_TYPE_MULTISET:
    case CCI_U_TYPE_SEQUENCE:
      ADD_ARG_BYTES (net_buf, value, size);
      break;
    case CCI_U_TYPE_BIT:
    case CCI_U_TYPE_VARBIT:
      ADD_ARG_BYTES (net_buf, value, size);
      break;
    case CCI_U_TYPE_INT:
    case CCI_U_TYPE_SHORT:
      ADD_ARG_INT (net_buf, *((int *) value));
      break;
    case CCI_U_TYPE_FLOAT:
      ADD_ARG_FLOAT (net_buf, *((float *) value));
      break;
    case CCI_U_TYPE_MONETARY:
    case CCI_U_TYPE_DOUBLE:
      ADD_ARG_DOUBLE (net_buf, *((double *) value));
      break;
    case CCI_U_TYPE_DATE:
    case CCI_U_TYPE_TIME:
    case CCI_U_TYPE_TIMESTAMP:
      ADD_ARG_TIMESTAMP (net_buf, value);
      break;
    case CCI_U_TYPE_OBJECT:
      ADD_ARG_OBJECT (net_buf, value);
      break;
    default:
      ADD_ARG_BYTES (net_buf, NULL, 0);
      break;
    }
}

static int
execute_array_info_decode (char *buf, int size, char flag,
			   T_CCI_QUERY_RESULT ** res_qr, int *res_remain_size)
{
  int remain_size = size;
  char *cur_p = buf;
  int num_query;
  int res_count;
  int i;
  T_OBJECT oid;
  T_CCI_QUERY_RESULT *qr;
  char client_cache_reusable;

  if (flag == EXECUTE_EXEC)
    {
      if (remain_size < 1)
	{
	  return CCI_ER_COMMUNICATION;
	}
      client_cache_reusable = *cur_p;
      remain_size -= 1;
      cur_p += 1;
    }

  if (remain_size < 4)
    {
      return CCI_ER_COMMUNICATION;
    }
  NET_STR_TO_INT (num_query, cur_p);
  remain_size -= 4;
  cur_p += 4;

  qr =
    (T_CCI_QUERY_RESULT *) malloc (sizeof (T_CCI_QUERY_RESULT) * num_query);
  if (qr == NULL)
    return CCI_ER_NO_MORE_MEMORY;
  memset (qr, 0, sizeof (T_CCI_QUERY_RESULT) * num_query);

  for (i = 0; i < num_query; i++)
    {
      if (flag == EXECUTE_BATCH || flag == EXECUTE_EXEC)
	{
	  if (remain_size < 1)
	    {
	      qe_query_result_free (i, qr);
	      return CCI_ER_COMMUNICATION;
	    }
	  qr[i].stmt_type = *cur_p;
	  remain_size -= 1;
	  cur_p += 1;
	}

      if (remain_size < 4)
	{
	  qe_query_result_free (i, qr);
	  return CCI_ER_COMMUNICATION;
	}
      NET_STR_TO_INT (res_count, cur_p);
      remain_size -= 4;
      cur_p += 4;

      qr[i].result_count = res_count;

      if (res_count < 0)
	{
	  int err_msg_size;

	  if (remain_size < 4)
	    {
	      qe_query_result_free (i, qr);
	      return CCI_ER_COMMUNICATION;
	    }
	  NET_STR_TO_INT (err_msg_size, cur_p);
	  remain_size -= 4;
	  cur_p += 4;

	  if (err_msg_size > 0)
	    {
	      if (remain_size < err_msg_size)
		{
		  qe_query_result_free (i, qr);
		  return CCI_ER_COMMUNICATION;
		}
	      ALLOC_N_COPY (qr[i].err_msg, cur_p, err_msg_size, char *);
	      remain_size -= err_msg_size;
	      cur_p += err_msg_size;
	    }
	}
      else
	{
	  if (remain_size < SIZE_OBJECT)
	    {
	      qe_query_result_free (i, qr);
	      return CCI_ER_COMMUNICATION;
	    }
	  NET_STR_TO_OBJECT (oid, cur_p);
	  ut_oid_to_str (&oid, qr[i].oid);
	  cur_p += SIZE_OBJECT;
	  remain_size -= SIZE_OBJECT;

	  if (flag == EXECUTE_EXEC)
	    {
	      int cache_time_sec, cache_time_usec;
	      if (remain_size < 8)
		{
		  return CCI_ER_COMMUNICATION;
		}
	      NET_STR_TO_INT (cache_time_sec, cur_p);
	      NET_STR_TO_INT (cache_time_usec, cur_p + 4);
	      remain_size -= 8;
	      cur_p += 8;
	    }
	}
    }

  *res_qr = qr;
  *res_remain_size = remain_size;

  return num_query;
}

static T_CCI_U_TYPE
get_basic_utype (T_CCI_U_TYPE u_type)
{
  if (CCI_IS_SET_TYPE (u_type))
    return CCI_U_TYPE_SET;
  else if (CCI_IS_MULTISET_TYPE (u_type))
    return CCI_U_TYPE_MULTISET;
  else if (CCI_IS_SEQUENCE_TYPE (u_type))
    return CCI_U_TYPE_SEQUENCE;
  else
    return u_type;
}

static int
parameter_info_decode (char *buf, int size, int num_param,
		       T_CCI_PARAM_INFO ** res_param)
{
  T_CCI_PARAM_INFO *param;
  int i;

  param = (T_CCI_PARAM_INFO *) malloc (sizeof (T_CCI_PARAM_INFO) * num_param);
  if (param == NULL)
    return CCI_ER_NO_MORE_MEMORY;
  memset (param, 0, sizeof (T_CCI_PARAM_INFO) * num_param);

  for (i = 0; i < num_param; i++)
    {
      if (size < 1)
	{
	  goto param_decode_error;
	}
      param[i].mode = (T_CCI_PARAM_MODE) * buf;
      size -= 1;
      buf += 1;

      if (size < 1)
	{
	  goto param_decode_error;
	}
      param[i].type = (T_CCI_U_TYPE) * buf;
      size -= 1;
      buf += 1;

      if (size < 2)
	{
	  goto param_decode_error;
	}
      NET_STR_TO_SHORT (param[i].scale, buf);
      size -= 2;
      buf += 2;

      if (size < 4)
	{
	  goto param_decode_error;
	}
      NET_STR_TO_INT (param[i].precision, buf);
      size -= 4;
      buf += 4;
    }

  *res_param = param;

  return 0;

param_decode_error:
  qe_param_info_free (param);
  return CCI_ER_COMMUNICATION;
}

static int
decode_fetch_result (T_REQ_HANDLE * req_handle, char *result_msg_org,
		     char *result_msg_start, int result_msg_size)
{
  int num_cols;
  int num_tuple;

  if (req_handle->stmt_type == CUBRID_STMT_CALL_SP)
    num_cols = req_handle->num_bind + 1;
  else
    num_cols = req_handle->num_col_info;

  num_tuple = fetch_info_decode (result_msg_start,
				 result_msg_size,
				 num_cols,
				 &(req_handle->tuple_value), FETCH_FETCH);
  if (num_tuple < 0)
    {
      return num_tuple;
    }

  if (num_tuple == 0)
    {
      req_handle->fetched_tuple_begin = 0;
      req_handle->fetched_tuple_end = 0;
      req_handle->msg_buf = result_msg_org;
      req_handle->cur_fetch_tuple_index = -1;
    }
  else
    {
      req_handle->fetched_tuple_begin = req_handle->cursor_pos;
      req_handle->fetched_tuple_end = req_handle->cursor_pos + num_tuple - 1;
      req_handle->msg_buf = result_msg_org;
      req_handle->cur_fetch_tuple_index = 0;
    }

  return num_tuple;
}

#ifdef CCI_XA
static void
add_arg_xid (T_NET_BUF * net_buf, XID * xid)
{
  net_buf_cp_int (net_buf, 12 + xid->gtrid_length + xid->bqual_length);
  net_buf_cp_int (net_buf, xid->formatID);
  net_buf_cp_int (net_buf, xid->gtrid_length);
  net_buf_cp_int (net_buf, xid->bqual_length);
  net_buf_cp_str (net_buf, xid->data, xid->gtrid_length + xid->bqual_length);
}

static int
xa_prepare_info_decode (char *buf, int buf_size, int count, XID * xid,
			int num_xid_buf)
{
  int xid_data_size;
  int i;

  if (count > num_xid_buf)
    count = num_xid_buf;

  for (i = 0; i < count; i++)
    {
      if (buf_size < 4)
	return CCI_ER_COMMUNICATION;
      NET_STR_TO_INT (xid_data_size, buf);
      buf += 4;
      buf_size -= 4;
      if (buf_size < xid_data_size)
	return CCI_ER_COMMUNICATION;
      net_str_to_xid (buf, &(xid[i]));
      buf += xid_data_size;
      buf_size -= xid_data_size;
    }

  return count;
}

static void
net_str_to_xid (char *buf, XID * xid)
{
  memset (xid, 0, sizeof (XID));
  NET_STR_TO_INT (xid->formatID, buf);
  buf += 4;
  NET_STR_TO_INT (xid->gtrid_length, buf);
  buf += 4;
  NET_STR_TO_INT (xid->bqual_length, buf);
  buf += 4;
  memcpy (xid->data, buf, xid->gtrid_length + xid->bqual_length);
}
#endif
