OLE DB -- Reading BLOBs

Started by
-1 comments, last by JonW 15 years, 9 months ago
Hi, I'm trying to read a BLOB column from an Access database using the basic Windows OLE DB API. I bind to the column and request an ISequentialStream interface for streaming in the data. I am having a couple issues, which are probably related: 1.) The first row read in gets an ISequentialStream pointer correctly, but attempting to read from it results in 0 bytes returned from ISequentialStream::Read. 2.) The second row has an undocumented HRESULT of 0x8000ffff returned from IRowset::GetNextRows (no matter what table I read from, or what the query is), and the rows read is equal to 0. Here is the code:

void CAreaDb::QueryRecordset (void)
{
	// Get the OLE DB session object
	IDBCreateSession *pIDBCreateSession;
	m_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession);

	// Create the session, getting an interface for command creation
	IDBCreateCommand *pIDBCreateCommand;
	pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**)&pIDBCreateCommand);
	pIDBCreateSession->Release();

	// Create the command object
	ICommandText* pICommandText;
	pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText, (IUnknown**)&pICommandText);
	pIDBCreateCommand->Release();

	// Set the command text as well as its language (SQL)
	pICommandText->SetCommandText(DBGUID_DBSQL, L"SELECT GDO_Geometry FROM d02_rest_area");

	// Execute the command
	LONG cRowsAffected;
	IRowset *pIRowset;
	pICommandText->Execute(NULL, IID_IRowset, NULL, &cRowsAffected, (IUnknown**)&pIRowset);
	pICommandText->Release();

	// Create the bindings from columns to offsets in the row value buffer
	DBBINDING binding;
	binding.iOrdinal = 1;
	binding.obValue = 0;
	binding.obLength = 0;
	binding.obStatus = sizeof(IUnknown*);
	binding.pTypeInfo = NULL;
	binding.pObject = NULL;
	binding.pBindExt = NULL;
	binding.dwPart = DBPART_VALUE | DBPART_STATUS;
	binding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
	binding.eParamIO = DBPARAMIO_NOTPARAM;
	binding.dwFlags = 0;
	binding.bPrecision = 0;
	binding.bScale = 0;
	binding.cbMaxLen = 0;
	binding.wType = DBTYPE_IUNKNOWN;

	// Ask the provider to return an ISequentialStream interface for reading
	DBOBJECT ObjectStruct;
	ObjectStruct.dwFlags = STGM_READ;
	ObjectStruct.iid = IID_ISequentialStream;
	binding.pObject = &ObjectStruct;

	// Create the accessor
	IAccessor *pIAccessor;
	HACCESSOR hAccessor;
	pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);

	pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, &binding, sizeof(IUnknown*) + sizeof(ULONG), &hAccessor, NULL);

	while (1)
	{
		// Get the next row handle
		HROW hRows[1];
		ULONG nRowsObtained;
		HROW *pRow = &hRows[0];

		// ERROR HERE!!!  Weird error on second pass through the loop
		HRESULT hr = pIRowset->GetNextRows(0, 0, 1, &nRowsObtained, &pRow);
		if (FAILED(hr))
			break;

		// All done -- there are no more rows left to get
		if (nRowsObtained == 0)
			return False;

		// Buffer of values read from the row
		char byRowValues[sizeof(IUnknown*) + sizeof(ULONG)];

		pIRowset->GetData(hRows[0], hAccessor, byRowValues);

		// HERE IS WHERE WE WOULD READ FROM THE ISequentialStream NOW
		// IN byRowValues; HOWEVER ISequentialStream::Read() RETURNS 0 BYTES

		// Release row handles
		pIRowset->ReleaseRows(nRowsObtained, hRows, NULL, NULL, NULL);
	}
}


This is some test code I put together, I don't have the problem with any rows that contain just basic values--its only when I bind to the BLOB column (an OLE Object containing binary data). I've been trying to figure this out for a long time! Any thoughts are greatly appreciated. Thanks!

This topic is closed to new replies.

Advertisement