3801 lines
93 KiB
C
3801 lines
93 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;
|
|
|
|
retval = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
|
|
ODBC_DEBUG_PRINTF_2("odbc_alloc_environment(): %x\n", henv);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
return s48_enter_integer(henv);
|
|
case SQL_ERROR:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocHandle returned SQL_ERROR");
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocHandle unknown return value");
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
|
|
retval = SQLSetEnvAttr(env_handle, SQL_ATTR_ODBC_VERSION,
|
|
(void *)SQL_OV_ODBC3, 0);
|
|
ODBC_DEBUG_PRINTF_2("odbc_set_environment() %x\n", env_handle);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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");
|
|
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;
|
|
|
|
envh = (SQLHENV) s48_extract_integer(env_handle);
|
|
|
|
retval = SQLAllocHandle(SQL_HANDLE_DBC, envh, &hdbc);
|
|
ODBC_DEBUG_PRINTF_3("odbc_alloc_connection_handle() %x %x\n", envh, hdbc);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer((long)hdbc);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
|
|
ch = (SQLHANDLE) s48_extract_integer(conn_handle);
|
|
retval = SQLAllocHandle(SQL_HANDLE_STMT, ch, &hstmt);
|
|
|
|
ODBC_DEBUG_PRINTF_3("odbc_alloc_statement_handle() %x %x\n", ch, hstmt);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer((long)hstmt);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* for ODBC 1.0 compatibility */
|
|
s48_value odbc_sql_alloc_env()
|
|
{
|
|
SQLRETURN retval;
|
|
SQLHENV eh;
|
|
|
|
ODBC_DEBUG_PRINTF("odbc_sql_alloc_env()\n");
|
|
|
|
retval = SQLAllocEnv(&eh);
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
return s48_enter_inteeger(eh);
|
|
case SQL_ERROR:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocHandle() returned SQL_ERROR");
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocHandle() returned unknown error code");
|
|
}
|
|
}
|
|
|
|
s48_value odbc_sql_alloc_connect(s48_value env_handle)
|
|
{
|
|
SQLRETURN retval;
|
|
SQLHENV eh;
|
|
SQLHDBC ch;
|
|
|
|
eh = (SQLHENV) s48_extract_integer(env_handle);
|
|
ODBC_DEBUG_PRINTF("odbc_sql_alloc_connect(): eh:%d\n");
|
|
|
|
retval = SQLAllocConnect(ch, &eh);
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
return s48_enter_integer(ch);
|
|
case SQL_ERROR:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocConnect returned SQL_ERROR");
|
|
case SQL_INVALID_HANDLE:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocConnect got invalid handle");
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocConnect returned unknown error");
|
|
}
|
|
}
|
|
|
|
s48_value odbc_sql_alloc_stmt(s48_value conn_handle)
|
|
{
|
|
SQLRETURN retval;
|
|
SQLHDBC ch;
|
|
SQLHSTMT sh;
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
|
ODBC_DEBUG_PRINTF("odbc_sql_alloc_stmt(): ch:%d\n");
|
|
|
|
retval = SQLAllocStmt(ch, &eh);
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
return s48_enter_integer(eh);
|
|
case SQL_ERROR:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocStmt returned SQL_ERROR");
|
|
case SQL_INVALID_HANDLE:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocStmt got invalid handle");
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("SQLAllocStmt returned unknown error code");
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
|
|
dsn = (SQLCHAR *) s48_extract_string(ds_name);
|
|
user = (SQLCHAR *) s48_extract_string(user_name);
|
|
auth = (SQLCHAR *) s48_extract_string(authentication);
|
|
ch = (SQLHDBC) s48_extract_integer(connection_handle);
|
|
|
|
ODBC_DEBUG_PRINTF_5("odbc_sql_connect() %x '%s' '%s' '%s'\n",
|
|
ch, dsn, user,auth);
|
|
retval = SQLConnect(ch,
|
|
dsn, SQL_NTS,
|
|
user, SQL_NTS,
|
|
auth, SQL_NTS);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
s48_value odbc_sql_browse_connect(s48_value conn_handle, s48_value conn_string)
|
|
{
|
|
SQLHDBC ch;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLRETURN retval;
|
|
SQLSMALLINT buffer_needed, buffer_len;
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
|
ODBC_DEBUG_PRINTF_3("odbc_sql_browse_connect() %x '%s'\n", ch, s48_extract_string(conn_string));
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
|
|
retval = SQLBrowseConnect(ch, (SQLCHAR *) s48_extract_string(conn_string),
|
|
(SQLSMALLINT) S48_STRING_LENGTH(conn_string),
|
|
buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBrowseConnect returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBrowseConnect got invalid handle");
|
|
break;
|
|
}
|
|
case SQL_NEED_DATA:
|
|
{
|
|
return s48_enter_integer(SQL_NEED_DATA);
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBrowseConnect returned 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, *driver_descr;
|
|
SQLSMALLINT server_name_len, driver_descr_len;
|
|
SQLSMALLINT server_name_needed, driver_descr_needed;
|
|
s48_value result = S48_UNSPECIFIC;
|
|
int first, more_items;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(result);
|
|
|
|
eh = (SQLHENV) s48_extract_integer(env_handle);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_data_sources\n");
|
|
|
|
server_name_len = driver_descr_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
server_name = (SQLCHAR *) calloc(server_name_len, sizeof(SQLCHAR));
|
|
driver_descr = (SQLCHAR *) calloc(driver_descr_len, sizeof(SQLCHAR));
|
|
|
|
if ((server_name == NULL) || (driver_descr == NULL))
|
|
{
|
|
ODBC_RAISE_EXCEPTION("Could not allocate memory for return values");
|
|
return S48_UNSPECIFIC;
|
|
}
|
|
|
|
redo_loop:
|
|
ODBC_DEBUG_PRINTF_1("redo_loop\n");
|
|
result = S48_NULL;
|
|
first = more_items = 1;
|
|
|
|
while (more_items) {
|
|
|
|
retval = SQLDataSources(eh,
|
|
(first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT),
|
|
server_name, sizeof(SQLCHAR)*server_name_len, &server_name_needed,
|
|
driver_descr, sizeof(SQLCHAR)*driver_descr_len, &driver_descr_needed);
|
|
|
|
if (ODBC_SUCCESS(retval))
|
|
{
|
|
int redo_call = 0;
|
|
|
|
if (server_name_needed > server_name_len)
|
|
{
|
|
ODBC_DEBUG_PRINTF_2("realloc() server_name %d\n", server_name_needed);
|
|
server_name_len = server_name_needed+1;
|
|
server_name = (SQLCHAR *) realloc(server_name, (size_t) server_name_len);
|
|
redo_call = 1;
|
|
}
|
|
if (driver_descr_needed > driver_descr_len)
|
|
{
|
|
ODBC_DEBUG_PRINTF_2("realloc() driver_descr %d\n", driver_descr_needed+1);
|
|
driver_descr_len = driver_descr_needed+1;
|
|
driver_descr = (SQLCHAR *) realloc(driver_descr, (size_t) driver_descr_len);
|
|
redo_call = 1;
|
|
}
|
|
|
|
if ((server_name == NULL) || (driver_descr == NULL))
|
|
{
|
|
ODBC_RAISE_EXCEPTION("Could not allocate memory for return values");
|
|
return S48_UNSPECIFIC;
|
|
}
|
|
|
|
if (redo_call) goto redo_loop;
|
|
}
|
|
|
|
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);
|
|
break;
|
|
}
|
|
case SQL_NO_DATA:
|
|
{
|
|
more_items = 0;
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDataSources returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDataSources got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDataSources returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
free(server_name);
|
|
free(driver_descr);
|
|
|
|
S48_GC_UNPROTECT();
|
|
return result;
|
|
}
|
|
|
|
/* 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 = S48_UNSPECIFIC;
|
|
int first, more_items;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(result);
|
|
|
|
eh = (SQLHENV) s48_extract_integer(env_handle);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_drivers\n");
|
|
result = S48_NULL;
|
|
first = more_items = 0;
|
|
|
|
while (more_items) {
|
|
|
|
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);
|
|
break;
|
|
}
|
|
case SQL_NO_DATA:
|
|
{
|
|
more_items = 0;
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDrivers returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDrivers got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDrivers returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
S48_GC_UNPROTECT();
|
|
return result;
|
|
}
|
|
|
|
/* 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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(info);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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 *buffer = NULL;
|
|
SQLSMALLINT buffer_needed, buffer_len;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_info_string\n");
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
|
ik = (SQLUSMALLINT) s48_extract_integer(info_key);
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
|
|
retval = SQLGetInfo(ch, ik, buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return SQL_FUNC_EXISTS(supported, fi) == SQL_TRUE ? S48_TRUE : S48_FALSE;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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 = NULL;
|
|
SQLINTEGER buffer_needed, buffer_len;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_connect_attr_string\n");
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
|
|
for (;;) {
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
|
|
retval = SQLGetConnectAttr(ch, attr, buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_needed = buffer_len;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("odbc_sql_get_connect_attr_int\n");
|
|
|
|
retval = SQLGetConnectAttr(ch, attr,
|
|
&buffer, sizeof(SQLUINTEGER), &buffer_size);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(buffer);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(val);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(val);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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, buffer_len, buffer_needed;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_stmt_attr_string\n");
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLGetStmtAttr(sh, attr, &buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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
|
|
*
|
|
*/
|
|
|
|
/* Returns the value of a single descriptor field (for integers) */
|
|
s48_value odbc_sql_get_desc_field_int(s48_value desc_handle, s48_value rec_number,
|
|
s48_value field_id)
|
|
{
|
|
SQLHDESC dh;
|
|
SQLSMALLINT rn, fi;
|
|
SQLINTEGER value, buffer_len;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_desc_field_int\n");
|
|
|
|
dh = (SQLHDESC) s48_extract_integer(desc_handle);
|
|
rn = (SQLSMALLINT) s48_extract_integer(rec_number);
|
|
fi = (SQLSMALLINT) s48_extract_integer(field_id);
|
|
|
|
retval = SQLGetDescField(dh, rn, fi, (SQLPOINTER) &value,
|
|
sizeof(SQLINTEGER), &buffer_len);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
switch (buffer_len)
|
|
{
|
|
case SQL_IS_INTEGER:
|
|
return s48_enter_integer((SQLINTEGER) value);
|
|
case SQL_IS_UINTEGER:
|
|
return s48_enter_integer((SQLUINTEGER) value);
|
|
case SQL_IS_SMALLINT:
|
|
return s48_enter_integer((SQLSMALLINT) value);
|
|
case SQL_IS_USMALLINT:
|
|
return s48_enter_integer((SQLUSMALLINT) value);
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField returned unknown integer type");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
case SQL_NO_DATA:
|
|
{
|
|
return S48_FALSE;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the value of a single descriptor field (for strings/binary data) */
|
|
s48_value odbc_sql_get_desc_field_string(s48_value desc_handle, s48_value rec_number,
|
|
s48_value field_id)
|
|
{
|
|
SQLHDESC dh;
|
|
SQLSMALLINT rn, fi;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLINTEGER buffer_len, buffer_needed;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_desc_field_string\n");
|
|
|
|
dh = (SQLHDESC) s48_extract_integer(desc_handle);
|
|
rn = (SQLSMALLINT) s48_extract_integer(rec_number);
|
|
fi = (SQLSMALLINT) s48_extract_integer(field_id);
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLGetDescField(dh, rn, fi, (SQLPOINTER) buffer,
|
|
buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
case SQL_NO_DATA:
|
|
{
|
|
return S48_FALSE;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDescField returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
* 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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLPrepare got invalid handle");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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_2("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_1("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_1("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_1("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_1("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_1("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_1("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_1("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_1("All parameters bound\n");
|
|
|
|
/* check the return value of SQLBindParameter */
|
|
if ((retval != SQL_SUCCESS) || (retval != SQL_SUCCESS_WITH_INFO)) {
|
|
switch (retval)
|
|
{
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBindParameter returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBindParameter got invalid handle");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} /* for */
|
|
|
|
ODBC_DEBUG_PRINTF_1("Executing statement\n");
|
|
|
|
/* execute statement */
|
|
|
|
retval = SQLExecute(sh);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
s48_value odbc_sql_get_cursor_name(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLRETURN retval;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLSMALLINT buffer_len, buffer_needed;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_cursor_name\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLGetCursorName(sh, buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(buffer);
|
|
free(buffer);
|
|
return s48_enter_string(buffer);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetCursorName returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetCursorName got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetCursorName returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void odbc_sql_set_cursor_name(s48_value stmt_handle, s48_value cursorname)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *cn;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_set_cursor_name\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLCHAR *) s48_extract_string(cursorname);
|
|
|
|
retval = SQLSetCursorName(sh, cn, S48_STRING_LENGTH(cursorname));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetCursorName returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetCursorName got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetCursorName 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_1("odbc_sql_execute\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
retval = SQLExecute(sh);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NEED_DATA: case SQL_NO_DATA:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_STILL_EXECUTING, not implemented yet");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLExecDirect got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLExecDirect returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the text of an SQL statement as translated by the driver. */
|
|
s48_value odbc_sql_native_sql(s48_value conn_handle, s48_value stmt_txt)
|
|
{
|
|
SQLHDBC ch;
|
|
SQLCHAR *stmt_in, *stmt_out = NULL;
|
|
SQLINTEGER buffer_len, buffer_needed;
|
|
SQLRETURN retval;
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
|
stmt_in = (SQLCHAR *) s48_extract_string(stmt_txt);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_native_sql\n");
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &stmt_out, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLNativeSql(ch, stmt_in, S48_STRING_LENGTH(stmt_txt),
|
|
stmt_out, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && buffer_needed > buffer_len)
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
s48_value res = s48_enter_string(stmt_out);
|
|
free(stmt_out);
|
|
return res;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNativeSql returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNativeSql got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNativeSql returned unknoen error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the description for a specific parameter in a statement */
|
|
s48_value odbc_sql_describe_param(s48_value stmt_handle, s48_value parameter_no)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT pn;
|
|
SQLUINTEGER ps;
|
|
SQLSMALLINT dt, dd, n;
|
|
SQLRETURN retval;
|
|
s48_value result = S48_UNSPECIFIC;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(result);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_describe_param\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
pn = (SQLUSMALLINT) s48_extract_integer(parameter_no);
|
|
|
|
retval = SQLDescribeParam(sh, pn, &dt, &ps, &dd, &n);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
result = s48_make_record(odbc_parameter_record_type);
|
|
S48_RECORD_SET(result, SR_ODBC_PARAMETER_TYPE, s48_enter_integer(dt));
|
|
S48_RECORD_SET(result, SR_ODBC_PARAMETER_SIZE, s48_enter_integer(ps));
|
|
S48_RECORD_SET(result, SR_ODBC_PARAMETER_DIGITS, s48_enter_integer(dd));
|
|
S48_RECORD_SET(result, SR_ODBC_PARAMETER_NULLABLE, s48_enter_integer(n));
|
|
return result;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDescribeParam returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDescribeParam got invalid handle");
|
|
break;
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDescribeParam returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDescribeParam returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the number of parameters in a statement */
|
|
s48_value odbc_sql_num_params(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLSMALLINT params;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_num_params\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
retval = SQLNumParams(sh, ¶ms);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(params);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNumParams returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNumParams returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNumParams got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLNumParams returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
* PART 7
|
|
*
|
|
* Retrieving results and information about results
|
|
*
|
|
*/
|
|
|
|
s48_value odbc_sql_row_count(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLRETURN retval;
|
|
SQLINTEGER rowcount;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_row_count\n");
|
|
|
|
retval = SQLRowCount(sh, &rowcount);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(rowcount);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLRowCount returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLRowCount got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLRowCount returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
s48_value odbc_sql_get_data(s48_value stmt_handle, s48_value column_number,
|
|
s48_value target_type, s48_value buffer_size)
|
|
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT cn, bl;
|
|
SQLSMALLINT tt;
|
|
SQLRETURN retval;
|
|
SQLINTEGER buffer_needed;
|
|
void *buffer = NULL;
|
|
s48_value result = S48_UNSPECIFIC;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLUSMALLINT) s48_extract_integer(column_number);
|
|
tt = (SQLSMALLINT) s48_extract_integer(target_type);
|
|
bl = (SQLUSMALLINT) s48_extract_integer(buffer_size);
|
|
|
|
ODBC_DEBUG_PRINTF_5("odbc_sql_get_data() sh:%x cn:%d tt:%d bl:%d\n", sh, cn, tt, bl);
|
|
|
|
odbc_sql_alloc((void **) &buffer, buffer_size, sizeof_sql_c_type_identifier(tt));
|
|
retval = SQLGetData(sh, cn, tt, buffer, buffer_size, &buffer_needed);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
S48_GC_PROTECT_1(result);
|
|
result = s48_cons(buffer_to_s48_value(buffer, tt),
|
|
s48_enter_integer(buffer_needed));
|
|
free(buffer);
|
|
S48_GC_UNPROTECT();
|
|
return result;
|
|
}
|
|
case SQL_NO_DATA:
|
|
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_NO_DATA");
|
|
case SQL_STILL_EXECUTING:
|
|
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_STILL_EXECUTING, not yet implemented");
|
|
case SQL_ERROR:
|
|
ODBC_RAISE_EXCEPTION("SQLGetData returned SQL_ERROR");
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("SQLGetData returned unknown error code");
|
|
}
|
|
}
|
|
|
|
/* Positions a cursor within a fetched block of data and allows an application
|
|
to refresh data in the rowset or to update or delete data in the result
|
|
set */
|
|
s48_value odbc_sql_set_pos(s48_value stmt_handle, s48_value row_number,
|
|
s48_value operation, s48_value lock_type)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT rn, op, lt;
|
|
SQLRETURN retval;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
rn = (SQLUSMALLINT) s48_extract_integer(row_number);
|
|
op = (SQLUSMALLINT) s48_extract_integer(operation);
|
|
lt = (SQLUSMALLINT) s48_extract_integer(lock_type);
|
|
|
|
ODBC_DEBUG_PRINTF_5("odbc_sql_set_pos() sh:%x rn:%d op:%d lt:%d\n", sh, rn, op, lt);
|
|
|
|
retval = SQLSetPos(sh, rn, op, lt);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NEED_DATA:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetPos returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetPos returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetPos got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSetPos returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Performs bulk insertions and bulk bookmark operations, including
|
|
update, delete, and fetch by bookmark. */
|
|
s48_value odbc_sql_bulk_operations(s48_value stmt_handle, s48_value operation)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT op;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_bulk_operations\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
op = (SQLUSMALLINT) s48_extract_integer(operation);
|
|
|
|
retval = SQLBulkOperations(sh, op);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NEED_DATA:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBulkOperations returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBulkOperations returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBulkOperations got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBulkOperations returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Determines whether there are more result sets available and, if so,
|
|
initializes processing for the next result set */
|
|
s48_value odbc_sql_more_results(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_more_results\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
retval = SQLMoreResults(sh);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLMoreResults returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLMoreResults returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLMoreResults got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLMoreResults returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
s48_value odbc_sql_fetch(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLRETURN retval;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
ODBC_DEBUG_PRINTF_2("odbc_sql_fetch() %x\n", sh);
|
|
|
|
retval = SQLFetch(sh);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
case SQL_NO_DATA:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLFetch returned SQL_STILL_EXECUTING, not yet implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_num_result_cols\n");
|
|
|
|
retval = SQLNumResultCols(sh, &numcols);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
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_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 *buffer = NULL;
|
|
SQLSMALLINT buffer_len, buffer_needed, data_type, digits, nullable;
|
|
SQLUINTEGER col_size;
|
|
SQLRETURN retval;
|
|
s48_value col_rec = S48_UNSPECIFIC;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(col_rec);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_describe_col\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLSMALLINT) s48_extract_integer(column_number);
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLDescribeCol(sh, cn,
|
|
buffer, buffer_len, &buffer_needed,
|
|
&data_type, &col_size, &digits,
|
|
&nullable);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
col_rec = s48_make_record(odbc_column_record_type);
|
|
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_NAME,
|
|
s48_enter_string(buffer));
|
|
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));
|
|
|
|
S48_GC_UNPROTECT();
|
|
free(buffer);
|
|
return col_rec;
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLDescribeCol returned SQL_STILL_EXECUTING, not yet implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Describes attributes of a column in the result set */
|
|
s48_value odbc_sql_col_attribute(s48_value stmt_handle, s48_value column_number,
|
|
s48_value field_id)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT cn, fi;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLSMALLINT buffer_len, buffer_needed;
|
|
SQLINTEGER intbuffer;
|
|
SQLRETURN retval;
|
|
s48_value res_string, res;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(res);
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_col_attribute\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLUSMALLINT) s48_extract_integer(column_number);
|
|
fi = (SQLUSMALLINT) s48_extract_integer(field_id);
|
|
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
|
|
retval = SQLColAttribute(sh, cn, fi,
|
|
buffer, buffer_len, &buffer_needed,
|
|
&intbuffer);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
res = s48_cons(s48_enter_string(buffer), s48_enter_integer(intbuffer));
|
|
free(buffer);
|
|
S48_GC_UNPROTECT();
|
|
return res;
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColAttribute returned SQL_STILL_EXECUTING. Not implemented yet.");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColAttribute returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColAttribute got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColAttribute returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ColumnRecPtr bindcol_lookup_binding(SQLHSTMT stmt_handle, SQLUSMALLINT column_no)
|
|
{
|
|
StmtRecPtr stmt;
|
|
ColumnRecPtr col;
|
|
|
|
ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding() %x %d\n", stmt_handle, column_no);
|
|
stmt = global_bindcol_list;
|
|
|
|
while (stmt != NULL)
|
|
{
|
|
if (stmt->stmt_handle == stmt_handle)
|
|
{
|
|
col = stmt->col_recs;
|
|
while ((col != NULL) && (col->col_no != column_no))
|
|
col = col->next;
|
|
return col;
|
|
}
|
|
col = col->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
s48_value bindcol_lookup_binding_scheme(s48_value stmt_handle, s48_value column_no)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT cn;
|
|
ColumnRecPtr col;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLUSMALLINT) s48_extract_integer(column_no);
|
|
|
|
ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding_scheme() sh:%x cn:%d\n", sh, cn);
|
|
col = bindcol_lookup_binding(sh, cn);
|
|
|
|
if (col == NULL)
|
|
s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2,
|
|
stmt_handle, column_no);
|
|
else
|
|
{
|
|
ODBC_DEBUG_PRINTF_2("bindcol_lookup_binding_scheme(): col_buf:%x\n", col->col_buffer);
|
|
return buffer_to_s48_value(col->col_buffer, col->target_type);
|
|
}
|
|
}
|
|
|
|
/* Semantics differs from original SQLBindCol(), due to the need of
|
|
bookkeeping a target buffer list in C. odbc_sql_bindcol() handles
|
|
column binding and rebinding, but not unbinding. To unbind a column
|
|
use bindcol_unbind_column() or bindcol_finalize_bindcols(). */
|
|
s48_value odbc_sql_bindcol(s48_value stmt_handle, s48_value column_no,
|
|
s48_value target_type, s48_value buffer_len)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLUSMALLINT cn;
|
|
SQLSMALLINT tt;
|
|
SQLLEN bl;
|
|
SQLRETURN retval;
|
|
ColumnRecPtr col = NULL;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
cn = (SQLUSMALLINT) s48_extract_integer(column_no);
|
|
tt = (SQLSMALLINT) s48_extract_integer(target_type);
|
|
bl = (SQLLEN) s48_extract_integer(buffer_len);
|
|
|
|
ODBC_DEBUG_PRINTF_5("odbc_sql_bindcol() %x %d %d %d\n", sh, cn, tt, bl);
|
|
|
|
/* try to look up ColumRec */
|
|
col = bindcol_lookup_binding(sh, cn);
|
|
|
|
if (col == NULL)
|
|
{
|
|
/* There is no binding for this stmt-handle/column-no yet */
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_bindcol(): new binding\n");
|
|
col = (ColumnRec *) malloc(sizeof(ColumnRec));
|
|
if (col == NULL)
|
|
ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer");
|
|
|
|
/* initialize it */
|
|
col->col_no = cn;
|
|
col->target_type = tt;
|
|
col->buffer_len = bl;
|
|
col->buffer_needed = 0;
|
|
col->next = NULL;
|
|
|
|
col->col_buffer = (void *) malloc(sizeof_sql_c_type_identifier(tt)*bl);
|
|
ODBC_DEBUG_PRINTF_3("odbc_sql_bindcol() malloc %x %d\n",
|
|
col->col_buffer, sizeof_sql_c_type_identifier(tt)*bl);
|
|
if (col->col_buffer == NULL)
|
|
ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer");
|
|
|
|
/* store col in global_bindcol_list */
|
|
bindcol_bind_column(sh, cn, col);
|
|
}
|
|
else
|
|
{
|
|
/* user wishes to rebind column for whatever reason */
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_bindcol(): rebinding existing binding\n");
|
|
|
|
if (tt != col->target_type)
|
|
ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): While rebinding buffers: old/new target type do not match");
|
|
|
|
/* free the old buffer, allocate a new one */
|
|
free(col->col_buffer);
|
|
col->col_buffer = (void *) malloc(sizeof_sql_c_type_identifier(tt)*bl);
|
|
col->buffer_len = sizeof_sql_c_type_identifier(tt)*bl;
|
|
ODBC_DEBUG_PRINTF_3("odbc_sql_bindcol() reallocate %x %d\n", col->col_buffer,
|
|
sizeof_sql_c_type_identifier(tt)*bl);
|
|
if (col->col_buffer == NULL)
|
|
ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer");
|
|
}
|
|
|
|
/* at this point ColumRecPtr col has been created or updated, call SQLBindCol() */
|
|
retval = SQLBindCol(sh, cn, tt, col->col_buffer, col->buffer_len, &col->buffer_needed);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return S48_UNSPECIFIC;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBindCol returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBindCol got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLBindCol returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bindcol_bind_column(SQLHSTMT stmt_handle, SQLUSMALLINT column_no, ColumnRecPtr new_col)
|
|
{
|
|
StmtRecPtr stmt, prev_stmt, new_stmt;
|
|
ColumnRecPtr col, prev_col;
|
|
|
|
ODBC_DEBUG_PRINTF_4("bindcol_bind_column() %x %d %x\n", stmt_handle, column_no, new_col);
|
|
prev_stmt = stmt = global_bindcol_list;
|
|
while (stmt != NULL)
|
|
{
|
|
if (stmt->stmt_handle == stmt_handle)
|
|
{
|
|
prev_col = col = stmt->col_recs;
|
|
while ((col != NULL) && (col->col_no != column_no))
|
|
{
|
|
prev_col = col;
|
|
col = col->next;
|
|
}
|
|
if (col == NULL)
|
|
{
|
|
prev_col->next = new_col;
|
|
return;
|
|
}
|
|
}
|
|
prev_stmt = stmt;
|
|
stmt = stmt->next;
|
|
}
|
|
if (stmt == NULL)
|
|
{
|
|
ODBC_DEBUG_PRINTF_1("bindcol_bind_column() global_bindcol_list is empty\n");
|
|
new_stmt = (StmtRecPtr) malloc(sizeof(StmtRec));
|
|
if (new_stmt == NULL)
|
|
ODBC_RAISE_EXCEPTION("bindcol_bind_column(): Error allocating memory");
|
|
new_stmt->next = NULL;
|
|
new_stmt->stmt_handle = stmt_handle;
|
|
new_stmt->col_recs = new_col;
|
|
if (global_bindcol_list == NULL)
|
|
global_bindcol_list = new_stmt;
|
|
else
|
|
prev_stmt->next = new_stmt;
|
|
}
|
|
}
|
|
|
|
void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no)
|
|
{
|
|
StmtRecPtr stmt, prev_stmt;
|
|
ColumnRecPtr col, prev_col;
|
|
|
|
ODBC_DEBUG_PRINTF_3("bindcol_unbind_colum() %x %d\n", stmt_handle, column_no);
|
|
|
|
prev_stmt = stmt = global_bindcol_list;
|
|
while (stmt != NULL)
|
|
{
|
|
if (stmt->stmt_handle == stmt_handle)
|
|
{
|
|
prev_col = col = stmt->col_recs;
|
|
while ((col != NULL) && (col->col_no != column_no))
|
|
{
|
|
prev_col = col;
|
|
col = col->next;
|
|
}
|
|
if (col == NULL)
|
|
s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no);
|
|
ODBC_DEBUG_PRINTF_2("bindcol_unbind_colum() free %x\n", col->col_buffer);
|
|
free(col->col_buffer);
|
|
prev_col->next = col->next;
|
|
free(col);
|
|
if (stmt->col_recs == NULL)
|
|
{
|
|
prev_stmt->next = stmt->next;
|
|
free(stmt);
|
|
}
|
|
return;
|
|
}
|
|
prev_stmt = stmt;
|
|
stmt = stmt->next;
|
|
}
|
|
s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2,
|
|
s48_enter_integer((SQLHSTMT) stmt_handle), s48_enter_integer(column_no));
|
|
}
|
|
|
|
s48_value bindcol_finalize_bindcols(s48_value stmt_handle)
|
|
{
|
|
SQLHSTMT sh;
|
|
StmtRecPtr stmt, prev_stmt;
|
|
ColumnRecPtr col, prev_col, first_col;
|
|
SQLRETURN retval;
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
ODBC_DEBUG_PRINTF_2("bindcol_finalize_bindcols() %x\n", sh);
|
|
|
|
prev_stmt = stmt = global_bindcol_list;
|
|
while (stmt != NULL)
|
|
{
|
|
if (stmt->stmt_handle == sh)
|
|
{
|
|
/* a rather dumb approach... */
|
|
first_col = stmt->col_recs;
|
|
while (first_col != NULL)
|
|
{
|
|
col = first_col;
|
|
while (col != NULL)
|
|
{
|
|
if (col->next == NULL)
|
|
{
|
|
/* this bindcol_rec is the last in chain */
|
|
SQLLEN dummy;
|
|
|
|
retval = SQLBindCol(sh, col->col_no, col->target_type,
|
|
NULL, 0, &dummy);
|
|
free(col->col_buffer);
|
|
free(col);
|
|
prev_col->next = NULL;
|
|
}
|
|
prev_col = col;
|
|
col = col->next;
|
|
}
|
|
}
|
|
}
|
|
stmt = stmt->next;
|
|
}
|
|
return S48_UNSPECIFIC;
|
|
}
|
|
|
|
/*
|
|
*
|
|
* PART 8
|
|
*
|
|
* Obtaining information about the data source's
|
|
* system tables (catalog functxbions)
|
|
*
|
|
*/
|
|
|
|
/* Returns a list of columns and associated privileges for one or more tables */
|
|
s48_value odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name,
|
|
s48_value column_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table, *column;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_column_privileges\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
column = (SQLCHAR *) s48_extract_string(column_name);
|
|
|
|
retval = SQLColumnPrivileges(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name),
|
|
column, S48_STRING_LENGTH(column_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumnPrivileges returned SQL_STILL_EXECUTING. Not implemented yet");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumnPrivileges returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumnPrivileges got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumnPrivileges returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the list of column names in a specified table */
|
|
s48_value odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name,
|
|
s48_value column_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table, *column;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_columns\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
column = (SQLCHAR *) s48_extract_string(column_name);
|
|
|
|
retval = SQLColumns(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name),
|
|
column, S48_STRING_LENGTH(column_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumns returned SQL_STILL_EXECUTING. Not implemented yet");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumns returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumns got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLColumns returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns a list of columns names that make up foreign keys,
|
|
if the exist for a specified table */
|
|
s48_value odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name,
|
|
s48_value pk_schema_name, s48_value pk_table_name,
|
|
s48_value fk_catalog_name, s48_value fk_schema_name,
|
|
s48_value fk_table_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *pk_catalog, *pk_schema, *pk_table;
|
|
SQLCHAR *fk_catalog, *fk_schema, *fk_table;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_foreign_keys\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
pk_catalog = (SQLCHAR *) s48_extract_string(pk_catalog_name);
|
|
pk_schema = (SQLCHAR *) s48_extract_string(pk_schema_name);
|
|
pk_table = (SQLCHAR *) s48_extract_string(pk_table_name);
|
|
fk_catalog = (SQLCHAR *) s48_extract_string(fk_catalog_name);
|
|
fk_schema = (SQLCHAR *) s48_extract_string(fk_schema_name);
|
|
fk_table = (SQLCHAR *) s48_extract_string(fk_table_name);
|
|
|
|
retval = SQLForeignKeys(sh,
|
|
pk_catalog, S48_STRING_LENGTH(pk_catalog_name),
|
|
pk_schema, S48_STRING_LENGTH(pk_schema_name),
|
|
pk_table, S48_STRING_LENGTH(pk_table_name),
|
|
fk_catalog, S48_STRING_LENGTH(fk_catalog_name),
|
|
fk_schema, S48_STRING_LENGTH(fk_schema_name),
|
|
fk_table, S48_STRING_LENGTH(fk_table_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLForeignKeys returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLForeignKeys returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLForeignKeys got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLForeignKeys returned unknwon error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the list of column names that make up the primary key for a table */
|
|
s48_value odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_primary_keys\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
|
|
retval = SQLPrimaryKeys(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLPrimaryKeys returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLPrimaryKeys returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLPrimaryKeys got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLPrimaryKeys returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the list of input and output parameters, as well as the columns
|
|
that make up the result set for the specified procedures */
|
|
s48_value odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value proc_name,
|
|
s48_value column_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *proc, *column;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_procedure_columns\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
proc = (SQLCHAR *) s48_extract_string(proc_name);
|
|
column = (SQLCHAR *) s48_extract_string(column_name);
|
|
|
|
retval = SQLProcedureColumns(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
proc, S48_STRING_LENGTH(proc_name),
|
|
column, S48_STRING_LENGTH(column_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedureColumns returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedureColumns returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedureColumns got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedureColumns return unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the list of procedure names stored in a specific data source. */
|
|
s48_value odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value proc_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *proc;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_procedures\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
proc = (SQLCHAR *) s48_extract_string(proc_name);
|
|
|
|
retval = SQLProcedures(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
proc, S48_STRING_LENGTH(proc_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedures returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedures returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedures got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLProcedures returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns information about the optimal set of columns that uniquely identifies
|
|
a row in a specified table, or the columns that are automatically updated
|
|
when any value in the row is updated by a transaction */
|
|
s48_value odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type,
|
|
s48_value catalog_name, s48_value schema_name,
|
|
s48_value table_name, s48_value scope,
|
|
s48_value nullable)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table;
|
|
SQLSMALLINT s, n, it;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_special_columns\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
it = (SQLSMALLINT) s48_extract_integer(identifier_type);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
s = (SQLSMALLINT) s48_extract_integer(scope);
|
|
n = (SQLSMALLINT) s48_extract_integer(nullable);
|
|
|
|
retval = SQLSpecialColumns(sh, it,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name),
|
|
s, n);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSpecialColumns returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSpecialColumns returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSpecialColumns got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLSpecialColumns returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns statistics about a single table and the list of indexes associated
|
|
with the table */
|
|
s48_value odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name,
|
|
s48_value unique, s48_value reserved)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table;
|
|
SQLSMALLINT u, r;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_statistics\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
u = (SQLSMALLINT) s48_extract_integer(unique);
|
|
r = (SQLSMALLINT) s48_extract_integer(reserved);
|
|
|
|
retval = SQLStatistics(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name),
|
|
u, r);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLStatistics returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLStatistics returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLStatistics got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLStatistics returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns a list of tables and the privileges associated with each table */
|
|
s48_value odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *table;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_table_privileges\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
catalog = (SQLCHAR *) s48_extract_string(catalog_name);
|
|
schema = (SQLCHAR *) s48_extract_string(schema_name);
|
|
table = (SQLCHAR *) s48_extract_string(table_name);
|
|
|
|
retval = SQLTablePrivileges(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
table, S48_STRING_LENGTH(table_name));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTablePrivileges returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTablePrivileges returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTablePrivileges got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTablePrivileges returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Returns the list of table names stored in a specific data source */
|
|
s48_value odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name,
|
|
s48_value schema_name, s48_value table_name,
|
|
s48_value table_type)
|
|
{
|
|
SQLHSTMT sh;
|
|
SQLCHAR *catalog, *schema, *tablen, *tablet;
|
|
SQLRETURN retval;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_tables\n");
|
|
|
|
retval = SQLTables(sh,
|
|
catalog, S48_STRING_LENGTH(catalog_name),
|
|
schema, S48_STRING_LENGTH(schema_name),
|
|
tablen, S48_STRING_LENGTH(table_name),
|
|
tablet, S48_STRING_LENGTH(table_type));
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_STILL_EXECUTING:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTables returned SQL_STILL_EXECUTING. Not implemented");
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTables returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTables got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLTables returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
* 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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("odbc_sql_close_cursor\n");
|
|
|
|
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
|
retval = SQLCloseCursor(sh);
|
|
|
|
switch (retval) {
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("odbc_sql_cancel\n");
|
|
|
|
retval = SQLCancel(sh);
|
|
|
|
switch (retval) {
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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_1("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: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
|
|
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
|
ODBC_DEBUG_PRINTF_2("odbc_sql_disconnect() %x\n", ch);
|
|
|
|
retval = SQLDisconnect(ch);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
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;
|
|
|
|
ht = (SQLSMALLINT) s48_extract_integer(handle_type);
|
|
h = (SQLHANDLE) s48_extract_integer(handle);
|
|
|
|
ODBC_DEBUG_PRINTF_3("odbc_sql_free_handle() %x %d\n", h, ht);
|
|
retval = SQLFreeHandle(ht, h);
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS:
|
|
{
|
|
return s48_enter_integer(retval);
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLFreeHandle returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLFreeHandle got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLFreeHandle returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
* PART 11
|
|
*
|
|
* misc. functions
|
|
*
|
|
*/
|
|
|
|
s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle)
|
|
{
|
|
SQLSMALLINT ht;
|
|
SQLHANDLE h;
|
|
SQLCHAR sql_state[6];
|
|
SQLINTEGER native_error;
|
|
SQLCHAR *buffer = NULL;
|
|
SQLSMALLINT i, more_recs, buffer_len, buffer_needed;
|
|
SQLRETURN retval;
|
|
s48_value res = S48_UNSPECIFIC;
|
|
s48_value diag_rec = S48_UNSPECIFIC;
|
|
|
|
S48_DECLARE_GC_PROTECT(2);
|
|
S48_GC_PROTECT_2(res, diag_rec);
|
|
|
|
ht = (SQLSMALLINT) s48_extract_integer(handle_type);
|
|
h = (SQLHANDLE) s48_extract_integer(handle);
|
|
res = S48_NULL;
|
|
|
|
ODBC_DEBUG_PRINTF_1("odbc_sql_get_diag_recs\n");
|
|
|
|
i = more_recs = 1;
|
|
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
|
while (more_recs) {
|
|
|
|
diag_rec = s48_make_record(odbc_diag_record_type);
|
|
|
|
for (;;)
|
|
{
|
|
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
|
retval = SQLGetDiagRec(ht, h, i,
|
|
sql_state, &native_error,
|
|
buffer, buffer_len, &buffer_needed);
|
|
|
|
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
|
buffer_len = buffer_needed+1;
|
|
else
|
|
break;
|
|
}
|
|
|
|
switch (retval)
|
|
{
|
|
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
|
{
|
|
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_SQL_STATE, s48_enter_string(sql_state));
|
|
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_NATIVE_ERROR, s48_enter_integer(native_error));
|
|
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_MESSAGE, s48_enter_string(buffer));
|
|
res = s48_cons(diag_rec, res);
|
|
break;
|
|
}
|
|
case SQL_NO_DATA:
|
|
{
|
|
more_recs = 0;
|
|
break;
|
|
}
|
|
case SQL_ERROR:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDiagRec returned SQL_ERROR");
|
|
break;
|
|
}
|
|
case SQL_INVALID_HANDLE:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDiagRec got invalid handle");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
ODBC_RAISE_EXCEPTION("SQLGetDiagRec returned unknown error code");
|
|
break;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
S48_GC_UNPROTECT(); /* res */
|
|
free(buffer);
|
|
return res;
|
|
}
|
|
|
|
#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;
|
|
|
|
printf("fetching diag_rec from odbc driver.\n");
|
|
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;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(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));
|
|
|
|
S48_GC_UNPROTECT();
|
|
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;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(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));
|
|
|
|
S48_GC_UNPROTECT();
|
|
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;
|
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
|
S48_GC_PROTECT_1(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));
|
|
|
|
S48_GC_UNPROTECT();
|
|
return sql_timestamp;
|
|
}
|
|
|
|
/* gets a C type identifier and returns the size of this type,
|
|
according to Appendix D of ODBC Programmer's reference */
|
|
size_t sizeof_sql_c_type_identifier(SQLSMALLINT ctypeid)
|
|
{
|
|
switch (ctypeid)
|
|
{
|
|
case SQL_C_CHAR: return sizeof(SQLCHAR);
|
|
case SQL_C_SSHORT: case SQL_C_SHORT: return sizeof(SQLSMALLINT);
|
|
case SQL_C_USHORT: return sizeof(SQLUSMALLINT);
|
|
case SQL_C_SLONG: case SQL_C_LONG: return sizeof(SQLINTEGER);
|
|
case SQL_C_ULONG: return sizeof(SQLUINTEGER);
|
|
case SQL_C_FLOAT: return sizeof(SQLREAL);
|
|
case SQL_C_DOUBLE: return sizeof(SQLDOUBLE);
|
|
case SQL_C_BIT: return sizeof(SQLCHAR);
|
|
case SQL_C_STINYINT: return sizeof(SQLSCHAR);
|
|
case SQL_C_UTINYINT: return sizeof(SQLCHAR);
|
|
/* case SQL_SBIGINT: return sizeof(SQLBIGINT); */
|
|
/* case SQL_UBIGINT: return sizeof(SQLUBIGINT); */
|
|
case SQL_C_BINARY: return sizeof(SQLCHAR);
|
|
/* I don't know what to do with these types... */
|
|
/* case SQL_C_BOOKMARK: return sizeof(BOOKMARK); */
|
|
/* case SQL_C_VARBOOKMARK: return sizeof(SQLCHAR); */
|
|
case SQL_C_TYPE_DATE: return sizeof(SQL_DATE_STRUCT);
|
|
case SQL_C_TYPE_TIME: return sizeof(SQL_TIME_STRUCT);
|
|
case SQL_C_TYPE_TIMESTAMP: return sizeof(SQL_TIMESTAMP_STRUCT);
|
|
case SQL_C_NUMERIC: return sizeof(SQL_NUMERIC_STRUCT);
|
|
/* case SQL_C_GUID: return sizeof(SQLGUID); */
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("Unknown c data type identifier");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void odbc_sql_alloc(void **buffer, size_t buffer_len, size_t type_len)
|
|
{
|
|
ODBC_DEBUG_PRINTF_4("odbc_sql_alloc(): bf:%x bl:%d tl: %d\n", buffer, buffer_len, type_len);
|
|
if (*buffer == NULL)
|
|
{
|
|
ODBC_DEBUG_PRINTF_3("calloc bl:%d tl:%d\n", buffer_len+1, type_len);
|
|
*buffer = (void *) calloc(buffer_len+1, type_len);
|
|
}
|
|
else
|
|
{
|
|
ODBC_DEBUG_PRINTF_2("realloc bl:%d\n", buffer_len*type_len);
|
|
*buffer = (void *) realloc(*buffer, buffer_len*type_len);
|
|
}
|
|
|
|
if (*buffer == NULL)
|
|
{
|
|
ODBC_RAISE_EXCEPTION("Could not allocate return value buffer");
|
|
return;
|
|
}
|
|
}
|
|
|
|
s48_value buffer_to_s48_value(void *buffer, SQLSMALLINT ctypeid)
|
|
{
|
|
ODBC_DEBUG_PRINTF_3("buffer_to_s48_value(): %x %d\n", buffer, ctypeid);
|
|
switch (ctypeid)
|
|
{
|
|
case SQL_C_CHAR:
|
|
return s48_enter_string((SQLCHAR *) buffer);
|
|
case SQL_C_SSHORT: case SQL_C_SHORT:
|
|
return s48_enter_integer(*((SQLSMALLINT*) buffer));
|
|
case SQL_C_USHORT:
|
|
return s48_enter_integer(*((SQLUSMALLINT*) buffer));
|
|
case SQL_C_SLONG: case SQL_C_LONG:
|
|
return s48_enter_integer(*((SQLINTEGER*) buffer));
|
|
case SQL_C_ULONG:
|
|
return s48_enter_integer(*((SQLUINTEGER*) buffer));
|
|
/* case SQL_C_FLOAT: */
|
|
/* case SQL_C_DOUBLE: */
|
|
/* case SQL_C_BIT: */
|
|
case SQL_C_STINYINT:
|
|
return s48_enter_integer(*((SQLSCHAR *) buffer));
|
|
case SQL_C_UTINYINT:
|
|
return s48_enter_integer(*((SQLCHAR *) buffer));
|
|
case SQL_C_BINARY:
|
|
return s48_enter_string((SQLCHAR *) buffer);
|
|
case SQL_C_TYPE_DATE:
|
|
return struct_to_sql_date_record((SQL_DATE_STRUCT *) buffer);
|
|
case SQL_C_TYPE_TIME:
|
|
return struct_to_sql_time_record((SQL_TIME_STRUCT *) buffer);
|
|
case SQL_C_TYPE_TIMESTAMP:
|
|
return struct_to_sql_timestamp_record((SQL_TIMESTAMP_STRUCT *) buffer);
|
|
/* case SQL_C_NUMERIC: */
|
|
default:
|
|
ODBC_RAISE_EXCEPTION("Unknown c data type identifier");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void s48_init_odbc(void)
|
|
{
|
|
/* bindings for record types */
|
|
S48_GC_PROTECT_GLOBAL(odbc_diag_record_type);
|
|
odbc_diag_record_type = s48_get_imported_binding("odbc-diag");
|
|
|
|
S48_GC_PROTECT_GLOBAL(odbc_column_record_type);
|
|
odbc_column_record_type = s48_get_imported_binding("odbc-column");
|
|
|
|
S48_GC_PROTECT_GLOBAL(odbc_parameter_record_type);
|
|
odbc_column_record_type = s48_get_imported_binding("odbc-parameter");
|
|
|
|
S48_GC_PROTECT_GLOBAL(signal_unbound_column);
|
|
signal_unbound_column = s48_get_imported_binding("signal-unbound-column");
|
|
|
|
S48_GC_PROTECT_GLOBAL(signal_buffer_exceeded);
|
|
signal_buffer_exceeded = s48_get_imported_binding("signal-buffer-exceeded");
|
|
|
|
S48_GC_PROTECT_GLOBAL(bindcol_buffer_record_type);
|
|
bindcol_buffer_record_type = s48_get_imported_binding("bindcol-buffer");
|
|
|
|
/* init global variables */
|
|
global_bindcol_list = NULL;
|
|
|
|
/* functions for SQLBindCol() */
|
|
S48_EXPORT_FUNCTION(bindcol_lookup_binding_scheme);
|
|
S48_EXPORT_FUNCTION(odbc_sql_bindcol);
|
|
|
|
/* 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);
|
|
S48_EXPORT_FUNCTION(odbc_sql_browse_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 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_get_desc_field_int);
|
|
S48_EXPORT_FUNCTION(odbc_sql_get_desc_field_string);
|
|
|
|
/* PART 5 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_prepare);
|
|
S48_EXPORT_FUNCTION(odbc_sql_bind_parameter_exec_out);
|
|
S48_EXPORT_FUNCTION(odbc_sql_get_cursor_name);
|
|
S48_EXPORT_FUNCTION(odbc_sql_set_cursor_name);
|
|
|
|
/* PART 6 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_execute);
|
|
S48_EXPORT_FUNCTION(odbc_sql_execute_direct);
|
|
S48_EXPORT_FUNCTION(odbc_sql_native_sql);
|
|
S48_EXPORT_FUNCTION(odbc_sql_describe_param);
|
|
S48_EXPORT_FUNCTION(odbc_sql_num_params);
|
|
|
|
/* PART 7 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_row_count);
|
|
S48_EXPORT_FUNCTION(odbc_sql_get_data);
|
|
S48_EXPORT_FUNCTION(odbc_sql_set_pos);
|
|
S48_EXPORT_FUNCTION(odbc_sql_bulk_operations);
|
|
S48_EXPORT_FUNCTION(odbc_sql_more_results);
|
|
S48_EXPORT_FUNCTION(odbc_sql_fetch);
|
|
S48_EXPORT_FUNCTION(odbc_sql_num_result_cols);
|
|
S48_EXPORT_FUNCTION(odbc_sql_describe_col);
|
|
S48_EXPORT_FUNCTION(odbc_sql_col_attribute);
|
|
|
|
/* PART 8 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_column_privileges);
|
|
S48_EXPORT_FUNCTION(odbc_sql_columns);
|
|
S48_EXPORT_FUNCTION(odbc_sql_foreign_keys);
|
|
S48_EXPORT_FUNCTION(odbc_sql_primary_keys);
|
|
S48_EXPORT_FUNCTION(odbc_sql_procedure_columns);
|
|
S48_EXPORT_FUNCTION(odbc_sql_procedures);
|
|
S48_EXPORT_FUNCTION(odbc_sql_special_columns);
|
|
S48_EXPORT_FUNCTION(odbc_sql_statistics);
|
|
S48_EXPORT_FUNCTION(odbc_sql_table_privileges);
|
|
S48_EXPORT_FUNCTION(odbc_sql_tables);
|
|
|
|
/* 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);
|
|
|
|
/* PART 11 */
|
|
S48_EXPORT_FUNCTION(odbc_sql_get_diag_recs);
|
|
|
|
/* misc functions */
|
|
S48_EXPORT_FUNCTION(bindcol_finalize_bindcols);
|
|
}
|