James
James

Reputation: 1490

How to handle long strings with ODBC?

I'm using ODBC SQLGetData to retrieve string data, using a 256 byte buffer as default. If the buffer is too short, I'm allocating a new buffer large enough for the string and calling SQLGetData() again.

It seems that calling this a second time only returns what was left after the last call, and not the whole field.

Is there any way to 'reset' this behaviour so SQLGetData returns the whole field into the second buffer?

char buffer[256];
SQLLEN sizeNeeded = 0;

SQLRETURN ret = SQLGetData(_statement, _columnIndex, SQL_C_CHAR, (SQLCHAR*)buffer, sizeof(buffer), &sizeNeeded);

if(ret == SQL_SUCCESS)
{
    return std::string(buffer);
}
else if(ret == SQL_SUCCESS_WITH_INFO)
{
    std::auto_ptr<char> largeBuffer(new char[sizeNeeded + 1]);

    // Doesn't return the whole field, only what was left...
    SQLGetData(_statement, _columnIndex, SQL_C_CHAR, (SQLCHAR*)largeBuffer.get(), sizeNeeded, &sizeNeeded);
}

Thanks for any help!

Upvotes: 0

Views: 2199

Answers (2)

D.Shawley
D.Shawley

Reputation: 59623

If you are interested in "resetting" the fetch buffer, I believe that the position in the column is only preserved if the column name/index is the same for two consecutive calls. In other words, calling SQLFetchData with a different column name should reset the position in the original column. Here's a snippet from MSDN:

Successive calls to SQLGetData will retrieve data from the last column requested; prior offsets become invalid. For example, when the following sequence is performed:

    SQLGetData(icol=n), SQLGetData(icol=m), SQLGetData(icol=n)

the second call to SQLGetData(icol=n) retrieves data from the start of the n column. Any offset in the data due to earlier calls to SQLGetData for the column is no longer valid.

I don't have the ODBC spec handy, but MSDN seems to indicate that this is the expected behavior. Personally, I have always accumulated the result of multiple calls directly into a string using a fixed size buffer.

Upvotes: 0

Joe
Joe

Reputation: 42666

It is the caller's responsibility to put the data together; the limitation on returning the data in chunks could be due to the database provider and not your code, so you need to be able to handle the case either way.

Also your code has a logic flaw -- you might have to call SQLGetData multiple times; each time could return additional chunks of data with SQL_SUCCESS_WITH_INFO/01004 that need to be appended in a loop.

Upvotes: 2

Related Questions