diff options
Diffstat (limited to 'innobase/odbc/odbc0odbc.c')
-rw-r--r-- | innobase/odbc/odbc0odbc.c | 714 |
1 files changed, 0 insertions, 714 deletions
diff --git a/innobase/odbc/odbc0odbc.c b/innobase/odbc/odbc0odbc.c deleted file mode 100644 index 0deb17c6714..00000000000 --- a/innobase/odbc/odbc0odbc.c +++ /dev/null @@ -1,714 +0,0 @@ -/****************************************************** -Innobase ODBC client library - -(c) 1998 Innobase Oy - -Created 2/22/1998 Heikki Tuuri -*******************************************************/ - -#include "odbc0odbc.h" - -#include "mem0mem.h" -#include "com0com.h" -#include "usr0sess.h" - -#define ODBC_STAT_INITIAL 1 -#define ODBC_STAT_PREPARED 2 -#define ODBC_STAT_EXECUTED 3 - - -typedef struct odbc_conn_struct odbc_conn_t; -typedef struct odbc_env_struct odbc_env_t; - -/* ODBC parameter description struct */ - -typedef struct odbc_param_struct odbc_param_t; -struct odbc_param_struct{ - ulint data_type; /* SQL_CHAR, ... */ - ibool is_input; /* TRUE if an input parameter of a stored - procedure, FALSE if an output parameter */ - byte* buf; /* buffer where the value is stored before - SQLExecute, or where it comes after SQLExecute - in the case of an output parameter */ - lint* data_len; /* pointer to where the data len or the value - SQL_NULL_DATA is stored */ - ulint buf_len; /* buffer size */ -}; - -/* ODBC statement data structure */ - -typedef struct odbc_stat_struct odbc_stat_t; -struct odbc_stat_struct{ - ulint state; /* ODBC_STAT_INITIAL, - ODBC_STAT_PREPARED, - ODBC_STAT_EXECUTED */ - ulint id; /* statement id */ - ulint n_params; /* number of parameters */ - odbc_param_t* params; /* pointer to an array describing - the parameters, if any */ - ulint n_params_bound; /* number of parameters that have - been bound: the statement cannot be - executed before n_params_bound - == n_params */ - byte* error_msg; /* possible error message, or NULL; - allocated separately from dynamic - memory */ - ulint error_msg_len; /* error mesage length if it is - non-NULL */ - odbc_conn_t* conn; /* connection */ - UT_LIST_NODE_T(odbc_stat_t) - stat_list; /* list of the statements of the - connection */ -}; - -/* ODBC connection data structure */ - -struct odbc_conn_struct{ - ibool connected; /* TRUE if connected */ - char* server_name; /* server name where connected - (= server address) */ - ulint server_name_len;/* length of the server name */ - com_endpoint_t* com_endpoint; /* connection endpoint for this client - connection */ - dulint out_msg_count; /* count of outgoing messages */ - byte* out_datagram_buf;/* buffer for outgoing datagrams to - the server */ - byte* in_datagram_buf;/* buffer for incoming datagrams from - the server */ - byte* addr_buf; /* buffer for the address from which - an incoming datagram came; in practice, - this will be the server address */ - dulint sess_id; /* user session id, once the - connection to the server is - established */ - odbc_env_t* env; /* environment */ - UT_LIST_BASE_NODE_T(odbc_stat_t) - stat_list; /* list of the statements of the - connection */ - UT_LIST_NODE_T(odbc_conn_t) - conn_list; /* list of the connections of the - environment */ -}; - -/* ODBC environment data structure */ - -struct odbc_env_struct{ - UT_LIST_BASE_NODE_T(odbc_conn_t) conn_list; - /* list of the connections of the - environment */ -}; - -/************************************************************************** -Gets the nth parameter description struct for a statement. */ -UNIV_INLINE -odbc_param_t* -stat_get_nth_param( -/*===============*/ - /* out: nth parameter */ - odbc_stat_t* stat, /* in: pointer to statement handle */ - ulint i) /* in: parameter index */ -{ - ut_ad(stat->n_params > i); - - return(stat->params + i); -} - -/************************************************************************** -Allocates an SQL environment. */ - -RETCODE -SQLAllocEnv( -/*========*/ - /* out: SQL_SUCCESS */ - HENV* phenv) /* out: pointer to an environment handle */ -{ - odbc_env_t* env; - - if (!sync_initialized) { - sync_init(); - mem_init(2000000); - } - - env = mem_alloc(sizeof(odbc_env_t)); - - UT_LIST_INIT(env->conn_list); - - *phenv = env; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Allocates an SQL connection. */ - -RETCODE -SQLAllocConnect( -/*============*/ - /* out: SQL_SUCCESS */ - HENV henv, /* in: pointer to an environment handle */ - HDBC* phdbc) /* out: pointer to a connection handle */ -{ - odbc_conn_t* conn; - odbc_env_t* env; - - ut_a(henv); - - env = henv; - conn = mem_alloc(sizeof(odbc_conn_t)); - - conn->connected = FALSE; - conn->env = env; - - UT_LIST_INIT(conn->stat_list); - - UT_LIST_ADD_LAST(conn_list, env->conn_list, conn); - - *phdbc = conn; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Allocates an SQL statement. */ - -RETCODE -SQLAllocStmt( -/*=========*/ - HDBC hdbc, /* in: SQL connection */ - HSTMT* phstmt) /* out: pointer to a statement handle */ -{ - odbc_conn_t* conn; - odbc_stat_t* stat; - - ut_a(hdbc); - - conn = hdbc; - - stat = mem_alloc(sizeof(odbc_stat_t)); - - stat->state = ODBC_STAT_INITIAL; - stat->error_msg = NULL; - stat->conn = conn; - - UT_LIST_ADD_LAST(stat_list, conn->stat_list, stat); - - *phstmt = stat; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Sends the message in datagram_buf to the server. */ -static -void -odbc_send_cli_msg( -/*==============*/ - odbc_conn_t* conn, /* in: connection, does not have to be - connected yet */ - ulint len) /* in: message length (excluding the standard - header of size SESS_CLI_MSG_DATA) */ -{ - ulint ret; - ulint fold; - byte* msg; - - ut_a(len + SESS_CLI_MSG_DATA <= ODBC_DATAGRAM_SIZE); - - msg = conn->out_datagram_buf; - - mach_write_to_8(msg + SESS_CLI_MSG_NO, conn->out_msg_count); - - UT_DULINT_INC(conn->out_msg_count); - - fold = ut_fold_binary(msg + 4, len + SESS_CLI_MSG_DATA - 4); - - ut_ad(SESS_CLI_MSG_CHECKSUM == 0); - - mach_write_to_4(msg + SESS_CLI_MSG_CHECKSUM, fold); - - ret = com_sendto(conn->com_endpoint, msg, SESS_CLI_MSG_DATA + len, - conn->server_name, conn->server_name_len); - ut_a(ret == 0); -} - -/************************************************************************** -Receives a message in datagram_buf from the server. */ -static -void -odbc_recv_srv_msg( -/*==============*/ - odbc_conn_t* conn, /* in: connection, does not have to be - connected yet */ - ulint* len) /* out: received message length (excluding the - standard header of size SESS_SRV_MSG_DATA) */ -{ - ulint total_len; - ulint addr_len; - ulint ret; - - ret = com_recvfrom(conn->com_endpoint, conn->in_datagram_buf, - ODBC_DATAGRAM_SIZE, &total_len, (char*)conn->addr_buf, - ODBC_ADDRESS_SIZE, &addr_len); - ut_a(ret == 0); - ut_a(total_len >= SESS_SRV_MSG_DATA); - - *len = total_len - SESS_SRV_MSG_DATA; -} - -/************************************************************************** -Connects to a database server process (establishes a connection and a -session). */ - -RETCODE -SQLConnect( -/*=======*/ - /* out: SQL_SUCCESS */ - HDBC hdbc, /* in: SQL connection handle */ - UCHAR* szDSN, /* in: data source name (server name) */ - SWORD cbDSN, /* in: data source name length */ - UCHAR* szUID, /* in: user name */ - SWORD cbUID, /* in: user name length */ - UCHAR* szAuthStr, /* in: password */ - SWORD cbAuthStr) /* in: password length */ -{ - com_endpoint_t* ep; - odbc_conn_t* conn; - ulint err; - ulint size; - byte* msg; - ulint len; - UCHAR catenated_name[100]; - - ut_a(hdbc && szDSN); - - UT_NOT_USED(szUID); - UT_NOT_USED(cbUID); - UT_NOT_USED(szAuthStr); - UT_NOT_USED(cbAuthStr); - - conn = hdbc; - - ut_a(!conn->connected); - - conn->server_name = mem_alloc(cbDSN); - ut_memcpy(conn->server_name, szDSN, cbDSN); - - conn->server_name_len = cbDSN; - - ep = com_endpoint_create(COM_SHM); - - ut_a(ep); - - conn->com_endpoint = ep; - - conn->out_msg_count = ut_dulint_zero; - - size = ODBC_DATAGRAM_SIZE; - - err = com_endpoint_set_option(ep, COM_OPT_MAX_DGRAM_SIZE, - (byte*)&size, 4); - ut_a(err == 0); - - /* Make the data source name catenated to user name as the - address of the communications endpoint */ - - ut_a((ulint)cbDSN + (ulint)cbUID < 100); - - ut_memcpy(catenated_name, szDSN, (ulint)cbDSN); - ut_memcpy(catenated_name + (ulint)cbDSN, szUID, (ulint)cbUID); - - err = com_bind(ep, (char*)catenated_name, (ulint)cbDSN - + (ulint)cbUID); - ut_a(err == 0); - - conn->in_datagram_buf = mem_alloc(ODBC_DATAGRAM_SIZE); - - msg = mem_alloc(ODBC_DATAGRAM_SIZE); - - conn->out_datagram_buf = msg; - conn->addr_buf = mem_alloc(ODBC_ADDRESS_SIZE); - - /* Set the session id to dulint 0 as we are not yet connected */ - - sess_cli_msg_set_sess(msg, ut_dulint_zero); - sess_cli_msg_set_type(msg, SESS_CLI_CONNECT); - - /*------------------------------------------*/ - - odbc_send_cli_msg(conn, 0); - - odbc_recv_srv_msg(conn, &len); - - /*------------------------------------------*/ - - ut_a(len == 0); - ut_a(sess_srv_msg_get_type(conn->in_datagram_buf) - == SESS_SRV_ACCEPT_CONNECT); - - conn->sess_id = mach_read_from_8(conn->in_datagram_buf - + SESS_SRV_MSG_SESS_ID); - - /* Write the session id to out_datagram_buf: it will not be rewritten - until the connection is closed, as the session id will stay the same */ - - sess_cli_msg_set_sess(msg, conn->sess_id); - - /* We currently only send single part messages: the following will - stay 0 during the connection */ - - mach_write_to_4(msg + SESS_CLI_MSG_CONTINUE, 0); - mach_write_to_4(msg + SESS_CLI_MSG_CONT_SIZE, 0); - - conn->connected = TRUE; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Stores an error message to a statement handle, so that it can be later -queried with SQLError. */ -static -void -odbc_stat_store_error_msg( -/*======================*/ - odbc_stat_t* stat, /* in: statement handle */ - byte* msg, /* in: error message sent by the server */ - ulint len) /* in: length of msg */ -{ - if (stat->error_msg) { - mem_free(stat->error_msg); - } - - stat->error_msg_len = len; - - len += SESS_SRV_MSG_DATA; - - stat->error_msg = mem_alloc(len); - ut_memcpy(stat->error_msg, msg, len); -} - -/************************************************************************** -Queries an error message. */ - -RETCODE -SQLError( -/*=====*/ - /* out: SQL_SUCCESS or SQL_NO_DATA_FOUND */ - HENV henv, /* in: SQL_NULL_HENV */ - HDBC hdbc, /* in: SQL_NULL_HDBC */ - HSTMT hstmt, /* in: statement handle */ - UCHAR* szSqlState, /* in/out: SQLSTATE as a null-terminated string, - (currently, always == "S1000") */ - SDWORD* pfNativeError, /* out: native error code */ - UCHAR* szErrorMsg, /* in/out: buffer for an error message as a - null-terminated string */ - SWORD cbErrorMsgMax, /* in: buffer size for szErrorMsg */ - SWORD* pcbErrorMsg) /* out: error message length */ -{ - odbc_stat_t* stat; - ulint len; - - ut_a(henv == SQL_NULL_HENV); - ut_a(hdbc == SQL_NULL_HDBC); - ut_a(hstmt); - ut_a(cbErrorMsgMax > 1); - - stat = hstmt; - - if (stat->error_msg == NULL) { - - return(SQL_NO_DATA_FOUND); - } - - *pfNativeError = 0; - ut_memcpy(szSqlState, (char *) "S1000", 6); - - len = (ulint)cbErrorMsgMax - 1; - - if (stat->error_msg_len < len) { - len = stat->error_msg_len; - } - - ut_memcpy(szErrorMsg, stat->error_msg + SESS_SRV_MSG_DATA, len); - - *(szErrorMsg + len) = '\0'; - - *pcbErrorMsg = (SWORD)len; - - if (stat->error_msg) { - mem_free(stat->error_msg); - stat->error_msg = NULL; - } - - return(SQL_SUCCESS); -} - -/************************************************************************** -Makes the server to parse and optimize an SQL string. */ - -RETCODE -SQLPrepare( -/*=======*/ - /* out: SQL_SUCCESS or SQL_ERROR */ - HSTMT hstmt, /* in: statement handle */ - UCHAR* szSqlStr, /* in: SQL string */ - SDWORD cbSqlStr) /* in: SQL string length */ -{ - odbc_stat_t* stat; - odbc_conn_t* conn; - odbc_param_t* param; - ulint len; - byte* msg; - ulint i; - - stat = hstmt; - conn = stat->conn; - - if (stat->error_msg) { - mem_free(stat->error_msg); - stat->error_msg = NULL; - } - - ut_memcpy(conn->out_datagram_buf + SESS_CLI_MSG_DATA, szSqlStr, - 1 + (ulint)cbSqlStr); - - sess_cli_msg_set_type(conn->out_datagram_buf, SESS_CLI_PREPARE); - - /* The client message will be decoded in sess_receive_prepare */ - - /*------------------------------------------*/ - - odbc_send_cli_msg(conn, 1 + (ulint)cbSqlStr); - - odbc_recv_srv_msg(conn, &len); - - /*------------------------------------------*/ - - /* The server message was coded in sess_receive_prepare */ - - ut_a(len >= 8); - - msg = conn->in_datagram_buf; - - if (sess_srv_msg_get_type(msg) != SESS_SRV_SUCCESS) { - - ut_a(sess_srv_msg_get_type(msg) == SESS_SRV_ERROR); - - odbc_stat_store_error_msg(stat, msg, len); - - return(SQL_ERROR); - } - - stat->id = mach_read_from_4(msg + SESS_SRV_MSG_DATA); - - stat->n_params = mach_read_from_4(msg + SESS_SRV_MSG_DATA + 4); - - stat->n_params_bound = 0; - - ut_a(len == 8 + stat->n_params); - - if (stat->n_params > 0) { - - stat->params = mem_alloc(stat->n_params - * sizeof(odbc_param_t)); - for (i = 0; i < stat->n_params; i++) { - param = stat_get_nth_param(stat, i); - - param->is_input = mach_read_from_1( - msg + SESS_SRV_MSG_DATA + 8 + i); - /* Set buf to NULL so that we know when the parameter - has been bound */ - - param->buf = NULL; - } - } - - stat->state = ODBC_STAT_PREPARED; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Binds a parameter in a prepared statement. */ - -RETCODE -SQLBindParameter( -/*=============*/ - /* out: SQL_SUCCESS */ - HSTMT hstmt, /* in: statement handle */ - UWORD ipar, /* in: parameter index, starting from 1 */ - SWORD fParamType, /* in: SQL_PARAM_INPUT or SQL_PARAM_OUTPUT */ - SWORD fCType, /* in: SQL_C_CHAR, ... */ - SWORD fSqlType, /* in: SQL_CHAR, ... */ - UDWORD cbColDef, /* in: precision: ignored */ - SWORD ibScale, /* in: scale: ignored */ - PTR rgbValue, /* in: pointer to a buffer for the data */ - SDWORD cbValueMax, /* in: buffer size */ - SDWORD* pcbValue) /* in: pointer to a buffer for the data - length or SQL_NULL_DATA */ -{ - odbc_stat_t* stat; - odbc_param_t* param; - - stat = hstmt; - - ut_a(stat->state != ODBC_STAT_INITIAL); - ut_a(rgbValue); - ut_a(ipar <= stat->n_params); - ut_a(ipar > 0); - ut_a(cbValueMax >= 0); - ut_a(pcbValue); - - UT_NOT_USED(ibScale); - UT_NOT_USED(fCType); - UT_NOT_USED(cbColDef); - - if (stat->error_msg) { - mem_free(stat->error_msg); - stat->error_msg = NULL; - } - - param = stat_get_nth_param(stat, ipar - 1); - - if (param->buf == NULL) { - stat->n_params_bound++; - } - - param->data_type = fSqlType; - - ut_a((fParamType != SQL_PARAM_INPUT) || param->is_input); - ut_a((fParamType == SQL_PARAM_INPUT) || !param->is_input); - - param->buf = rgbValue; - param->buf_len = cbValueMax; - param->data_len = pcbValue; - - return(SQL_SUCCESS); -} - -/************************************************************************** -Executes a prepared statement where all parameters have been bound. */ - -RETCODE -SQLExecute( -/*=======*/ - /* out: SQL_SUCCESS or SQL_ERROR */ - HSTMT hstmt) /* in: statement handle */ -{ - odbc_stat_t* stat; - odbc_conn_t* conn; - odbc_param_t* param; - lint len; - ulint msg_len; - byte* msg; - byte* ptr; - lint int_val; - ulint i; - - stat = hstmt; - - ut_a(stat->state != ODBC_STAT_INITIAL); - ut_a(stat->n_params == stat->n_params_bound); - - if (stat->error_msg) { - mem_free(stat->error_msg); - stat->error_msg = NULL; - } - - conn = stat->conn; - msg = conn->out_datagram_buf; - - sess_cli_msg_set_type(msg, SESS_CLI_EXECUTE); - - ptr = msg + SESS_CLI_MSG_DATA; - - mach_write_to_4(ptr, stat->id); - - ptr += 4; - - for (i = 0; i < stat->n_params; i++) { - - param = stat_get_nth_param(stat, i); - - if (param->is_input) { - /* Copy its length and data to the message buffer */ - - len = *(param->data_len); - - mach_write_to_4(ptr, (ulint)len); - - ptr += 4; - - if (len != SQL_NULL_DATA) { - if (param->data_type == SQL_INTEGER) { - ut_ad(len == 4); - int_val = *((lint*)(param->buf)); - - mach_write_to_4(ptr, (ulint)int_val); - } else { - ut_memcpy(ptr, param->buf, len); - } - - ptr += len; - } - } - } - - /* The client message will be decoded in sess_receive_command */ - - /*------------------------------------------*/ - - odbc_send_cli_msg(conn, ptr - (msg + SESS_CLI_MSG_DATA)); - - odbc_recv_srv_msg(conn, &msg_len); - - /*------------------------------------------*/ - - /* The server message was coded in sess_command_completed_message */ - - msg = conn->in_datagram_buf; - - if (sess_srv_msg_get_type(msg) != SESS_SRV_SUCCESS) { - - ut_a(sess_srv_msg_get_type(msg) == SESS_SRV_ERROR); - - odbc_stat_store_error_msg(stat, msg, msg_len); - - return(SQL_ERROR); - } - - ptr = msg + SESS_SRV_MSG_DATA; - - for (i = 0; i < stat->n_params; i++) { - - param = stat_get_nth_param(stat, i); - - if (!param->is_input) { - /* Copy its length and data from the message buffer */ - - len = (lint)mach_read_from_4(ptr); - - ptr += 4; - - *(param->data_len) = len; - - if (len != SQL_NULL_DATA) { - if (param->data_type == SQL_INTEGER) { - ut_ad(len == 4); - - int_val = (lint)mach_read_from_4(ptr); - - *((lint*)(param->buf)) = int_val; - } else { - ut_memcpy(param->buf, ptr, (ulint)len); - } - - ptr += len; - } - } - } - - ut_ad(msg + SESS_SRV_MSG_DATA + msg_len == ptr); - - return(SQL_SUCCESS); -} |