File cas_function.c¶
File List > broker > cas_function.c
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* cas_function.c -
*/
#ident "$Id$"
#include <stdio.h>
#include <stdlib.h>
#if defined(WINDOWS)
#include <winsock2.h>
#include <windows.h>
#include <sys/timeb.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/time.h>
#endif
#include <assert.h>
#include "cas_common_main.h"
#include "cas_common_vars.h"
#include "cas_net_buf.h"
#include "cas_log.h"
#include "cas.h"
#include "cas_handle.h"
#include "cas_util.h"
#include "cas_common_function.h"
#include "perf_monitor.h"
#include "cas_sql_log2.h"
#include "parse_tree.h"
#include "ddl_log.h"
#include "error_manager.h"
#include "cas_function.h"
#include "cas_execute.h"
#include "broker_filename.h"
#include "dbtype.h"
#include "db_session.h"
#include "object_primitive.h"
/* ========================================================================
* Forward Function Declarations
* ======================================================================== */
static FN_RETURN fn_prepare_internal (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info,
int *ret_srv_h_id);
static FN_RETURN fn_execute_internal (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info,
int *prepared_srv_h_id);
void set_query_timeout (T_SRV_HANDLE * srv_handle, int query_timeout);
extern void tran_set_query_timeout (int);
extern bool tran_is_in_libcas (void);
FN_RETURN
fn_end_tran (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int tran_type;
int err_code = 0;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval end_tran_begin, end_tran_end;
int timeout;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_char (tran_type, argv[0]);
if (tran_type != CCI_TRAN_COMMIT && tran_type != CCI_TRAN_ROLLBACK)
{
ERROR_INFO_SET (CAS_ER_TRAN_TYPE, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (0, false, "end_tran %s", get_tran_type_str (tran_type));
gettimeofday (&end_tran_begin, NULL);
#ifdef CCI_XA
if (is_xa_prepared ())
{
/*
* In the 2PC Prepare state, end_tran (commit or rollback) must not be processed.
* In this state, commit and rollback must be processed
* through the commit decision or abort decision from the coordinator.
* In other words, it must be processed with fn_xa_end_tran.
*/
;
}
else
#endif
{
err_code = ux_end_tran ((char) tran_type, false, false);
}
if ((tran_type == CCI_TRAN_ROLLBACK) && (req_info->client_version < CAS_MAKE_VER (8, 2, 0)))
{
/* For backward compatibility */
cas_send_result_flag = FALSE;
}
gettimeofday (&end_tran_end, NULL);
ut_timeval_diff (&end_tran_begin, &end_tran_end, &elapsed_sec, &elapsed_msec);
cas_log_write (0, false, "end_tran %s%d time %d.%03d%s", err_code < 0 ? "error:" : "", err_info.err_number,
elapsed_sec, elapsed_msec, get_error_log_eids (err_info.err_number));
logddl_write_tran_str ("end_tran %s%d %s", err_code < 0 ? "error:" : "", err_info.err_number,
get_tran_type_str (tran_type));
if (err_code < 0)
{
NET_BUF_ERR_SET (net_buf);
req_info->need_rollback = TRUE;
}
else
{
net_buf_cp_int (net_buf, 0, NULL);
req_info->need_rollback = FALSE;
}
timeout =
ut_check_timeout (&tran_start_time, &end_tran_end, shm_appl->long_transaction_time, &elapsed_sec, &elapsed_msec);
if (timeout >= 0)
{
as_info->num_long_transactions %= MAX_DIAG_DATA_VALUE;
as_info->num_long_transactions++;
}
if (err_code < 0 || errors_in_transaction > 0)
{
cas_log_end (SQL_LOG_MODE_ERROR, elapsed_sec, elapsed_msec);
errors_in_transaction = 0;
}
else
{
if (timeout >= 0 || query_timeout >= 0)
{
cas_log_end (SQL_LOG_MODE_TIMEOUT, elapsed_sec, elapsed_msec);
}
else
{
cas_log_end (SQL_LOG_MODE_NONE, elapsed_sec, elapsed_msec);
}
}
gettimeofday (&tran_start_time, NULL);
gettimeofday (&query_start_time, NULL);
tran_timeout = 0;
query_timeout = 0;
assert (as_info->con_status == CON_STATUS_IN_TRAN);
as_info->con_status = CON_STATUS_OUT_TRAN;
as_info->transaction_start_time = (time_t) 0;
if (as_info->cas_log_reset)
{
cas_log_reset (broker_name);
}
if (as_info->cas_slow_log_reset)
{
cas_slow_log_reset (broker_name);
}
if (shm_appl->sql_log2 != as_info->cur_sql_log2)
{
sql_log2_end (false);
as_info->cur_sql_log2 = shm_appl->sql_log2;
sql_log2_init (broker_name, shm_as_index, as_info->cur_sql_log2, true);
}
if (!ux_is_database_connected ())
{
cas_log_debug (ARG_FILE_LINE, "fn_end_tran: !ux_is_database_connected()");
return FN_CLOSE_CONN;
}
else if (restart_is_needed () || as_info->reset_flag == TRUE)
{
cas_log_debug (ARG_FILE_LINE, "fn_end_tran: restart_is_needed() || reset_flag");
db_set_keep_session (true);
return FN_KEEP_SESS;
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_end_session (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
/* ignore all request to close session from drivers */
net_buf_cp_int (net_buf, NO_ERROR, NULL);
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_row_count (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
ux_get_row_count (net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_last_insert_id (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
ux_get_last_insert_id (net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_prepare (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
return (fn_prepare_internal (sock_fd, argc, argv, net_buf, req_info, NULL));
}
static FN_RETURN
fn_prepare_internal (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info,
int *ret_srv_h_id)
{
char *sql_stmt;
char flag;
char auto_commit_mode;
int sql_size;
int srv_h_id;
T_SRV_HANDLE *srv_handle;
int i;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_str (&sql_stmt, &sql_size, argv[0]);
net_arg_get_char (flag, argv[1]);
if (argc > 2)
{
net_arg_get_char (auto_commit_mode, argv[2]);
if (cas_shard_flag == OFF)
{
for (i = 3; i < argc; i++)
{
int deferred_close_handle;
net_arg_get_int (&deferred_close_handle, argv[i]);
cas_log_write (0, true, "close_req_handle srv_h_id %d", deferred_close_handle);
hm_srv_handle_free (deferred_close_handle);
}
}
}
else
{
auto_commit_mode = FALSE;
}
logddl_set_commit_mode (auto_commit_mode);
gettimeofday (&query_start_time, NULL);
query_timeout = 0;
cas_log_write_nonl (query_seq_num_next_value (), false, "prepare %d ", flag);
cas_log_compile_begin_write_query_string (sql_stmt, sql_size - 1, NULL);
SQL_LOG2_COMPILE_BEGIN (as_info->cur_sql_log2, ((const char *) sql_stmt));
/* append query string to as_info->log_msg */
if (sql_stmt)
{
char *s, *t;
size_t l;
for (s = as_info->log_msg, l = 0; *s && l < SHM_LOG_MSG_SIZE - 1; s++, l++)
{
/* empty body */
}
*s++ = ' ';
l++;
for (t = sql_stmt; *t && l < SHM_LOG_MSG_SIZE - 1; s++, t++, l++)
{
*s = *t;
}
*s = '\0';
}
srv_h_id = ux_prepare (sql_stmt, flag, auto_commit_mode, net_buf, req_info, query_seq_num_current_value ());
if (ret_srv_h_id != NULL)
{
/* this ret_srv_h_id used by following fn_execute_internal() function */
*ret_srv_h_id = srv_h_id;
}
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle && srv_handle->session)
{
assert (((DB_SESSION *) srv_handle->session)->parser);
PARSER_CONTEXT *psr = ((DB_SESSION *) srv_handle->session)->parser;
cas_log_compile_end_write_query_string (sql_stmt, sql_size - 1, &psr->hide_pwd_info);
}
else
{
cas_log_compile_end_write_query_string (sql_stmt, sql_size - 1, NULL);
}
cas_log_write (query_seq_num_current_value (), false, "prepare srv_h_id %s%d%s%s", (srv_h_id < 0) ? "error:" : "",
(srv_h_id < 0) ? err_info.err_number : srv_h_id, (srv_handle != NULL
&& srv_handle->use_plan_cache) ? " (PC)" : "",
get_error_log_eids (err_info.err_number));
logddl_set_err_code (err_info.err_number);
if (srv_h_id < 0)
{
update_error_query_count (as_info, &err_info);
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_execute (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
FN_RETURN ret = fn_execute_internal (sock_fd, argc, argv, net_buf, req_info, NULL);
return ret;
}
static FN_RETURN
fn_execute_internal (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info,
int *prepared_srv_h_id)
{
int srv_h_id;
char flag;
int max_col_size;
int bind_value_index;
int max_row = 0;
int ret_code;
int param_mode_size = 0;
char forward_only_cursor = 0;
char auto_commit_mode = 0;
char *param_mode = NULL;
T_SRV_HANDLE *srv_handle;
const char *exec_func_name;
int argc_mod_2;
int (*ux_exec_func) (T_SRV_HANDLE *, char, int, int, int, void **, T_NET_BUF *, T_REQ_INFO *, CACHE_TIME *, int *);
char fetch_flag = 0;
CACHE_TIME clt_cache_time, *clt_cache_time_ptr;
int client_cache_reusable = FALSE;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval exec_begin, exec_end;
int app_query_timeout;
bool client_supports_query_timeout = false;
char *eid_string;
int err_number_execute;
int arg_idx = 0;
char stmt_type = -1;
char *plan = NULL;
bind_value_index = 9;
/*
* query timeout is transferred from a driver only if protocol version 1
* or above.
*/
if (req_info->client_version >= CAS_PROTO_MAKE_VER (PROTOCOL_V1))
{
client_supports_query_timeout = true;
bind_value_index++;
}
argc_mod_2 = bind_value_index % 2;
if ((argc < bind_value_index) || (argc % 2 != argc_mod_2))
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
if (prepared_srv_h_id != NULL)
{
srv_h_id = *prepared_srv_h_id;
}
else
{
net_arg_get_int (&srv_h_id, argv[arg_idx++]);
}
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL || srv_handle->schema_type >= CCI_SCH_FIRST)
{
ERROR_INFO_SET (CAS_ER_SRV_HANDLE, CAS_ERROR_INDICATOR);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "execute_internal srv_h_id %d %s%d",
srv_h_id, "error:", err_info.err_number);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_char (flag, argv[arg_idx++]);
net_arg_get_int (&max_col_size, argv[arg_idx++]);
net_arg_get_int (&max_row, argv[arg_idx++]);
net_arg_get_str (¶m_mode, ¶m_mode_size, argv[arg_idx++]);
if (prepared_srv_h_id != NULL)
{
if (srv_handle->q_result->stmt_type == CUBRID_STMT_SELECT)
{
fetch_flag = 1;
}
else
{
fetch_flag = 0;
}
if (srv_handle->auto_commit_mode != 0)
{
auto_commit_mode = true;
forward_only_cursor = true;
}
else
{
auto_commit_mode = false;
forward_only_cursor = false;
}
}
else
{
/* PROTOCOL_V2 is used only 9.0.0 */
if (DOES_CLIENT_MATCH_THE_PROTOCOL (req_info->client_version, PROTOCOL_V2))
{
if (srv_handle->q_result->stmt_type == CUBRID_STMT_SELECT)
{
fetch_flag = 1;
}
else
{
fetch_flag = 0;
}
arg_idx++; /* skip fetch_flag from driver */
}
else
{
net_arg_get_char (fetch_flag, argv[arg_idx++]);
}
net_arg_get_char (auto_commit_mode, argv[arg_idx++]);
net_arg_get_char (forward_only_cursor, argv[arg_idx++]);
}
clt_cache_time_ptr = &clt_cache_time;
net_arg_get_cache_time (clt_cache_time_ptr, argv[arg_idx++]);
if (client_supports_query_timeout == true)
{
net_arg_get_int (&app_query_timeout, argv[arg_idx++]);
if (!DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V2))
{
/* protocol version v1 driver send query timeout in second */
app_query_timeout *= 1000;
}
}
else
{
app_query_timeout = 0;
}
if (shm_appl->max_string_length >= 0)
{
if (max_col_size <= 0 || max_col_size > shm_appl->max_string_length)
max_col_size = shm_appl->max_string_length;
}
set_query_timeout (srv_handle, app_query_timeout);
srv_handle->auto_commit_mode = auto_commit_mode;
srv_handle->forward_only_cursor = forward_only_cursor;
logddl_set_commit_mode (auto_commit_mode);
if (srv_handle->prepare_flag & CCI_PREPARE_CALL)
{
exec_func_name = "execute_call";
ux_exec_func = ux_execute_call;
if (param_mode)
{
ux_call_info_cp_param_mode (srv_handle, param_mode, param_mode_size);
}
}
else if (flag & CCI_EXEC_QUERY_ALL)
{
exec_func_name = "execute_all";
ux_exec_func = ux_execute_all;
}
else
{
exec_func_name = "execute";
ux_exec_func = ux_execute;
}
if (srv_handle->is_pooled)
{
gettimeofday (&query_start_time, NULL);
query_timeout = 0;
}
cas_log_write_nonl (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "%s srv_h_id %d ", exec_func_name, srv_h_id);
if (srv_handle->sql_stmt != NULL)
{
if (srv_handle->session == NULL)
{
cas_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt), NULL);
}
else
{
assert (((DB_SESSION *) srv_handle->session)->parser);
PARSER_CONTEXT *psr = ((DB_SESSION *) srv_handle->session)->parser;
cas_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt), &psr->hide_pwd_info);
}
}
cas_log_debug (ARG_FILE_LINE, "%s%s", auto_commit_mode ? "auto_commit_mode " : "",
forward_only_cursor ? "forward_only_cursor " : "");
if (as_info->cur_sql_log_mode != SQL_LOG_MODE_NONE)
{
cas_common_bind_value_log (NULL, bind_value_index, argc, argv, param_mode_size, param_mode,
SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, CAS_SCHEMA_DEFAULT_CHARSET);
}
/* append query string to as_info->log_msg */
if (srv_handle->sql_stmt)
{
char *s, *t;
size_t l;
for (s = as_info->log_msg, l = 0; *s && l < SHM_LOG_MSG_SIZE - 1; s++, l++)
{
/* empty body */
}
*s++ = ' ';
l++;
for (t = srv_handle->sql_stmt; *t && l < SHM_LOG_MSG_SIZE - 1; s++, t++, l++)
{
*s = *t;
}
*s = '\0';
}
gettimeofday (&exec_begin, NULL);
ret_code =
(*ux_exec_func) (srv_handle, flag, max_col_size, max_row, argc - bind_value_index, argv + bind_value_index, net_buf,
req_info, clt_cache_time_ptr, &client_cache_reusable);
gettimeofday (&exec_end, NULL);
ut_timeval_diff (&exec_begin, &exec_end, &elapsed_sec, &elapsed_msec);
eid_string = get_error_log_eids (err_info.err_number);
err_number_execute = err_info.err_number;
logddl_set_err_code (err_info.err_number);
if (fetch_flag && ret_code >= 0 && client_cache_reusable == FALSE)
{
ux_fetch (srv_handle, 1, 50, 0, 0, net_buf, req_info);
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "%s %s%d tuple %d time %d.%03d%s%s%s", exec_func_name,
(ret_code < 0) ? "error:" : "", err_number_execute, get_tuple_count (srv_handle), elapsed_sec,
elapsed_msec, (client_cache_reusable == TRUE) ? " (CC)" : "",
(srv_handle->use_query_cache == true) ? " (QC)" : "", eid_string);
plan = db_get_execution_plan ();
query_timeout =
ut_check_timeout (&query_start_time, &exec_end, shm_appl->long_query_time, &elapsed_sec, &elapsed_msec);
if (query_timeout >= 0 || ret_code < 0)
{
if (query_timeout >= 0)
{
as_info->num_long_queries %= MAX_DIAG_DATA_VALUE;
as_info->num_long_queries++;
}
if (ret_code < 0)
{
update_error_query_count (as_info, &err_info);
}
if (as_info->cur_slow_log_mode == SLOW_LOG_MODE_ON)
{
cas_slow_log_write (&query_start_time, SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "%s srv_h_id %d ",
exec_func_name, srv_h_id);
if (srv_handle->sql_stmt != NULL)
{
assert (srv_handle->session);
assert (((DB_SESSION *) srv_handle->session)->parser);
PARSER_CONTEXT *psr = ((DB_SESSION *) srv_handle->session)->parser;
cas_slow_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt),
&psr->hide_pwd_info);
cas_common_bind_value_log (&query_start_time, bind_value_index, argc, argv, param_mode_size, param_mode,
SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), true, CAS_SCHEMA_DEFAULT_CHARSET);
}
cas_slow_log_write (NULL, SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false,
"%s %s%d tuple %d time %d.%03d%s%s%s\n", exec_func_name, (ret_code < 0) ? "error:" : "",
err_number_execute, get_tuple_count (srv_handle), elapsed_sec, elapsed_msec,
(client_cache_reusable == TRUE) ? " (CC)" : "",
(srv_handle->use_query_cache == true) ? " (QC)" : "", eid_string);
if (plan != NULL && plan[0] != '\0')
{
cas_slow_log_write (NULL, 0, false, "slow query plan\n%s", plan);
}
cas_slow_log_end ();
}
}
/* set is_pooled */
if (as_info->cur_statement_pooling)
{
srv_handle->is_pooled = TRUE;
}
if (plan != NULL && plan[0] != '\0')
{
cas_log_write (0, true, "slow query plan\n%s", plan);
/* reset global plan buffer */
db_set_execution_plan (NULL, 0);
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_prepare_and_execute (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int prepare_argc_count;
int srv_h_id;
T_SRV_HANDLE *srv_handle;
net_arg_get_int (&prepare_argc_count, argv[0]);
fn_prepare_internal (sock_fd, prepare_argc_count, argv + 1, net_buf, req_info, &srv_h_id);
if (IS_ERROR_INFO_SET ())
{
goto prepare_and_execute_end;
}
/* execute argv begins at prepare argv + 1 + prepare_argc_count */
fn_execute_internal (sock_fd, 10, argv + 1 + prepare_argc_count, net_buf, req_info, &srv_h_id);
if (IS_ERROR_INFO_SET ())
{
srv_handle = hm_find_srv_handle (srv_h_id);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "close_req_handle srv_h_id %d", srv_h_id);
hm_srv_handle_free (srv_h_id);
}
prepare_and_execute_end:
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_db_parameter (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int param_name;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (¶m_name, argv[0]);
if (param_name == CCI_PARAM_ISOLATION_LEVEL)
{
int isol_level;
ux_get_tran_setting (NULL, &isol_level);
cas_log_write (0, true, "get_db_parameter isolation_level %d", isol_level);
net_buf_cp_int (net_buf, 0, NULL); /* res code */
net_buf_cp_int (net_buf, isol_level, NULL); /* res msg */
}
else if (param_name == CCI_PARAM_LOCK_TIMEOUT)
{
int lock_timeout;
char lock_timeout_string[32];
ux_get_tran_setting (&lock_timeout, NULL);
if (lock_timeout == 0)
{
sprintf (lock_timeout_string, "0 (No wait)");
}
else if (lock_timeout == -1)
{
sprintf (lock_timeout_string, "-1 (Infinite wait)");
}
else
{
sprintf (lock_timeout_string, "%d ms", lock_timeout);
}
cas_log_write (0, true, "get_db_parameter lock_timeout %s", lock_timeout_string);
net_buf_cp_int (net_buf, 0, NULL);
if (!DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V2))
{
if (lock_timeout > 0)
{
/* protocol version v1 driver receive lock timeout in second */
lock_timeout /= 1000;
}
}
net_buf_cp_int (net_buf, lock_timeout, NULL);
}
else if (param_name == CCI_PARAM_MAX_STRING_LENGTH)
{
int max_str_len = shm_appl->max_string_length;
net_buf_cp_int (net_buf, 0, NULL);
if (max_str_len <= 0 || max_str_len > DB_MAX_STRING_LENGTH)
max_str_len = DB_MAX_STRING_LENGTH;
net_buf_cp_int (net_buf, max_str_len, NULL);
}
else if (param_name == CCI_PARAM_NO_BACKSLASH_ESCAPES)
{
int no_backslash_escapes;
no_backslash_escapes =
((cas_default_no_backslash_escapes == true) ? CCI_NO_BACKSLASH_ESCAPES_TRUE : CCI_NO_BACKSLASH_ESCAPES_FALSE);
cas_log_write (0, true, "get_db_parameter no_backslash_escapes %s",
(cas_default_no_backslash_escapes ? "true" : "false"));
net_buf_cp_int (net_buf, 0, NULL);
net_buf_cp_int (net_buf, no_backslash_escapes, NULL);
}
else
{
ERROR_INFO_SET (CAS_ER_PARAM_NAME, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_set_db_parameter (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int param_name;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (¶m_name, argv[0]);
if (param_name == CCI_PARAM_ISOLATION_LEVEL)
{
int isol_level;
net_arg_get_int (&isol_level, argv[1]);
cas_log_write (0, true, "set_db_parameter isolation_level %d", isol_level);
if (ux_set_isolation_level (isol_level, net_buf) < 0)
return FN_KEEP_CONN;
net_buf_cp_int (net_buf, 0, NULL); /* res code */
}
else if (param_name == CCI_PARAM_LOCK_TIMEOUT)
{
int lock_timeout;
char lock_timeout_string[32];
net_arg_get_int (&lock_timeout, argv[1]);
if (lock_timeout == -2)
{
lock_timeout = cas_default_lock_timeout;
}
if (lock_timeout < -1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
ux_set_lock_timeout (lock_timeout);
if (lock_timeout == 0)
{
sprintf (lock_timeout_string, "0 (No wait)");
}
else if (lock_timeout == -1)
{
sprintf (lock_timeout_string, "-1 (Infinite wait)");
}
else
{
sprintf (lock_timeout_string, "%d ms", lock_timeout);
}
cas_log_write (0, true, "set_db_parameter lock_timeout %s", lock_timeout_string);
net_buf_cp_int (net_buf, 0, NULL);
}
else if (param_name == CCI_PARAM_AUTO_COMMIT)
{
int auto_commit;
net_arg_get_int (&auto_commit, argv[1]);
if (auto_commit)
as_info->auto_commit_mode = TRUE;
else
as_info->auto_commit_mode = FALSE;
cas_log_write (0, true, "set_db_parameter auto_commit %d", auto_commit);
net_buf_cp_int (net_buf, 0, NULL);
}
else
{
ERROR_INFO_SET (CAS_ER_PARAM_NAME, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_set_cas_change_mode (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int mode;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&mode, argv[0]);
if (mode != CAS_CHANGE_MODE_AUTO && mode != CAS_CHANGE_MODE_KEEP)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (0, true, "set_cas_change_mode %s", mode == CAS_CHANGE_MODE_AUTO ? "AUTO" : "KEEP");
ux_set_cas_change_mode (mode, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_close_req_handle (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
T_SRV_HANDLE *srv_handle;
char auto_commit_mode = FALSE;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
if (argc > 1)
{
net_arg_get_char (auto_commit_mode, argv[1]);
}
srv_handle = hm_find_srv_handle (srv_h_id);
if (auto_commit_mode == TRUE)
{
req_info->need_auto_commit = TRAN_AUTOCOMMIT;
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "close_req_handle srv_h_id %d", srv_h_id);
hm_srv_handle_free (srv_h_id);
net_buf_cp_int (net_buf, 0, NULL); /* res code */
return FN_KEEP_CONN;
}
FN_RETURN
fn_cursor (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
int offset;
char origin;
if (argc < 3)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
net_arg_get_int (&offset, argv[1]);
net_arg_get_char (origin, argv[2]);
ux_cursor (srv_h_id, offset, origin, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_fetch (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
int cursor_pos;
int fetch_count;
int func_args;
char fetch_flag;
int result_set_index;
T_SRV_HANDLE *srv_handle;
func_args = 5;
if (argc < func_args)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
net_arg_get_int (&cursor_pos, argv[1]);
net_arg_get_int (&fetch_count, argv[2]);
net_arg_get_char (fetch_flag, argv[3]);
net_arg_get_int (&result_set_index, argv[4]);
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL)
{
ERROR_INFO_SET (CAS_ER_SRV_HANDLE, CAS_ERROR_INDICATOR);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "fn_fetch srv_h_id %d %s%d",
srv_h_id, "error:", err_info.err_number);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "fetch srv_h_id %d cursor_pos %d fetch_count %d",
srv_h_id, cursor_pos, fetch_count);
ux_fetch (srv_handle, cursor_pos, fetch_count, fetch_flag, result_set_index, net_buf, req_info);
return FN_KEEP_CONN;
}
FN_RETURN
fn_schema_info (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int schema_type;
char *arg1, *arg2;
char flag;
int arg1_size, arg2_size;
int shard_id;
int srv_h_id;
if (argc < 4)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&schema_type, argv[0]);
net_arg_get_str (&arg1, &arg1_size, argv[1]);
net_arg_get_str (&arg2, &arg2_size, argv[2]);
net_arg_get_char (flag, argv[3]);
if (DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V5))
{
net_arg_get_int (&shard_id, argv[4]);
}
else
{
shard_id = 0;
}
cas_log_write (query_seq_num_next_value (), true, "schema_info %s %s %s %d", get_schema_type_str (schema_type),
(arg1 ? arg1 : "NULL"), (arg2 ? arg2 : "NULL"), flag);
srv_h_id = ux_schema_info (schema_type, arg1, arg2, flag, net_buf, req_info, query_seq_num_current_value ());
cas_log_write (query_seq_num_current_value (), false, "schema_info srv_h_id %d", srv_h_id);
return FN_KEEP_CONN;
}
FN_RETURN
fn_oid_get (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int pageid;
short slotid, volid;
int ret;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_cci_object (&pageid, &slotid, &volid, argv[0]);
ret = ux_oid_get (argc, argv, net_buf);
cas_log_write (0, true, "oid_get @%d|%d|%d %s", pageid, slotid, volid, (ret < 0 ? "ERR" : ""));
return FN_KEEP_CONN;
}
FN_RETURN
fn_oid_put (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
if (argc < 3 || argc % 3 != 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (0, true, "oid_put");
ux_oid_put (argc, argv, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_db_version (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
char auto_commit_mode;
cas_log_write (0, true, "get_version");
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_char (auto_commit_mode, argv[0]);
ux_get_db_version (net_buf, req_info);
if (auto_commit_mode == TRUE)
{
req_info->need_auto_commit = TRAN_AUTOCOMMIT;
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_class_num_objs (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
char *class_name;
char flag;
int class_name_size;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (0, true, "get_class_num_objs");
net_arg_get_str (&class_name, &class_name_size, argv[0]);
net_arg_get_char (flag, argv[1]);
ux_get_class_num_objs (class_name, flag, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_oid (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
DB_OBJECT *obj;
char cmd;
int err_code;
char *res_msg = NULL;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
net_arg_get_char (cmd, argv[0]);
net_arg_get_dbobject (&obj, argv[1]);
if (cmd != CCI_OID_IS_INSTANCE)
{
if ((err_code = ux_check_object (obj, net_buf)) < 0)
{
goto fn_oid_error;
}
}
if (cmd == CCI_OID_DROP)
{
cas_log_write (0, true, "oid drop");
if (obj == NULL)
{
ERROR_INFO_SET (CAS_ER_OBJECT, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
err_code = db_drop (obj);
}
else if (cmd == CCI_OID_IS_INSTANCE)
{
cas_log_write (0, true, "oid is_instance");
if (obj == NULL)
{
err_code = 0;
}
else
{
er_clear ();
if (db_is_instance (obj) > 0)
{
err_code = 1;
}
else
{
err_code = db_error_code ();
if (err_code == -48)
err_code = 0;
}
}
}
else if (cmd == CCI_OID_LOCK_READ)
{
cas_log_write (0, true, "oid lock_read");
if (obj == NULL)
{
ERROR_INFO_SET (CAS_ER_OBJECT, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
err_code = db_lock_read (obj);
}
else if (cmd == CCI_OID_LOCK_WRITE)
{
cas_log_write (0, true, "oid lock_write");
if (obj == NULL)
{
ERROR_INFO_SET (CAS_ER_OBJECT, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
err_code = db_lock_write (obj);
}
else if (cmd == CCI_OID_CLASS_NAME)
{
cas_log_write (0, true, "oid get_class_name");
if (obj == NULL)
{
ERROR_INFO_SET (CAS_ER_OBJECT, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
res_msg = (char *) db_get_class_name (obj);
if (res_msg == NULL)
{
err_code = db_error_code ();
res_msg = (char *) "";
}
else
{
err_code = 0;
}
}
else
{
ERROR_INFO_SET (CAS_ER_INTERNAL, CAS_ERROR_INDICATOR);
goto fn_oid_error;
}
if (err_code < 0)
{
ERROR_INFO_SET (err_code, DBMS_ERROR_INDICATOR);
goto fn_oid_error;
}
else
{
net_buf_cp_int (net_buf, err_code, NULL);
if (cmd == CCI_OID_CLASS_NAME)
{
net_buf_cp_str (net_buf, res_msg, (int) strlen (res_msg) + 1);
}
}
return FN_KEEP_CONN;
fn_oid_error:
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_collection (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
char cmd;
DB_OBJECT *obj;
char *attr_name = (char *) "";
int attr_name_size = 0, seq_index = 0;
int err_code;
DB_VALUE val;
DB_COLLECTION *collection;
DB_ATTRIBUTE *attr;
DB_DOMAIN *domain, *ele_domain;
char col_type, ele_type, db_type;
int value_index;
DB_VALUE *ele_val = NULL;
if (argc < 3)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_char (cmd, argv[0]);
net_arg_get_dbobject (&obj, argv[1]);
if ((err_code = ux_check_object (obj, net_buf)) < 0)
{
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
err_code = 0;
value_index = 0;
switch (cmd)
{
case CCI_COL_GET:
case CCI_COL_SIZE:
net_arg_get_str (&attr_name, &attr_name_size, argv[2]);
break;
case CCI_COL_SET_DROP:
case CCI_COL_SET_ADD:
if (argc < 5)
{
err_code = ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
}
else
{
net_arg_get_str (&attr_name, &attr_name_size, argv[2]);
}
value_index = 3;
break;
case CCI_COL_SEQ_DROP:
if (argc < 4)
{
err_code = ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
}
else
{
net_arg_get_int (&seq_index, argv[2]);
net_arg_get_str (&attr_name, &attr_name_size, argv[3]);
}
break;
case CCI_COL_SEQ_INSERT:
case CCI_COL_SEQ_PUT:
if (argc < 6)
{
err_code = ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
}
else
{
net_arg_get_int (&seq_index, argv[2]);
net_arg_get_str (&attr_name, &attr_name_size, argv[3]);
}
value_index = 4;
break;
default:
err_code = ERROR_INFO_SET (CAS_ER_INTERNAL, CAS_ERROR_INDICATOR);
}
if (err_code < 0)
{
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
if (attr_name_size < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
goto fn_col_finale;
}
attr = db_get_attribute (obj, attr_name);
if (attr == NULL)
{
ERROR_INFO_SET (db_error_code (), DBMS_ERROR_INDICATOR);
goto fn_col_finale;
}
domain = db_attribute_domain (attr);
col_type = ux_db_type_to_cas_type (TP_DOMAIN_TYPE (domain));
if (col_type != CCI_U_TYPE_SET && col_type != CCI_U_TYPE_MULTISET && col_type != CCI_U_TYPE_SEQUENCE)
{
ERROR_INFO_SET (CAS_ER_NOT_COLLECTION, CAS_ERROR_INDICATOR);
goto fn_col_finale;
}
ele_type = get_set_domain (domain, NULL, NULL, &db_type, NULL);
ele_domain = db_domain_set (domain);
if (ele_type <= 0)
{
ERROR_INFO_SET (CAS_ER_COLLECTION_DOMAIN, CAS_ERROR_INDICATOR);
goto fn_col_finale;
}
err_code = db_get (obj, attr_name, &val);
if (err_code < 0)
{
ERROR_INFO_SET (err_code, DBMS_ERROR_INDICATOR);
goto fn_col_finale;
}
if (db_value_type (&val) == DB_TYPE_NULL)
{
collection = NULL;
}
else
{
collection = db_get_collection (&val);
}
if (value_index > 0)
{
err_code = make_bind_value (1, 2, argv + value_index, &ele_val, net_buf, db_type);
if (err_code < 0)
{
if (err_info.err_number == CAS_ER_SRV_HANDLE || err_info.err_number == CAS_ER_NUM_BIND)
{
cas_log_write (0, false, "fn_collection %s%d", "error:", err_info.err_number);
}
goto fn_col_finale;
}
}
err_code = 0;
switch (cmd)
{
case CCI_COL_GET:
ux_col_get (collection, col_type, ele_type, ele_domain, net_buf);
break;
case CCI_COL_SIZE:
ux_col_size (collection, net_buf);
break;
case CCI_COL_SET_DROP:
err_code = ux_col_set_drop (collection, ele_val, net_buf);
break;
case CCI_COL_SET_ADD:
err_code = ux_col_set_add (collection, ele_val, net_buf);
break;
case CCI_COL_SEQ_DROP:
err_code = ux_col_seq_drop (collection, seq_index, net_buf);
break;
case CCI_COL_SEQ_INSERT:
err_code = ux_col_seq_insert (collection, seq_index, ele_val, net_buf);
break;
case CCI_COL_SEQ_PUT:
err_code = ux_col_seq_put (collection, seq_index, ele_val, net_buf);
break;
default:
break;
}
switch (cmd)
{
case CCI_COL_SET_DROP:
case CCI_COL_SET_ADD:
case CCI_COL_SEQ_DROP:
case CCI_COL_SEQ_INSERT:
case CCI_COL_SEQ_PUT:
if (err_code >= 0)
db_put (obj, attr_name, &val);
default:
break;
}
if (ele_val)
{
db_value_clear (ele_val);
FREE_MEM (ele_val);
}
db_col_free (collection);
db_value_clear (&val);
return FN_KEEP_CONN;
fn_col_finale:
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_next_result (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
char flag;
int func_args;
T_SRV_HANDLE *srv_handle;
func_args = 2;
if (argc < func_args)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
net_arg_get_char (flag, argv[1]);
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL)
{
ERROR_INFO_SET (CAS_ER_SRV_HANDLE, CAS_ERROR_INDICATOR);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "fn_next_result srv_h_id %d %s%d",
srv_h_id, "error:", err_info.err_number);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "next_result %d %s", srv_h_id,
(srv_handle->use_query_cache == true) ? "(QC)" : "");
ux_next_result (srv_handle, flag, net_buf, req_info);
return FN_KEEP_CONN;
}
FN_RETURN
fn_execute_batch (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int arg_index = 0;
char auto_commit_mode;
int query_timeout;
net_arg_get_char (auto_commit_mode, argv[arg_index]);
logddl_set_commit_mode (auto_commit_mode);
arg_index++;
if (DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V4))
{
net_arg_get_int (&query_timeout, argv[arg_index]);
arg_index++;
}
else
{
query_timeout = 0;
}
/* does not support query timeout for execute_batch yet */
set_query_timeout (NULL, query_timeout);
cas_log_write (0, true, "execute_batch %d", argc - arg_index);
ux_execute_batch (argc - arg_index, argv + arg_index, net_buf, req_info, auto_commit_mode);
cas_log_write (0, true, "execute_batch end");
return FN_KEEP_CONN;
}
FN_RETURN
fn_execute_array (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
T_SRV_HANDLE *srv_handle;
int ret_code;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval exec_begin, exec_end;
char *eid_string;
char *plan = NULL;
int driver_query_timeout;
int arg_index = 0;
char auto_commit_mode;
int min_argc;
/* argv[0] : service handle argv[1] : auto commit flag */
min_argc = 2;
if (DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V4))
{
/* argv[2] : driver_query_timeout */
min_argc++;
}
if (argc < min_argc)
{
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[arg_index]);
arg_index++;
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL)
{
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
return FN_KEEP_CONN;
}
if (srv_handle->is_pooled)
{
gettimeofday (&query_start_time, NULL);
query_timeout = 0;
}
if (DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V4))
{
net_arg_get_int (&driver_query_timeout, argv[arg_index]);
arg_index++;
}
else
{
driver_query_timeout = 0;
}
/* does not support query timeout for execute_array yet */
set_query_timeout (srv_handle, driver_query_timeout);
net_arg_get_char (auto_commit_mode, argv[arg_index]);
arg_index++;
if (auto_commit_mode == TRUE)
{
req_info->need_auto_commit = TRAN_AUTOCOMMIT;
}
srv_handle->auto_commit_mode = auto_commit_mode;
cas_log_write_nonl (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "execute_array srv_h_id %d %d ", srv_h_id,
(argc - arg_index) / 2);
if (srv_handle->sql_stmt != NULL)
{
if (srv_handle->session == NULL)
{
cas_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt), NULL);
}
else
{
assert (((DB_SESSION *) srv_handle->session)->parser);
PARSER_CONTEXT *psr = ((DB_SESSION *) srv_handle->session)->parser;
cas_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt), &psr->hide_pwd_info);
}
}
if (as_info->cur_sql_log_mode != SQL_LOG_MODE_NONE)
{
cas_common_bind_value_log (NULL, arg_index, argc - 1, argv, 0, NULL, SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false,
CAS_SCHEMA_DEFAULT_CHARSET);
}
gettimeofday (&exec_begin, NULL);
ret_code = ux_execute_array (srv_handle, argc - arg_index, argv + arg_index, net_buf, req_info);
gettimeofday (&exec_end, NULL);
ut_timeval_diff (&exec_begin, &exec_end, &elapsed_sec, &elapsed_msec);
eid_string = get_error_log_eids (err_info.err_number);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "execute_array %s%d tuple %d time %d.%03d%s%s%s",
(ret_code < 0) ? "error:" : "", err_info.err_number, get_tuple_count (srv_handle), elapsed_sec,
elapsed_msec, "", (srv_handle->use_query_cache == true) ? " (QC)" : "", eid_string);
query_timeout =
ut_check_timeout (&query_start_time, &exec_end, shm_appl->long_query_time, &elapsed_sec, &elapsed_msec);
if (query_timeout >= 0 || ret_code < 0)
{
if (query_timeout >= 0)
{
as_info->num_long_queries %= MAX_DIAG_DATA_VALUE;
as_info->num_long_queries++;
}
if (ret_code < 0)
{
update_error_query_count (as_info, &err_info);
}
if (as_info->cur_slow_log_mode == SLOW_LOG_MODE_ON)
{
cas_slow_log_write (&query_start_time, SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false,
"execute_array srv_h_id %d %d ", srv_h_id, (argc - 2) / 2);
if (srv_handle->sql_stmt != NULL)
{
assert (srv_handle->session);
assert (((DB_SESSION *) srv_handle->session)->parser);
PARSER_CONTEXT *psr = ((DB_SESSION *) srv_handle->session)->parser;
cas_slow_log_write_query_string (srv_handle->sql_stmt, (int) strlen (srv_handle->sql_stmt),
&psr->hide_pwd_info);
cas_common_bind_value_log (&query_start_time, 2, argc - 1, argv, 0, NULL,
SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), true, CAS_SCHEMA_DEFAULT_CHARSET);
}
cas_slow_log_write (NULL, SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false,
"execute_array %s%d tuple %d time %d.%03d%s%s%s\n", (ret_code < 0) ? "error:" : "",
err_info.err_number, get_tuple_count (srv_handle), elapsed_sec, elapsed_msec, "",
(srv_handle->use_query_cache == true) ? " (QC)" : "", eid_string);
plan = db_get_execution_plan ();
if (plan != NULL && plan[0] != '\0')
{
cas_slow_log_write (NULL, 0, false, "slow query plan\n%s", plan);
/* reset global plan buffer */
db_set_execution_plan (NULL, 0);
}
cas_slow_log_end ();
}
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_cursor_close (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
T_SRV_HANDLE *srv_handle;
net_arg_get_int (&srv_h_id, argv[0]);
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL || srv_handle->num_q_result < 1)
{
/* has already been closed */
return FN_KEEP_CONN;
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "cursor_close srv_h_id %d", srv_h_id);
ux_cursor_close (srv_handle);
return FN_KEEP_CONN;
}
FN_RETURN
fn_cursor_update (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
int cursor_pos;
T_SRV_HANDLE *srv_handle;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
net_arg_get_int (&cursor_pos, argv[1]);
srv_handle = hm_find_srv_handle (srv_h_id);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "cursor_update srv_h_id %d, cursor %d", srv_h_id,
cursor_pos);
ux_cursor_update (srv_handle, cursor_pos, argc, argv, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_attr_type_str (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int size;
char *class_name;
char *attr_name;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_str (&class_name, &size, argv[0]);
net_arg_get_str (&attr_name, &size, argv[1]);
ux_get_attr_type_str (class_name, attr_name, net_buf, req_info);
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_query_info (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
char info_type;
T_SRV_HANDLE *srv_handle = NULL;
int srv_h_id, size, stmt_id, err;
char *sql_stmt = NULL;
DB_SESSION *session;
DB_QUERY_RESULT *result = NULL;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
net_arg_get_char (info_type, argv[1]);
if (argc >= 3)
{
net_arg_get_str (&sql_stmt, &size, argv[2]);
}
if (sql_stmt != NULL)
{
srv_h_id = hm_new_srv_handle (&srv_handle, query_seq_num_next_value ());
if (srv_h_id < 0)
{
net_buf_cp_byte (net_buf, '\0');
goto end;
}
cas_log_query_info_init (srv_h_id, TRUE);
srv_handle->query_info_flag = TRUE;
db_init_lexer_lineno ();
session = db_open_buffer (sql_stmt);
if (!session)
{
ERROR_INFO_SET (db_error_code (), DBMS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
goto end;
}
if ((stmt_id = db_compile_statement (session)) < 0)
{
ERROR_INFO_SET (stmt_id, DBMS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
db_close_session (session);
goto end;
}
/* Generally, it is not necessary to execute a statement in order to get a plan. But, if a statement has a term,
* which cannot be prepared, such as serial, we should execute it to get its plan. And, currently, we cannot see
* a plan for a statement which includes both "cannot be prepared" term and host variable. This limitation also
* exists in csql. */
err = db_execute_statement (session, stmt_id, &result);
if (err < 0 && err != ER_UCI_TOO_FEW_HOST_VARS)
{
/* We will ignore an error "too few host variables are given" to return a plan for a statement including host
* variables. */
ERROR_INFO_SET (db_error_code (), DBMS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
db_close_session (session);
goto end;
}
if (result != NULL)
{
db_query_end (result);
}
db_close_session (session);
}
ux_get_query_info (srv_h_id, info_type, net_buf);
end:
if (sql_stmt != NULL)
{
reset_optimization_level_as_saved ();
hm_srv_handle_free (srv_h_id);
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_savepoint (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int err_code;
char cmd;
char *savepoint_name;
int savepoint_name_size;
if (argc < 2)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_char (cmd, argv[0]);
net_arg_get_str (&savepoint_name, &savepoint_name_size, argv[1]);
if (savepoint_name == NULL)
savepoint_name = (char *) "";
if (cmd == 1)
{ /* set */
cas_log_write (0, true, "savepoint %s", savepoint_name);
err_code = db_savepoint_transaction (savepoint_name);
}
else if (cmd == 2)
{ /* rollback */
cas_log_write (0, true, "rollback_savepoint %s", savepoint_name);
err_code = db_abort_to_savepoint (savepoint_name);
}
else
{
ERROR_INFO_SET (CAS_ER_INTERNAL, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
if (err_code < 0)
{
ERROR_INFO_SET (err_code, DBMS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
}
else
{
net_buf_cp_int (net_buf, 0, NULL);
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_parameter_info (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
ux_get_parameter_info (srv_h_id, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_con_close (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
cas_log_write (0, true, "con_close");
net_buf_cp_int (net_buf, 0, NULL);
return FN_CLOSE_CONN;
}
FN_RETURN
fn_check_cas (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int err_code = 0;
if (argc == 1)
{
char *msg;
int msg_size;
net_arg_get_str (&msg, &msg_size, argv[0]);
cas_log_write (0, true, "client_msg:%s", msg);
}
else
{
err_code = ux_check_connection ();
cas_log_write (0, true, "check_cas %d", err_code);
}
if (err_code < 0)
{
ERROR_INFO_SET (err_code, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
db_set_keep_session (true);
return FN_KEEP_SESS;
}
else
{
return FN_KEEP_CONN;
}
}
FN_RETURN
fn_make_out_rs (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
if (DOES_CLIENT_UNDERSTAND_THE_PROTOCOL (req_info->client_version, PROTOCOL_V11))
{
DB_BIGINT query_id;
net_arg_get_bigint (&query_id, argv[0]);
ux_make_out_rs (query_id, net_buf, req_info);
}
else
{
fn_not_supported (sock_fd, argc, argv, net_buf, req_info);
}
return FN_KEEP_CONN;
}
FN_RETURN
fn_get_generated_keys (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int srv_h_id;
T_SRV_HANDLE *srv_handle;
if (argc < 1)
{
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
net_arg_get_int (&srv_h_id, argv[0]);
srv_handle = hm_find_srv_handle (srv_h_id);
if (srv_handle == NULL)
{
ERROR_INFO_SET (CAS_ER_SRV_HANDLE, CAS_ERROR_INDICATOR);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "fn_get_generated_keys srv_h_id %d %s%d",
srv_h_id, "error:", err_info.err_number);
NET_BUF_ERR_SET (net_buf);
return FN_KEEP_CONN;
}
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "get_generated_keys %d", srv_h_id);
ux_get_generated_keys (srv_handle, net_buf);
return FN_KEEP_CONN;
}
FN_RETURN
fn_lob_new (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
int lob_type, err_code;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval lob_new_begin, lob_new_end;
if (argc != 1)
{
#if defined(CAS_FOR_DBMS)
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
#else /* CAS_FOR_DBMS */
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
#endif /* CAS_FOR_DBMS */
return FN_KEEP_CONN;
}
net_arg_get_int (&lob_type, argv[0]);
if (lob_type != CCI_U_TYPE_BLOB && lob_type != CCI_U_TYPE_CLOB)
{
#if defined(CAS_FOR_DBMS)
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
#else /* CAS_FOR_DBMS */
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
#endif /* CAS_FOR_DBMS */
return FN_KEEP_CONN;
}
cas_log_write (0, false, "lob_new lob_type=%d", lob_type);
gettimeofday (&lob_new_begin, NULL);
err_code = ux_lob_new (lob_type, net_buf);
gettimeofday (&lob_new_end, NULL);
ut_timeval_diff (&lob_new_begin, &lob_new_end, &elapsed_sec, &elapsed_msec);
cas_log_write (0, false, "lob_new %s%d time %d.%03d%s", err_code < 0 ? "error:" : "", err_info.err_number,
elapsed_sec, elapsed_msec, get_error_log_eids (err_info.err_number));
return FN_KEEP_CONN;
}
FN_RETURN
fn_lob_write (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
DB_VALUE lob_dbval;
INT64 offset;
char *data_buf = NULL;
int err_code, data_length = 0;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval lob_new_begin, lob_new_end;
DB_ELO *elo_debug;
if (argc != 3)
{
#if defined(CAS_FOR_DBMS)
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
#else /* CAS_FOR_DBMS */
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
#endif /* CAS_FOR_DBMS */
return FN_KEEP_CONN;
}
net_arg_get_lob_value (&lob_dbval, argv[0]);
net_arg_get_bigint (&offset, argv[1]);
net_arg_get_str (&data_buf, &data_length, argv[2]);
elo_debug = db_get_elo (&lob_dbval);
cas_log_write (0, false, "lob_write lob_type=%d offset=%lld, length=%d", elo_debug->type, offset, data_length);
gettimeofday (&lob_new_begin, NULL);
err_code = ux_lob_write (&lob_dbval, offset, data_length, data_buf, net_buf);
gettimeofday (&lob_new_end, NULL);
ut_timeval_diff (&lob_new_begin, &lob_new_end, &elapsed_sec, &elapsed_msec);
cas_log_write (0, false, "lob_write %s%d time %d.%03d%s", err_code < 0 ? "error:" : "", err_info.err_number,
elapsed_sec, elapsed_msec, get_error_log_eids (err_info.err_number));
db_value_clear (&lob_dbval);
return FN_KEEP_CONN;
}
FN_RETURN
fn_lob_read (SOCKET sock_fd, int argc, void **argv, T_NET_BUF * net_buf, T_REQ_INFO * req_info)
{
DB_VALUE lob_dbval;
INT64 offset;
int err_code, data_length = 0;
int elapsed_sec = 0, elapsed_msec = 0;
struct timeval lob_new_begin, lob_new_end;
DB_ELO *elo_debug;
if (argc != 3)
{
#if defined(CAS_FOR_DBMS)
ERROR_INFO_SET (CAS_ER_ARGS, CAS_ERROR_INDICATOR);
NET_BUF_ERR_SET (net_buf);
#else /* CAS_FOR_DBMS */
net_buf_cp_int (net_buf, CAS_ER_ARGS, NULL);
#endif /* CAS_FOR_DBMS */
return FN_KEEP_CONN;
}
net_arg_get_lob_value (&lob_dbval, argv[0]);
net_arg_get_bigint (&offset, argv[1]);
net_arg_get_int (&data_length, argv[2]);
elo_debug = db_get_elo (&lob_dbval);
cas_log_write (0, false, "lob_read lob_type=%d offset=%lld, length=%d", elo_debug->type, offset, data_length);
gettimeofday (&lob_new_begin, NULL);
err_code = ux_lob_read (&lob_dbval, offset, data_length, net_buf);
gettimeofday (&lob_new_end, NULL);
ut_timeval_diff (&lob_new_begin, &lob_new_end, &elapsed_sec, &elapsed_msec);
cas_log_write (0, false, "lob_read %s%d time %d.%03d%s", err_code < 0 ? "error:" : "", err_info.err_number,
elapsed_sec, elapsed_msec, get_error_log_eids (err_info.err_number));
db_value_clear (&lob_dbval);
return FN_KEEP_CONN;
}
void
set_query_timeout (T_SRV_HANDLE * srv_handle, int query_timeout)
{
int broker_timeout_in_millis = shm_appl->query_timeout * 1000;
if (tran_is_in_libcas () == false)
{
if (query_timeout == 0 || broker_timeout_in_millis == 0)
{
tran_set_query_timeout (query_timeout + broker_timeout_in_millis);
if (query_timeout == 0 && broker_timeout_in_millis == 0)
{
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "set query timeout to 0 (no limit)");
}
else
{
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "set query timeout to %d ms (from %s)",
(query_timeout + broker_timeout_in_millis), (query_timeout > 0 ? "app" : "broker"));
}
}
else if (query_timeout > broker_timeout_in_millis)
{
tran_set_query_timeout (broker_timeout_in_millis);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "set query timeout to %d ms (from broker)",
broker_timeout_in_millis);
}
else
{
tran_set_query_timeout (query_timeout);
cas_log_write (SRV_HANDLE_QUERY_SEQ_NUM (srv_handle), false, "set query timeout to %d ms (from app)",
query_timeout);
}
}
}