1792 lines
38 KiB
C
1792 lines
38 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 server_name,
|
|
s48_value user_name,
|
|
s48_value authentication)
|
|
{
|
|
|
|
SQLHDBC ch;
|
|
SQLCHAR *server, *user, *auth;
|
|
SQLRETURN retval;
|
|
int server_len, user_len, auth_len;
|
|
|
|
ODBC_DEBUG_PRINTF("odbc_sql_connect\n");
|
|
|
|
server = (SQLCHAR *) s48_extract_string(server_name);
|
|
user = (SQLCHAR *) s48_extract_string(user_name);
|
|
auth = (SQLCHAR *) s48_extract_string(authentication);
|
|
|
|
server_len = S48_STRING_LENGTH(server_name);
|
|
user_len = S48_STRING_LENGTH(user_name);
|
|
auth_len = S48_STRING_LENGTH(authentication);
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(connection_handle);
|
|
|
|
retval = SQLConnect(ch,
|
|
server, server_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, s48_value direction)
|
|
{
|
|
|
|
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);
|
|
dir = (SQLUSMALLINT) s48_extract_integer(direction);
|
|
|
|
ODBC_DEBUG_PRINTF("odbc_sql_data_sources\n");
|
|
|
|
result = S48_NULL;
|
|
first = 1;
|
|
|
|
while (1) {
|
|
|
|
retval = SQLDataSources(eh,
|
|
(first ? dir : 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;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
/* bind parameters */
|
|
for (i = 1; i < S48_VECTOR_LENGTH(param_vals); 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;
|
|
|
|
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,
|
|
SQL_PARAM_OUTPUT,
|
|
value_type, param_type,
|
|
val_len, 0,
|
|
value, 0, (void *)SQL_NTS);
|
|
break;
|
|
}
|
|
case SQL_C_SSHORT:
|
|
case SQL_C_USHORT:
|
|
case SQL_C_SLONG:
|
|
case SQL_C_ULONG:
|
|
{
|
|
SQLINTEGER value;
|
|
SQLINTEGER cb_val;
|
|
|
|
cb_val = 0;
|
|
value = (SQLINTEGER)
|
|
s48_extract_integer(S48_CAR(S48_VECTOR_REF(param_vals, i)));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
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,
|
|
SQL_PARAM_OUTPUT,
|
|
value_type, param_type,
|
|
0, 0,
|
|
&value, 0, &cb_val);
|
|
break;
|
|
}
|
|
case SQL_C_FLOAT:
|
|
{
|
|
SQLREAL value;
|
|
SQLINTEGER cb_val;
|
|
|
|
cb_val = 0;
|
|
value = (SQLREAL)
|
|
S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i)));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
SQL_PARAM_OUTPUT,
|
|
value_type, param_type,
|
|
0, 0,
|
|
&value, 0, &cb_val);
|
|
break;
|
|
}
|
|
case SQL_C_DOUBLE:
|
|
{
|
|
SQLDOUBLE value;
|
|
SQLINTEGER cb_val;
|
|
|
|
cb_val = 0;
|
|
value = (SQLDOUBLE)
|
|
S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i)));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
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;
|
|
|
|
cb_val = 0;
|
|
value.year = (SQLSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_DATE_YEAR));
|
|
|
|
value.month = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_DATE_MONTH));
|
|
|
|
value.day = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_DATE_DAY));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
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;
|
|
|
|
cb_val = 0;
|
|
value.hour = (SQLSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIME_HOUR));
|
|
|
|
value.minute = (SQLSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIME_MINUTE));
|
|
|
|
value.second = (SQLSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIME_SECOND));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
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;
|
|
|
|
cb_val = 0;
|
|
value.year = (SQLSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_YEAR));
|
|
|
|
value.month = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_MONTH));
|
|
|
|
value.day = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_DAY));
|
|
|
|
value.hour = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_HOUR));
|
|
|
|
value.minute = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_MINUTE));
|
|
|
|
value.second = (SQLUSMALLINT)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_SECOND));
|
|
|
|
value.fraction = (SQLUINTEGER)
|
|
s48_extract_integer(S48_RECORD_REF(S48_CAR(S48_VECTOR_REF(param_vals, i)),
|
|
SR_SQL_TIMESTAMP_FRACTION));
|
|
|
|
retval = SQLBindParameter(sh, (SQLUSMALLINT) i,
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* 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 */
|
|
|
|
/* 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;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
* PART 7
|
|
*
|
|
* Retrieving results and information about results
|
|
*
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
* 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,
|
|
&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);
|
|
printf("native error msg: %s\n", (char *)native_error);
|
|
printf("error msg: %s\n", message);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
/* PART 6 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_execute);
|
|
|
|
/* PART 7 */
|
|
|
|
/* PART 8 */
|
|
|
|
/* PART 9 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_free_statement);
|
|
S48_EXPORT_FUNCTION(odbc_sql_close_cursor);
|
|
S48_EXPORT_FUNCTION(odbc_sql_cancel);
|
|
|
|
/* PART 10 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_disconnect);
|
|
S48_EXPORT_FUNCTION(odbc_sql_free_handle);
|
|
}
|
|
|