diff options
author | unknown <monty@donna.mysql.com> | 2001-02-17 14:19:19 +0200 |
---|---|---|
committer | unknown <monty@donna.mysql.com> | 2001-02-17 14:19:19 +0200 |
commit | 132e667b0bbbe33137b6baeb59f3f22b7524f066 (patch) | |
tree | bfe39951a73e906579ab819bf5198ad8f3a64a36 /innobase/odbc | |
parent | b084cf1951eb271f662a9326c950f4cf0570258d (diff) | |
download | mariadb-git-132e667b0bbbe33137b6baeb59f3f22b7524f066.tar.gz |
Added Innobase to source distribution
Docs/manual.texi:
Added Innobase documentation
configure.in:
Incremented version
include/my_base.h:
Added option for Innobase
myisam/mi_check.c:
cleanup
mysql-test/t/bdb.test:
cleanup
mysql-test/t/innobase.test:
Extended with new tests from bdb.test
mysql-test/t/merge.test:
Added test of SHOW create
mysys/my_init.c:
Fix for UNIXWARE 7
scripts/mysql_install_db.sh:
Always write how to start mysqld
scripts/safe_mysqld.sh:
Fixed type
sql/ha_innobase.cc:
Update to new version
sql/ha_innobase.h:
Update to new version
sql/handler.h:
Added 'update_table_comment()' and 'append_create_info()'
sql/sql_delete.cc:
Fixes for Innobase
sql/sql_select.cc:
Fixes for Innobase
sql/sql_show.cc:
Append create information (for MERGE tables)
sql/sql_update.cc:
Fixes for Innobase
Diffstat (limited to 'innobase/odbc')
-rw-r--r-- | innobase/odbc/Makefile.am | 24 | ||||
-rw-r--r-- | innobase/odbc/makefilewin | 7 | ||||
-rw-r--r-- | innobase/odbc/odbc0dummy.c | 62 | ||||
-rw-r--r-- | innobase/odbc/odbc0odbc.c | 714 |
4 files changed, 807 insertions, 0 deletions
diff --git a/innobase/odbc/Makefile.am b/innobase/odbc/Makefile.am new file mode 100644 index 00000000000..d1a47bd8c18 --- /dev/null +++ b/innobase/odbc/Makefile.am @@ -0,0 +1,24 @@ +# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB +# & Innobase Oy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +include ../include/Makefile.i + +libs_LIBRARIES = libodbc.a + +libodbc_a_SOURCES = odbc0odbc.c + +EXTRA_PROGRAMS = diff --git a/innobase/odbc/makefilewin b/innobase/odbc/makefilewin new file mode 100644 index 00000000000..969043e096d --- /dev/null +++ b/innobase/odbc/makefilewin @@ -0,0 +1,7 @@ +include ..\include\makefile.i + +innobase.lib: odbc0odbc.obj + lib -out:..\libs\innobase.lib odbc0odbc.obj ..\libs\btr.lib ..\libs\eval.lib ..\libs\ibuf.lib ..\libs\trx.lib ..\libs\pars.lib ..\libs\que.lib ..\libs\lock.lib ..\libs\row.lib ..\libs\read.lib ..\libs\srv.lib ..\libs\com.lib ..\libs\usr.lib ..\libs\thr.lib ..\libs\fut.lib ..\libs\fsp.lib ..\libs\page.lib ..\libs\dyn.lib ..\libs\mtr.lib ..\libs\log.lib ..\libs\rem.lib ..\libs\fil.lib ..\libs\buf.lib ..\libs\dict.lib ..\libs\data.lib ..\libs\mach.lib ..\libs\ha.lib ..\libs\ut.lib ..\libs\sync.lib ..\libs\mem.lib ..\libs\os.lib + +odbc0odbc.obj: odbc0odbc.c + $(CCOM) $(CFL) -c odbc0odbc.c diff --git a/innobase/odbc/odbc0dummy.c b/innobase/odbc/odbc0dummy.c new file mode 100644 index 00000000000..e44677aa266 --- /dev/null +++ b/innobase/odbc/odbc0dummy.c @@ -0,0 +1,62 @@ +/* Used to screen off linker 'undefined symbol' errors +when making an ODBC client library */ + + +unsigned long srv_test_cache_evict; + +void buf_frame_alloc(void) +{} + +void buf_frame_free(void) +{} + +void trx_create(void) +{} + +void* kernel_mutex_temp; + +void trx_sig_send(void) +{} + +void rec_sprintf(void) +{} + +void dtuple_sprintf(void) +{} + +void pars_write_query_param_info (void) +{} + +void que_graph_try_free (void) +{} + +void pars_sql (void) +{} + +void que_run_threads (void) +{} + +void que_fork_start_command(void) +{} + +void dict_procedure_add_to_cache(void) +{} + +void dict_mem_procedure_create(void) +{} + +void pars_proc_read_input_params_from_buf(void) +{} + +void dict_procedure_reserve_parsed_copy(void) +{} + +void* srv_sys; + +void* srv_print_latch_waits; + +void* srv_spin_wait_delay; + +void* srv_n_spin_wait_rounds; + +void* buf_debug_prints; diff --git a/innobase/odbc/odbc0odbc.c b/innobase/odbc/odbc0odbc.c new file mode 100644 index 00000000000..640a88a2503 --- /dev/null +++ b/innobase/odbc/odbc0odbc.c @@ -0,0 +1,714 @@ +/****************************************************** +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, "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); +} |