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