scsh-0.6/scsh/odbc/odbc.c

2241 lines
48 KiB
C

#include "odbc.h"
/*
*
* PART 1
*
* Connecting to a data source
*
*/
/* Call SQLAllocHandle and get an environment handle. After that
* call odbc_set_environment to set the ODBC version */
s48_value odbc_alloc_environment_handle()
{
SQLHENV henv;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_alloc_environment\n");
retval = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
switch (retval)
{
case SQL_SUCCESS:
{
odbc_sql_set_env_attr(henv);
return s48_enter_integer((long)henv);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, henv);
odbc_sql_set_env_attr(henv);
return s48_enter_integer((long)henv);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, henv);
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned SQL_ERROR");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLAllocHandle unknown return value");
break;
}
}
}
/* given a valid environment handle (type SQLHENV) this function
* sets the environment attributes. This needs to be done before
* allocating a connection handle */
void odbc_sql_set_env_attr(SQLHENV env_handle)
{
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_set_environment\n");
retval = SQLSetEnvAttr(env_handle,
SQL_ATTR_ODBC_VERSION,
(void *)SQL_OV_ODBC3, 0);
switch (retval)
{
case SQL_SUCCESS:
{
return;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, env_handle);
return;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, env_handle);
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr got invalid handle. Is your ODBC broken?");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr returned unknown error code\n");
break;
}
}
}
/* Given a valid environment handle get a connection handle */
s48_value odbc_alloc_connection_handle(s48_value env_handle) {
SQLHDBC hdbc;
SQLRETURN retval;
SQLHENV envh;
ODBC_DEBUG_PRINTF("odbc_alloc_connection_handle\n");
envh = (SQLHENV) s48_extract_integer(env_handle);
retval = SQLAllocHandle(SQL_HANDLE_DBC, envh, &hdbc);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_integer((long)hdbc);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, envh);
return s48_enter_integer((long)hdbc);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, envh);
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLAllocHandle got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned unknown error code");
break;
}
}
}
/* Given a valid connection handle get a statement handle */
s48_value odbc_alloc_statement_handle(s48_value conn_handle) {
SQLHSTMT hstmt;
SQLRETURN retval;
SQLHANDLE ch;
ODBC_DEBUG_PRINTF("odbc_alloc_statement_handle\n");
ch = (SQLHANDLE) s48_extract_integer(conn_handle);
retval = SQLAllocHandle(SQL_HANDLE_STMT, ch, &hstmt);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_integer((long)hstmt);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return s48_enter_integer((long)hstmt);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLAllocHandle got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned unknown error code");
break;
}
}
}
/* Connect to a server */
s48_value odbc_sql_connect(s48_value connection_handle,
s48_value ds_name,
s48_value user_name,
s48_value authentication)
{
SQLHDBC ch;
SQLCHAR *dsn, *user, *auth;
SQLRETURN retval;
int dsn_len, user_len, auth_len;
ODBC_DEBUG_PRINTF("odbc_sql_connect\n");
dsn = (SQLCHAR *) s48_extract_string(ds_name);
user = (SQLCHAR *) s48_extract_string(user_name);
auth = (SQLCHAR *) s48_extract_string(authentication);
dsn_len = S48_STRING_LENGTH(ds_name);
user_len = S48_STRING_LENGTH(user_name);
auth_len = S48_STRING_LENGTH(authentication);
ch = (SQLHDBC) s48_extract_integer(connection_handle);
retval = SQLConnect(ch,
dsn, dsn_len,
user, user_len,
auth, auth_len);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLConnect returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLConnect got invalid handle");
break;
}
default:
ODBC_RAISE_EXCEPTION("SQLConnect returned an unknown error code");
break;
}
}
/*
*
* PART 2
*
* Obtaining information about a driver and data source
*
*/
/* Returns a list of available data sources. */
s48_value odbc_sql_data_sources(s48_value env_handle)
{
SQLHENV eh;
SQLUSMALLINT dir;
SQLRETURN retval;
SQLCHAR server_name[SQL_MAX_DSN_LENGTH+1];
SQLSMALLINT server_name_len;
SQLCHAR driver_descr[ODBC_MAX_DRIVER_NAME_LEN];
SQLSMALLINT driver_descr_len;
s48_value result;
int first;
eh = (SQLHENV) s48_extract_integer(env_handle);
ODBC_DEBUG_PRINTF("odbc_sql_data_sources\n");
result = S48_NULL;
first = 1;
while (1) {
retval = SQLDataSources(eh,
(first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT),
server_name, SQL_MAX_DSN_LENGTH+1, &server_name_len,
driver_descr, ODBC_MAX_DRIVER_NAME_LEN, &driver_descr_len);
first = 0;
switch (retval)
{
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
{
result = s48_cons(s48_cons(s48_enter_string(server_name),
s48_enter_string(driver_descr)),
result);
if (retval == SQL_SUCCESS_WITH_INFO)
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
break;
}
case SQL_NO_DATA:
{
return result;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
ODBC_RAISE_EXCEPTION("SQLDataSources returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLDataSources got invalid handle");
break;
}
default:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
ODBC_RAISE_EXCEPTION("SQLDataSources returned unknown error code");
break;
}
}
}
}
/* Returns the list of installed drivers and their attributes. */
s48_value odbc_sql_drivers(s48_value env_handle)
{
SQLHENV eh;
SQLRETURN retval;
SQLCHAR driver_descr[ODBC_MAX_DRIVER_NAME_LEN];
SQLSMALLINT driver_descr_len;
SQLCHAR driver_attr[ODBC_MAX_DRIVER_NAME_LEN];
SQLSMALLINT driver_attr_len;
s48_value result;
int first;
ODBC_DEBUG_PRINTF("odbc_sql_drivers\n");
eh = (SQLHENV) s48_extract_integer(env_handle);
result = S48_NULL;
first = 0;
while (1) {
retval = SQLDrivers(eh,
(SQLUSMALLINT) (first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT),
driver_descr, ODBC_MAX_DRIVER_NAME_LEN, &driver_descr_len,
driver_attr, ODBC_MAX_DRIVER_NAME_LEN, &driver_attr_len);
first = 1;
switch (retval)
{
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
{
result = s48_cons(s48_cons(s48_enter_string(driver_descr),
s48_enter_string(driver_attr)),
result);
if (retval == SQL_SUCCESS_WITH_INFO)
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
break;
}
case SQL_NO_DATA:
{
return result;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
ODBC_RAISE_EXCEPTION("SQLDrivers returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLDrivers got invalid handle");
break;
}
default:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
ODBC_RAISE_EXCEPTION("SQLDrivers returned unknown error code");
break;
}
}
}
}
/* Returns information about a specific driver and data source.
* (use if the information is an integer) */
s48_value odbc_sql_get_info_int(s48_value conn_handle, s48_value info_key)
{
SQLHDBC ch;
SQLUSMALLINT ik;
SQLRETURN retval;
SQLUINTEGER info;
SQLSMALLINT buffer_size;
ODBC_DEBUG_PRINTF("odbc_sql_get_info_int\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
ik = (SQLUSMALLINT) s48_extract_integer(info_key);
retval = SQLGetInfo(ch, ik, &info, sizeof(SQLUINTEGER), &buffer_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_integer(info);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return s48_enter_integer(info);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLGetInfo returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetInfo got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetInfo returned unknown error code");
break;
}
}
}
/* Returns information about a specific driver and data source.
* (use if the information is a string) */
s48_value odbc_sql_get_info_string(s48_value conn_handle, s48_value info_key)
{
SQLHDBC ch;
SQLUSMALLINT ik;
SQLRETURN retval;
SQLCHAR info[ODBC_GET_INFO_MAX_LEN];
SQLSMALLINT buffer_size;
ODBC_DEBUG_PRINTF("odbc_sql_get_info_string\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
ik = (SQLUSMALLINT) s48_extract_integer(info_key);
retval = SQLGetInfo(ch, ik, &info, ODBC_GET_INFO_MAX_LEN, &buffer_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_string(info);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return s48_enter_string(info);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLGetInfo returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetInfo got invalid exception");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetInfo returned unknown error code");
break;
}
}
}
/* Returns supported driver functions. (for a multiple functions) */
s48_value odbc_sql_get_func_exists(s48_value conn_handle, s48_value fun_id)
{
SQLHDBC ch;
SQLUSMALLINT fi, supported[SQL_API_ODBC3_ALL_FUNCTIONS_SIZE];
SQLRETURN retval;
s48_value vec;
int i;
ODBC_DEBUG_PRINTF("odbc_sql_func_exists\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
fi = (SQLUSMALLINT) s48_extract_integer(fun_id);
retval = SQLGetFunctions(ch, fi, supported);
switch (retval)
{
case SQL_SUCCESS:
{
return SQL_FUNC_EXISTS(supported, fi) == SQL_TRUE ? S48_TRUE : S48_FALSE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return SQL_FUNC_EXISTS(supported, fi) == SQL_TRUE ? S48_TRUE : S48_FALSE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLGetFunctions returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetFunctions got invalid exception");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetFunctions returned unknown error code");
break;
}
}
}
/* Returns information about supported data types. */
s48_value odbc_sql_get_type_info(s48_value stmt_handle, s48_value data_type)
{
SQLHSTMT sh;
SQLSMALLINT dt;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_type_info\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
dt = (SQLSMALLINT) s48_extract_integer(data_type);
retval = SQLGetTypeInfo(sh, dt);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLGetTypeInfo returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetTypeInfo got invalid handle");
break;
}
/* TODO: handle SQL_STILL_EXECUTING */
default:
{
ODBC_RAISE_EXCEPTION("SQLGetTypeInfo returned unknown error code");
break;
}
}
}
/*
*
* PART 3
*
* Setting and retrieving driver attributes
*
*/
s48_value odbc_sql_set_connect_attr_int(s48_value conn_handle,
s48_value attribute,
s48_value value)
{
SQLHDBC ch;
SQLINTEGER attr;
SQLUINTEGER val;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_set_connect_attr_int\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLUINTEGER) s48_extract_integer(value);
retval = SQLSetConnectAttr(ch, attr, &val, 0);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr got unknown error code");
break;
}
}
}
s48_value odbc_sql_set_connect_attr_string(s48_value conn_handle,
s48_value attribute,
s48_value value)
{
SQLHDBC ch;
SQLINTEGER attr;
SQLCHAR *val;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_set_connect_attr_string\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLCHAR *) s48_extract_string(value);
retval = SQLSetConnectAttr(ch, attr, val, S48_STRING_LENGTH(value));
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetConnectAttr got unknown error code");
break;
}
}
}
s48_value odbc_sql_get_connect_attr_string(s48_value conn_handle,
s48_value attribute)
{
SQLHDBC ch;
SQLINTEGER attr;
SQLCHAR buffer[ODBC_GET_CONNECT_ATTR_MAX_LEN];
SQLINTEGER buffer_size;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_connect_attr_string\n");
retval = SQLGetConnectAttr(ch, attr,
buffer, ODBC_GET_CONNECT_ATTR_MAX_LEN-1,
&buffer_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_string(buffer);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return s48_enter_string(buffer);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_get_connect_attr_int(s48_value conn_handle,
s48_value attribute)
{
SQLHDBC ch;
SQLINTEGER attr;
SQLUINTEGER buffer;
SQLINTEGER buffer_size;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_connect_attr_int\n");
retval = SQLGetConnectAttr(ch, attr,
&buffer, sizeof(SQLUINTEGER), &buffer_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_integer(buffer);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return s48_enter_integer(buffer);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetConnectAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_set_env_attr_int(s48_value env_handle,
s48_value attribute,
s48_value value)
{
SQLHENV eh;
SQLINTEGER attr;
SQLUINTEGER val;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_set_env_attr\n");
eh = (SQLHENV) s48_extract_integer(env_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLUINTEGER) s48_extract_integer(value);
retval = SQLSetEnvAttr(eh, attr, &val, sizeof(SQLUINTEGER));
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, eh);
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetEnvAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_get_env_attr_int(s48_value env_handle,
s48_value attribute,
s48_value value)
{
SQLHENV eh;
SQLINTEGER attr;
SQLUINTEGER val, str_len;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_env_attr_int\n");
eh = (SQLHENV) s48_extract_integer(env_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLUINTEGER) s48_extract_integer(value);
retval = SQLGetEnvAttr(eh, attr, &val, sizeof(SQLUINTEGER), &str_len);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_extract_integer(val);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
return s48_extract_integer(val);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_ENV, eh);
ODBC_RAISE_EXCEPTION("SQLGetEnvAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetEnvAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetEnvAttr returned unknown error code");
break;
}
}
}
/* Sets a statement attribute */
s48_value odbc_sql_set_stmt_attr_int(s48_value stmt_handle,
s48_value attribute,
s48_value value)
{
SQLHSTMT sh;
SQLINTEGER attr;
SQLUINTEGER val;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_int\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLUINTEGER) s48_extract_integer(value);
retval = SQLSetStmtAttr(sh, attr, &val, 0);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr got invalid handel");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle,
s48_value attribute,
s48_value value)
{
SQLHSTMT sh;
SQLINTEGER attr;
SQLCHAR *val;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_set_stmt_attr_string\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
val = (SQLCHAR *) s48_extract_string(value);
retval = SQLSetStmtAttr(sh, attr,
val, S48_STRING_LENGTH(value));
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr got invalid handel");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLSetStmtAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_get_stmt_attr_int(s48_value stmt_handle,
s48_value attribute)
{
SQLHSTMT sh;
SQLINTEGER attr, val, buf_size;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_int\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
attr = (SQLINTEGER) s48_extract_integer(attribute);
retval = SQLGetStmtAttr(sh, attr, &val, sizeof(SQLINTEGER), &buf_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_integer(val);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return s48_enter_integer(val);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr returned unknown error code");
break;
}
}
}
s48_value odbc_sql_get_stmt_attr_string(s48_value stmt_handle,
s48_value attribute)
{
SQLHSTMT sh;
SQLINTEGER attr, buf_size;
SQLCHAR buf[ODBC_GET_STMT_ATTR_MAX_LEN];
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_string\n");
retval = SQLGetStmtAttr(sh, attr, &buf,
ODBC_GET_STMT_ATTR_MAX_LEN-1, &buf_size);
switch (retval)
{
case SQL_SUCCESS:
{
return s48_enter_string(buf);
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return s48_enter_string(buf);
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLGetStmtAttr returned unknown error code");
break;
}
}
}
/*
*
* part 4
*
* Setting and retrieving descriptor fields
*
*/
/*
*
* PART 5
*
* Preparing SQL requests
*
*/
/* Prepare a SQL statement for execution */
s48_value odbc_sql_prepare(s48_value stmt_handle, s48_value stmt_txt)
{
SQLHSTMT sh;
SQLCHAR *query;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_prepare\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
query = (SQLCHAR *) s48_extract_string(stmt_txt);
retval = SQLPrepare(sh, query, S48_STRING_LENGTH(stmt_txt));
switch (retval) {
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLPrepare got invalid handle");
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLPrepare returned SQL_ERROR");
break;
}
case SQL_STILL_EXECUTING:
{
/* Not yet implemented, raise an error meanwhile */
ODBC_RAISE_EXCEPTION("SQLPrepare returned SQL_STILL_EXECUTING");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLPrepare returned an unknown error code");
break;
}
}
}
s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle,
s48_value param_vals)
{
SQLHSTMT sh;
SQLSMALLINT value_type, param_type;
SQLRETURN retval;
unsigned int i;
ODBC_DEBUG_PRINTF("odbc_sql_bind_parameter_exec_out\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
/* bind parameters */
for (i = 0; i < S48_VECTOR_LENGTH(param_vals); i++) {
ODBC_DEBUG_PRINTF_ARG1("Binding parameter %d", i);
value_type = (SQLSMALLINT)
s48_extract_integer(S48_CAR(S48_CDR(S48_VECTOR_REF(param_vals, i))));
param_type = (SQLSMALLINT)
s48_extract_integer(S48_CDR(S48_CDR(S48_VECTOR_REF(param_vals, i))));
switch (value_type)
{
case SQL_C_CHAR:
case SQL_C_BINARY:
{
SQLCHAR *value;
SQLUINTEGER val_len;
ODBC_DEBUG_PRINTF("value_type is string\n");
value = (SQLCHAR *)
s48_extract_string(S48_CAR(S48_VECTOR_REF(param_vals, i)));
val_len =
(SQLUINTEGER) S48_STRING_LENGTH(S48_CAR(S48_VECTOR_REF(param_vals, i)));
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
val_len, 0,
value, 0, (void *)SQL_NTS);
break;
}
case SQL_C_SHORT:
case SQL_C_LONG:
{
SQLINTEGER value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type integer\n");
cb_val = 0;
value = (SQLINTEGER)
s48_extract_integer(S48_CAR(S48_VECTOR_REF(param_vals, i)));
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_BIT:
case SQL_C_STINYINT:
case SQL_C_UTINYINT:
{
SQLCHAR value;
SQLINTEGER cb_val;
cb_val = 0;
value = (SQLCHAR)
s48_extract_char(S48_CAR(S48_VECTOR_REF(param_vals, i)));
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_FLOAT:
{
SQLREAL value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type is float\n");
cb_val = 0;
value = (SQLREAL)
S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i)));
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_DOUBLE:
{
SQLDOUBLE value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type is double\n");
cb_val = 0;
value = (SQLDOUBLE)
S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i)));
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_TYPE_DATE:
{
SQL_DATE_STRUCT value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type is date\n");
cb_val = 0;
sql_date_record_to_struct(param_vals, &value);
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_TYPE_TIME:
{
SQL_TIME_STRUCT value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type is time\n");
cb_val = 0;
sql_time_record_to_struct(param_vals, &value);
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
case SQL_C_TYPE_TIMESTAMP:
{
SQL_TIMESTAMP_STRUCT value;
SQLINTEGER cb_val;
ODBC_DEBUG_PRINTF("value_type is timestamp\n");
cb_val = 0;
sql_timestamp_record_to_struct(param_vals, &value);
retval = SQLBindParameter(sh, (SQLUSMALLINT) (i+1),
SQL_PARAM_OUTPUT,
value_type, param_type,
0, 0,
&value, 0, &cb_val);
break;
}
/* case SQL_C_NUMERIC: */
/* { */
/* SQL_NUMERIC_STRUCT value; */
/* SQLINTEGER cb_val; */
/* cb_val = 0; */
/* value.precision = (SQLCHAR) */
/* s48_extract_char(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)), */
/* SR_SQL_NUMERIC_PRECISION)); */
/* value.scale = (SQLSCHAR) */
/* s48_extract_char(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)), */
/* SR_SQL_NUMERIC_SCALE)); */
/* value.sign = (SQLCHAR) */
/* s48_extract_char(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)), */
/* SR_SQL_NUMERIC_SIGN)); */
/* } */
default:
{
ODBC_RAISE_EXCEPTION("SQLBindParameter: unknown/unsupported value type");
break;
}
}
ODBC_DEBUG_PRINTF("All parameters bound\n");
/* check the return value of SQLBindParameter */
if (retval != SQL_SUCCESS) {
switch (retval)
{
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLBindParameter returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLBindParameter got invalid handle");
break;
}
}
}
} /* for */
ODBC_DEBUG_PRINTF("Executing statement\n");
/* execute statement */
retval = SQLExecute(sh);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLExcute returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLExcute got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLExcute returned unknown error code");
break;
}
}
}
/*
*
* PART 6
*
* Submitting requests
*
*/
s48_value odbc_sql_execute(s48_value stmt_handle)
{
SQLHSTMT sh;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_execute\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
retval = SQLExecute(sh);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLExecute returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLExecute got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLExecute returned unknown error code");
break;
}
}
}
s48_value odbc_sql_execute_direct(s48_value stmt_handle,
s48_value stmt)
{
SQLHSTMT sh;
SQLCHAR *query;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_execute_direct\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
query = (SQLCHAR *) s48_extract_string(stmt);
retval = SQLExecDirect(sh, query, S48_STRING_LENGTH(stmt));
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_ERROR");
break;
}
case SQL_NEED_DATA:
{
return SQL_NEED_DATA;
}
case SQL_STILL_EXECUTING:
{
ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_STILL_EXECUTING, not implemented yet");
break;
}
case SQL_NO_DATA:
{
return SQL_NO_DATA;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLExecDirect got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLExecDirect returned unknown error code");
break;
}
}
}
/*
*
* PART 7
*
* Retrieving results and information about results
*
*/
s48_value odbc_sql_get_data(s48_value stmt_handle,
s48_value column_number,
s48_value target_type)
{
SQLHSTMT sh;
SQLUSMALLINT cn;
SQLSMALLINT tt;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_get_data\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
cn = (SQLUSMALLINT) s48_extract_integer(column_number);
tt = (SQLSMALLINT) s48_extract_integer(target_type);
switch (tt)
{
case SQL_C_CHAR:
case SQL_C_BINARY:
{
SQLCHAR str[ODBC_GET_DATA_MAX_STR_LEN];
SQLINTEGER str_len;
retval = SQLGetData(sh, cn, tt,
str, ODBC_GET_DATA_MAX_STR_LEN-1,
&str_len);
check_sql_get_data_result(retval, sh);
return s48_enter_string((char *) str);
}
case SQL_C_SSHORT:
case SQL_C_USHORT:
case SQL_C_SLONG:
case SQL_C_ULONG:
{
long int i;
SQLINTEGER rest;
retval = SQLGetData(sh, cn, tt,
&i, sizeof(long int), &rest);
check_sql_get_data_result(retval, sh);
return s48_enter_integer(i);
}
}
}
void check_sql_get_data_result(SQLRETURN retval, SQLHSTMT stmt_handle)
{
switch (retval)
{
case SQL_SUCCESS:
{
return;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, stmt_handle);
return;
}
case SQL_NO_DATA:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, stmt_handle);
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_NO_DATA");
break;
}
case SQL_STILL_EXECUTING:
{
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_STILL_EXECUTING, not yet implemented");
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, stmt_handle);
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLGetData got invalid handle");
break;
}
}
}
s48_value odbc_sql_fetch(s48_value stmt_handle)
{
SQLHSTMT sh;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_fetch\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
retval = SQLFetch(sh);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_NO_DATA:
{
return SQL_NO_DATA;
}
case SQL_STILL_EXECUTING:
{
ODBC_RAISE_EXCEPTION("SQLFetch returned SQL_STILL_EXECUTING, not yet implemented");
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLFetch returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLFetch got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLFetch returned unknown error code");
break;
}
}
}
s48_value odbc_sql_num_result_cols(s48_value stmt_handle)
{
SQLHSTMT sh;
SQLSMALLINT numcols;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_num_result_cols\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
retval = SQLNumResultCols(sh, &numcols);
switch (retval)
{
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
{
if (retval == SQL_SUCCESS_WITH_INFO)
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return s48_enter_integer(numcols);
}
case SQL_STILL_EXECUTING:
{
ODBC_RAISE_EXCEPTION("SQLNumResultCols returned SQL_STILL_EXECUTING, not yet implemented");
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLNumResultCols returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLNumResultCols got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLNumResultCols returned unknown error code");
break;
}
}
}
s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number)
{
SQLHSTMT sh;
SQLSMALLINT cn;
SQLCHAR column_name[ODBC_DESCRIBE_COL_MAX_STR_LEN];
SQLSMALLINT buf_len, data_type, digits, nullable;
SQLUINTEGER col_size;
s48_value col_rec;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_describe_col\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
cn = (SQLSMALLINT) s48_extract_integer(column_number);
retval = SQLDescribeCol(sh, cn,
column_name,
ODBC_DESCRIBE_COL_MAX_STR_LEN - 1,
&buf_len,
&data_type,
&col_size,
&digits,
&nullable);
switch (retval)
{
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
{
if (retval == SQL_SUCCESS_WITH_INFO)
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
col_rec = s48_make_record(odbc_column_record_type);
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_NAME,
s48_enter_string(column_name));
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_TYPE,
s48_enter_integer(data_type));
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_SIZE,
s48_enter_integer(col_size));
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_DIGITS,
s48_enter_integer(digits));
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_NULLABLE,
s48_enter_integer(nullable));
return col_rec;
}
case SQL_STILL_EXECUTING:
{
ODBC_RAISE_EXCEPTION("SQLDescribeCol returned SQL_STILL_EXECUTING, not yet implemented");
break;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLDescribeCol returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLDescribeCol got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLDescribeCol returned unknown error code");
break;
}
}
}
/*
*
* PART 8
*
* Obtaining information about the data source's
* system tables (catalog functions)
*
*/
/*
*
* PART 9
*
* Terminating a statement
*
*/
/* Ends statement processing, discards pending resilt, and,
* optionally, frees all resources associated with the
* statement handle */
s48_value odbc_sql_free_statement(s48_value stmt_handle, s48_value option)
{
SQLHSTMT sh;
SQLUSMALLINT opt;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_free_statement\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
opt = (SQLUSMALLINT) s48_extract_integer(option);
retval = SQLFreeStmt(sh, opt);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLFreeStmt returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLFreeStmt got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLFreeStmt returned unknown error");
break;
}
}
}
/* Closes a cursor that has been opened on a statement handle */
s48_value odbc_sql_close_cursor(s48_value stmt_handle)
{
SQLHSTMT sh;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_close_cursor\n");
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
retval = SQLCloseCursor(sh);
switch (retval) {
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLCloseCursor returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLCloseCursor got an invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLCloseCursor returned an unknown error code");
break;
}
}
}
/* Cancels an SQL statement */
s48_value odbc_sql_cancel(s48_value stmt_handle)
{
SQLHSTMT sh;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_cancel\n");
retval = SQLCancel(sh);
switch (retval) {
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_STMT, sh);
ODBC_RAISE_EXCEPTION("SQLCancel returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLCancel got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLCancel returned unknown error code");
break;
}
}
}
/* Commits or rolls back a transaction */
s48_value odbc_sql_endtran(s48_value handle_type, s48_value handle,
s48_value completion_type)
{
SQLSMALLINT ht, ct;
SQLHANDLE h;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_endtran\n");
ht = (SQLSMALLINT) s48_extract_integer(handle_type);
h = (SQLHANDLE) s48_extract_integer(handle);
ct = (SQLSMALLINT) s48_extract_integer(completion_type);
retval = SQLEndTran(ht, h, ct);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(ht, h);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(ht, h);
ODBC_RAISE_EXCEPTION("SQLEndTran returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLEndTran got invalid handle");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLEndTran returned unknown error code");
break;
}
}
}
/*
*
* PART 10
*
* Terminating a connection
*
*/
/* Closes the connection */
s48_value odbc_sql_disconnect(s48_value conn_handle)
{
SQLHDBC ch;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_sql_disconnect\n");
ch = (SQLHDBC) s48_extract_integer(conn_handle);
retval = SQLDisconnect(ch);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_SUCCESS_WITH_INFO:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(SQL_HANDLE_DBC, ch);
ODBC_RAISE_EXCEPTION("SQLDisconnect returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLDisconnect got invalid hande");
break;
}
default:
{
ODBC_RAISE_EXCEPTION("SQLDisconnect returned unknown error code");
break;
}
}
}
/* Free a handle */
s48_value odbc_sql_free_handle(s48_value handle_type, s48_value handle)
{
SQLSMALLINT ht;
SQLHANDLE h;
SQLRETURN retval;
ODBC_DEBUG_PRINTF("odbc_free_handle\n");
ht = (SQLSMALLINT) s48_extract_integer(handle_type);
h = (SQLHANDLE) s48_extract_integer(handle);
retval = SQLFreeHandle(ht, h);
switch (retval)
{
case SQL_SUCCESS:
{
return S48_TRUE;
}
case SQL_ERROR:
{
ODBC_DEBUG_DIAGREC(ht, h);
ODBC_RAISE_EXCEPTION("SQLFreeHandle returned SQL_ERROR");
break;
}
case SQL_INVALID_HANDLE:
{
ODBC_RAISE_EXCEPTION("SQLFreeHandle got invalid handle");
break;
}
default:
{
ODBC_DEBUG_DIAGREC(ht, h);
ODBC_RAISE_EXCEPTION("SQLFreeHandle returned unknown error code");
break;
}
}
}
/*
*
* PART 11
*
* misc. functions
*
*/
#ifdef ODBC_DEBUG_MSGS
/* print detailed debug information */
void odbc_debug_msgs(SQLSMALLINT handle_type, SQLHANDLE handle)
{
SQLCHAR sql_state[5];
SQLINTEGER native_error;
SQLCHAR message[ERROR_MSG_BUFFER_LEN];
SQLSMALLINT i, message_len;
SQLRETURN retval;
i = 1;
while (1) {
retval = SQLGetDiagRec(handle_type, handle,
i, sql_state,
&native_error,
message, ERROR_MSG_BUFFER_LEN-1,
&message_len);
if (retval == SQL_NO_DATA)
break;
if (retval == SQL_INVALID_HANDLE) {
printf("ODBC: Could not get debug information: invalid handle provided\n");
break;
}
if (retval == SQL_ERROR) {
printf("ODBC: SQLGetDiagRec returned SQL_ERROR\n");
break;
}
if (retval == SQL_SUCCESS_WITH_INFO)
printf("ODBC warning: error message buffer too small.\n");
if (retval == SQL_SUCCESS) {
printf("\nODBC status record %d:\n", i);
printf("SQL state: %s\n", (char *)sql_state);
/* TODO:
* Need to find out how to printf the
* native_error here
*/
printf("error msg: %s\n", message);
}
i++;
}
}
#endif
/* convert Scheme sql-date record to SQL_DATE_STRUCT */
void sql_date_record_to_struct(s48_value sql_date, SQL_DATE_STRUCT *ds)
{
ds->year = (SQLSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_date, SR_SQL_DATE_YEAR));
ds->month = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_date, SR_SQL_DATE_MONTH));
ds->day = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_date, SR_SQL_DATE_DAY));
}
/* convert SQL_DATE_STRUCT to Scheme sql-date record */
s48_value struct_to_sql_date_record(SQL_DATE_STRUCT *ds)
{
s48_value sql_date;
sql_date = s48_make_record(sql_date_record_type);
S48_RECORD_SET(sql_date, SR_SQL_DATE_YEAR,
s48_enter_integer(ds->year));
S48_RECORD_SET(sql_date, SR_SQL_DATE_MONTH,
s48_enter_integer(ds->month));
S48_RECORD_SET(sql_date, SR_SQL_DATE_DAY,
s48_enter_integer(ds->day));
return sql_date;
}
/* convert Scheme sql-time record to SQL_TIME_STRUCT */
void sql_time_record_to_struct(s48_value sql_time, SQL_TIME_STRUCT *ts)
{
ts->hour = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_time, SR_SQL_TIME_HOUR));
ts->minute = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_time, SR_SQL_TIME_MINUTE));
ts->second = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_time, SR_SQL_TIME_SECOND));
}
/* convert SQL_TIME_STRUCT to Scheme sql-time record */
s48_value struct_to_sql_time_record(SQL_TIME_STRUCT *ts)
{
s48_value sql_time;
sql_time = s48_make_record(sql_time_record_type);
S48_RECORD_SET(sql_time, SR_SQL_TIME_HOUR,
s48_extract_integer(ts->hour));
S48_RECORD_SET(sql_time, SR_SQL_TIME_MINUTE,
s48_extract_integer(ts->minute));
S48_RECORD_SET(sql_time, SR_SQL_TIME_SECOND,
s48_extract_integer(ts->second));
return sql_time;
}
/* convert Scheme sql-timestamp record to SQL_TIMESTAMP_STRUCT */
void sql_timestamp_record_to_struct(s48_value sql_timestamp,
SQL_TIMESTAMP_STRUCT *ts)
{
ts->year = (SQLSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_YEAR));
ts->month = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_MONTH));
ts->day = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_DAY));
ts->hour = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_HOUR));
ts->minute = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_MINUTE));
ts->second = (SQLUSMALLINT)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_SECOND));
ts->fraction = (SQLUINTEGER)
s48_extract_integer(S48_RECORD_REF(sql_timestamp, SR_SQL_TIMESTAMP_FRACTION));
}
/* convert SQL_TIMESTAMP_STRUCT to Scheme sql-timestamp record */
s48_value struct_to_sql_timestamp_record(SQL_TIMESTAMP_STRUCT *ts)
{
s48_value sql_timestamp;
sql_timestamp = s48_make_record(sql_timestamp_record_type);
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_YEAR,
s48_extract_integer(ts->year));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_MONTH,
s48_extract_integer(ts->month));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_DAY,
s48_extract_integer(ts->day));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_HOUR,
s48_extract_integer(ts->hour));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_MINUTE,
s48_extract_integer(ts->minute));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_SECOND,
s48_extract_integer(ts->second));
S48_RECORD_SET(sql_timestamp, SR_SQL_TIMESTAMP_FRACTION,
s48_extract_integer(ts->fraction));
return sql_timestamp;
}
void s48_init_odbc(void)
{
/* PART 1 */
S48_EXPORT_FUNCTION(odbc_alloc_environment_handle);
S48_EXPORT_FUNCTION(odbc_alloc_connection_handle);
S48_EXPORT_FUNCTION(odbc_alloc_statement_handle);
S48_EXPORT_FUNCTION(odbc_sql_connect);
/* PART 2 */
/* S48_EXPORT_FUNCTION(odbc_sql_data_sources); */
/* S48_EXPORT_FUNCTION(odbc_sql_drivers); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_info_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_info_string); */
S48_EXPORT_FUNCTION(odbc_sql_get_func_exists);
/* S48_EXPORT_FUNCTION(odbc_sql_get_type_info); */
/* PART 3 */
/* S48_EXPORT_FUNCTION(odbc_sql_set_connect_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_set_connect_attr_string); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_connect_attr_string); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_connect_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_set_env_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_env_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_set_stmt_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_set_stmt_attr_string); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_stmt_attr_int); */
/* S48_EXPORT_FUNCTION(odbc_sql_get_stmt_attr_string); */
/* PART 4 */
/* PART 5 */
S48_EXPORT_FUNCTION(odbc_sql_prepare);
S48_EXPORT_FUNCTION(odbc_sql_bind_parameter_exec_out);
/* PART 6 */
S48_EXPORT_FUNCTION(odbc_sql_execute);
S48_EXPORT_FUNCTION(odbc_sql_execute_direct);
/* PART 7 */
S48_EXPORT_FUNCTION(odbc_sql_get_data);
S48_EXPORT_FUNCTION(odbc_sql_fetch);
S48_EXPORT_FUNCTION(odbc_sql_num_result_cols);
S48_EXPORT_FUNCTION(odbc_sql_describe_col);
/* PART 8 */
/* PART 9 */
S48_EXPORT_FUNCTION(odbc_sql_free_statement);
S48_EXPORT_FUNCTION(odbc_sql_close_cursor);
S48_EXPORT_FUNCTION(odbc_sql_cancel);
S48_EXPORT_FUNCTION(odbc_sql_endtran);
/* PART 10 */
S48_EXPORT_FUNCTION(odbc_sql_disconnect);
S48_EXPORT_FUNCTION(odbc_sql_free_handle);
}