2241 lines
48 KiB
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);
|
|
}
|