The example program below blows up on 64-bit architectures when using the Oracle ODBC driver. (ODBC drivers for other DBs work correctly.)
Apparently, the driver does not use SQLUSMALLINT but a 64-bit type for the entries in the row status array (set with SQL_ATTR_ROW_STATUS_PTR).
The ODBC specification requires the array entries to be SQLUSMALLINT:
… points to an array of SQLUSMALLINT values containing row status values after a call to SQLFetch or SQLFetchScroll.
(https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlsetstmtattr-function)
And the 64-Bit information page (https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-64-bit-information) does not mention anything about changes to this data type; only the pointer to the array is now 64 bits.
Is there a reason why the driver does not use SQLUSMALLINT?
Tested with the latest version, Instant Client 12.2 (instantclient-basiclite-windows.x64-12.2.0.1.0.zip and instantclient-odbc-windows.x64-12.2.0.1.0-2.zip), but I've seen this also with earlier versions.
#include <stdio.h>
#include <assert.h>
#include <windows.h> // needed for Microsoft's ODBC headers
#include <sql.h>
#include <sqlext.h>
#define DSN "Oracle"
#define USER "scott"
#define PASSWORD "tiger"
#define CHECK(fn) do { if ((fn) != SQL_SUCCESS) { fprintf(stderr, "%s failed\n", #fn); return 1; } } while (0)
int main()
{
SQLHENV hEnv;
SQLHDBC hDbc;
SQLHSTMT hStmt;
struct {
SQLUSMALLINT rowStatusArray[1];
char important_data;
} d;
assert(sizeof(d.rowStatusArray) == 2);
CHECK(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv));
CHECK(SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0));
CHECK(SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc));
CHECK(SQLConnect(hDbc, (SQLCHAR*)DSN, SQL_NTS, (SQLCHAR*)USER, SQL_NTS, (SQLCHAR*)PASSWORD, SQL_NTS));
CHECK(SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt));
CHECK(SQLExecDirect(hStmt, (SQLCHAR*)"SELECT 42 FROM DUAL", SQL_NTS));
CHECK(SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)1, 0));
CHECK(SQLSetStmtAttr(hStmt, SQL_ATTR_ROW_STATUS_PTR, d.rowStatusArray, 0));
d.important_data = 123;
CHECK(SQLFetch(hStmt));
assert(d.important_data == 123);
SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
return 0;
}
Assertion failed: d.important_data == 123, file ODBC_64_Test.cpp, line 35