When you use an ODBC function like SQLBindCol, SQLBindParameter, or SQLGetData, some of the parameters are typed as SQLLEN or SQLULEN in the function prototype. Depending on the date of the Microsoft ODBC API Reference documentation that you are looking at, you might see the same parameters described as SQLINTEGER or SQLUINTEGER.
SQLLEN and SQLULEN data items are 64 bits in a 64-bit ODBC application and 32 bits in a 32-bit ODBC application. SQLINTEGER and SQLUINTEGER data items are 32 bits on all platforms.
To illustrate the problem, the following ODBC function prototype was excerpted from an older copy of the Microsoft ODBC API Reference.
SQLRETURN SQLGetData( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StrLen_or_IndPtr);
Compare this with the actual function prototype found in sql.h in Microsoft Visual Studio version 8.
SQLRETURN SQL_API SQLGetData( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind);
As you can see, the BufferLength and StrLen_or_Ind parameters are now typed as SQLLEN, not SQLINTEGER. For the 64-bit platform, these are 64-bit quantities, not 32-bit quantities as indicated in the Microsoft documentation.
The following table lists some common ODBC types that have the same or different storage sizes on 64-bit and 32-bit platforms.
ODBC API | 64-bit platform | 32-bit platform |
---|---|---|
SQLINTEGER | 32 bits | 32 bits |
SQLUINTEGER | 32 bits | 32 bits |
SQLLEN | 64 bits | 32 bits |
SQLULEN | 64 bits | 32 bits |
SQLSETPOSIROW | 64 bits | 16 bits |
SQL_C_BOOKMARK | 64 bits | 32 bits |
BOOKMARK | 64 bits | 32 bits |
If you declare data variables and parameters incorrectly, then you may encounter incorrect software behavior.
The following table summarizes the ODBC API function prototypes that have changed since the introduction of 64-bit support. The parameters that are affected are noted. The parameter name as documented by Microsoft is shown in parentheses when it differs from the actual parameter name used in the function prototype. The parameter names are those used in the Microsoft Visual Studio version 8 header files.
ODBC API | Parameter (Documented Parameter Name) |
---|---|
SQLBindCol |
SQLLEN BufferLength SQLLEN *Strlen_or_Ind |
SQLBindParam |
SQLULEN LengthPrecision SQLLEN *Strlen_or_Ind |
SQLBindParameter |
SQLULEN cbColDef (ColumnSize) SQLLEN cbValueMax (BufferLength) SQLLEN *pcbValue (Strlen_or_IndPtr) |
SQLColAttribute |
SQLLEN *NumericAttribute |
SQLColAttributes |
SQLLEN *pfDesc |
SQLDescribeCol |
SQLULEN *ColumnSize (ColumnSizePtr) |
SQLDescribeParam |
SQLULEN *pcbParamDef (ParameterSizePtr) |
SQLExtendedFetch |
SQLLEN irow (FetchOffset) SQLULEN *pcrow (RowCountPtr) |
SQLFetchScroll |
SQLLEN FetchOffset |
SQLGetData |
SQLLEN BufferLength SQLLEN *Strlen_or_Ind (Strlen_or_IndPtr) |
SQLGetDescRec |
SQLLEN *Length (LengthPtr) |
SQLParamOptions |
SQLULEN crow, SQLULEN *pirow |
SQLPutData |
SQLLEN Strlen_or_Ind |
SQLRowCount |
SQLLEN *RowCount (RowCountPtr) |
SQLSetConnectOption |
SQLULEN Value |
SQLSetDescRec |
SQLLEN Length SQLLEN *StringLength (StringLengthPtr) SQLLEN *Indicator (IndicatorPtr) |
SQLSetParam |
SQLULEN LengthPrecision SQLLEN *Strlen_or_Ind (Strlen_or_IndPtr) |
SQLSetPos |
SQLSETPOSIROW irow (RowNumber) |
SQLSetScrollOptions |
SQLLEN crowKeyset |
SQLSetStmtOption |
SQLULEN Value |
Some values passed into and returned from ODBC API calls through pointers have changed to accommodate 64-bit applications. For example, the following values for the SQLSetStmtAttr and SQLSetDescField functions are no longer SQLINTEGER/SQLUINTEGER. The same rule applies to the corresponding parameters for the SQLGetStmtAttr and SQLGetDescField functions.
ODBC API | Type for Value/ValuePtr variable |
---|---|
SQLSetStmtAttr(SQL_ATTR_FETCH_BOOKMARK_PTR) |
SQLLEN * value |
SQLSetStmtAttr(SQL_ATTR_KEYSET_SIZE) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_MAX_LENGTH) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_MAX_ROWS) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_PARAM_BIND_OFFSET_PTR) |
SQLULEN * value |
SQLSetStmtAttr(SQL_ATTR_PARAMS_PROCESSED_PTR) |
SQLULEN * value |
SQLSetStmtAttr(SQL_ATTR_PARAMSET_SIZE) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_ROW_ARRAY_SIZE) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_ROW_BIND_OFFSET_PTR) |
SQLULEN * value |
SQLSetStmtAttr(SQL_ATTR_ROW_NUMBER) |
SQLULEN value |
SQLSetStmtAttr(SQL_ATTR_ROWS_FETCHED_PTR) |
SQLULEN * value |
SQLSetDescField(SQL_DESC_ARRAY_SIZE) |
SQLULEN value |
SQLSetDescField(SQL_DESC_BIND_OFFSET_PTR) |
SQLLEN * value |
SQLSetDescField(SQL_DESC_ROWS_PROCESSED_PTR) |
SQLULEN * value |
SQLSetDescField(SQL_DESC_DISPLAY_SIZE) |
SQLLEN value |
SQLSetDescField(SQL_DESC_INDICATOR_PTR) |
SQLLEN * value |
SQLSetDescField(SQL_DESC_LENGTH) |
SQLLEN value |
SQLSetDescField(SQL_DESC_OCTET_LENGTH) |
SQLLEN value |
SQLSetDescField(SQL_DESC_OCTET_LENGTH_PTR) |
SQLLEN * value |
For more information, see the Microsoft article ODBC 64-Bit API Changes in MDAC 2.7.
When you use SQLBindCol, SQLBindParameter, or SQLGetData, a C data type is specified for the column or parameter. On certain platforms, the storage (memory) provided for each column must be properly aligned to fetch or store a value of the specified type. The following table lists memory alignment requirements for all processors except x86, x64, and PowerPC platforms. The x64 platform includes Advanced Micro Devices (AMD) AMD64 processors and Intel Extended Memory 64 Technology (EM64T) processors. Processors such as Sun Sparc, Itanium-IA64, and ARM-based devices require memory alignment.
C Data Type | Alignment required |
---|---|
SQL_C_CHAR | none |
SQL_C_BINARY | none |
SQL_C_GUID | none |
SQL_C_BIT | none |
SQL_C_STINYINT | none |
SQL_C_UTINYINT | none |
SQL_C_TINYINT | none |
SQL_C_NUMERIC | none |
SQL_C_DEFAULT | none |
SQL_C_SSHORT | 2 |
SQL_C_USHORT | 2 |
SQL_C_SHORT | 2 |
SQL_C_DATE | 2 |
SQL_C_TIME | 2 |
SQL_C_TIMESTAMP | 2 |
SQL_C_TYPE_DATE | 2 |
SQL_C_TYPE_TIME | 2 |
SQL_C_TYPE_TIMESTAMP | 2 |
SQL_C_WCHAR | 2 (buffer size must be a multiple of 2 on all platforms) |
SQL_C_SLONG | 4 |
SQL_C_ULONG | 4 |
SQL_C_LONG | 4 |
SQL_C_FLOAT | 4 |
SQL_C_DOUBLE | 8 |
SQL_C_SBIGINT | 8 |
SQL_C_UBIGINT | 8 |