CRecordset::GetFieldValue() with BIGINT

583 Views Asked by At

Can anyone help me figure out how to read an __int64 value from CRecordset?

My code looks something like this:

CDBVariant var;
CRecordset rs(&db);

rs.Open(CRecordset::forwardOnly, L"SELECT col FROM Customers");
rs.GetFieldValue((short)0, m_Var, SQL_C_SBIGINT);

But the call to GetFieldValue() produces the error:

Invalid argument value

Tracing through the code, I see that CRecordset::GetDataBuffer() asserts because SQL_C_SBIGINT (or SQL_C_BIGINT for that matter) is not one of the field types in the switch statement.

After spending over an hour on this, I've found a lot of documentation that indicates this should be possible, although not a single example. Does anyone know if it can be done?

1

There are 1 best solutions below

0
On BEST ANSWER

Well, I couldn't find a good way with CRecordset.

Since CRecordset is a wrapper for the Windows ODBC functions, I found I was able to get this to work by reaching down to lower-level functions. The methods below are part of a class that derives from CRecordset.

__int64 CRecordsetEx::GetInt64FieldValue(int nField)
{
    __int64 val = 0;
    GetData(nField, SQL_C_SBIGINT, &val, sizeof(val));
    return val;
}

long CRecordsetEx::GetData(int nField, short type, LPVOID pBuffer, int nBufferSize)
{
    SQLINTEGER nActualLength;
    SQLRETURN r = ::SQLGetData(m_hstmt, (short)nField + 1, type, pBuffer, nBufferSize, &nActualLength);

    if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)
    {
        ASSERT(FALSE);

        TCHAR szBuffer[10];
        TCHAR szMessage[100];
        SQLINTEGER nError;

        if (::SQLGetDiagRec(SQL_HANDLE_STMT, m_hstmt, 1, szBuffer, &nError, szMessage, 100, NULL) == SQL_SUCCESS)
            ::AfxThrowDBException(r, m_pDatabase, m_hstmt);
    }

    // Note: nActualLength set to SQL_NULL_DATA if field was NULL
    return nActualLength;
}

In fact, looking at the code for CRecordset, I think this approach is a little faster so I implemented this for all supported data types and it seems to work well.