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