Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Informix - BLOB trough ADO [VC++]

Status
Not open for further replies.

Krotow

Programmer
Dec 4, 2001
1
LV
I have a Informix database, and table, where is one BLOB field (type: BYTE) and some INTEGER type fields. Connections to this base is going trough ADO. Table content is selected/updated with SQL SELECT/INSERT/UPDATE respectively. All was allright, but I get errors, if BLOB size exceeds 640 Kb - BLOB content get corrupted on write. I tried use AppendChunk/GetChunk, but recordset updates was unsuccesful. On rs.Update() I has error -611 (Scroll cursor can't select Blob columns) - if recordset has result of SQL SELECT query or -201 (Syntax error or access violation) - if this was be table recordset. Blob save/load functions is followed:


Connection string:
Provider=Ifxoledbc.2;User ID=informix;Password=informix;Persist Security Info=True;Data Source=mybase@myhost


// Save blob to database.
BOOL CADOBlob::DBSaveBlob(const long lRecID, const BYTE *pBlob, const DWORD dwSize, BOOL bChunk)
{
HRESULT hr = S_OK;
_RecordsetPtr pRs = NULL;
CString strSQL;
_bstr_t bstrSQL;
_variant_t vBlob;
_variant_t vSize;
LPSAFEARRAY psa;
BYTE *lpArrayData;
BOOL bResult = TRUE;

strSQL.Format("select * from blobstore where id = %u;", lRecID);
bstrSQL = strSQL.AllocSysString();

vSize.vt = VT_I4;
vSize.lVal = dwSize;

try
{
// If record with given ID isn't exist and new record with this ID
// adding also failed, exit with FALSE.
if (!IsRecordExist(lRecID))
if (!AddNewRecord(lRecID))
return FALSE;

// Add blob to record.
pRs.CreateInstance(__uuidof(Recordset));
pRs->CursorLocation = adUseClient;
pRs->Open(bstrSQL, _variant_t((IDispatch *)m_pConnection, TRUE), adOpenKeyset, adLockOptimistic, adCmdText);
//pRs->Open("blobstore", _variant_t((IDispatch *)m_pConnection, TRUE), adOpenKeyset, adLockOptimistic, adCmdTable);
pRs->GetFields()->GetItem("size")->PutValue(vSize);
if(bChunk)
{
_variant_t vChunk;
DWORD dwOffset = 0;
DWORD dwLast;

psa = SafeArrayCreateVector(VT_UI1, 0, m_dwChunkSize);
if (!psa)
return E_OUTOFMEMORY;

while(dwOffset < dwSize)
{
// If blob tail is smaller than chunk size, redefine array to smaller size.
dwLast = dwSize - dwOffset;
if(dwLast < m_dwChunkSize)
{
SAFEARRAYBOUND *aDims = new SAFEARRAYBOUND[1];
aDims->cElements = dwLast;
aDims->lLbound = 0;
if (hr = SafeArrayRedim(psa, aDims)) throw hr;
}

SafeArrayAccessData(psa, (LPVOID*)&lpArrayData);
memcpy(lpArrayData, pBlob + dwOffset, psa->rgsabound[0].cElements);
SafeArrayUnaccessData(psa);

vChunk.vt = VT_ARRAY | VT_UI1;
vChunk.parray = psa;
pRs->GetFields()->GetItem(&quot;blob&quot;)->AppendChunk(vChunk);
dwOffset = dwOffset + m_dwChunkSize;
}
}
else
{
_variant_t vBlob;

psa = SafeArrayCreateVector(VT_UI1, 0, dwSize);
if (!psa)
return E_OUTOFMEMORY;

SafeArrayAccessData(psa, (LPVOID*)&lpArrayData);
memcpy(lpArrayData, pBlob, dwSize);
SafeArrayUnaccessData(psa);

vBlob.vt = VT_ARRAY | VT_UI1;
vBlob.parray = psa;
pRs->GetFields()->GetItem(&quot;blob&quot;)->PutValue(vBlob);
}
pRs->Update();
pRs->Close();
}
catch(const _com_error& e)
{
SendErrorMessage(e);
bResult = FALSE;
}
catch(...)
{
bResult = FALSE;
}

return bResult;
}

// Load blob from database.
BOOL CADOBlob::DBLoadBlob(const long lRecID, BYTE **pBlob, DWORD *dwSize, BOOL bChunk)
{
HRESULT hr = S_OK;
_RecordsetPtr pRs = NULL;
CString strSQL;
_bstr_t bstrSQL;
BOOL bResult = TRUE;

strSQL.Format(&quot;select * from blobstore where id = %u;&quot;, lRecID);
bstrSQL = strSQL.AllocSysString();

try
{
if(IsRecordExist(lRecID))
{
pRs.CreateInstance(__uuidof(Recordset));
pRs->CursorLocation = adUseClient;
pRs->Open(bstrSQL, _variant_t((IDispatch *)m_pConnection, TRUE), adOpenKeyset, adLockPessimistic, adCmdText);
_variant_t vSize = pRs->GetFields()->GetItem(&quot;size&quot;)->GetValue();
// If size field is not Null and blob field contain something, load blob.
if((vSize.vt != VT_NULL) && (pRs->GetFields()->GetItem(&quot;blob&quot;)->ActualSize > 0))
{
*dwSize = vSize.lVal;
*pBlob = new BYTE[*dwSize];
// Chunk ot not chunk? That is the question :)
if(bChunk)
{
_variant_t vChunk;
DWORD dwOffset = 0;
DWORD dwLast;
long lChunkSize = (long)m_dwChunkSize;

while(dwOffset < *dwSize)
{
dwLast = *dwSize - dwOffset;
// If blob tail is smaller than chunk size, redefine smaller chunk size.
if(dwLast < m_dwChunkSize)
lChunkSize = dwLast;
// Load chunk and at to memory buffer.
vChunk = pRs->GetFields()->GetItem(&quot;blob&quot;)->GetChunk(lChunkSize);
memcpy(*pBlob + dwOffset, vChunk.parray->pvData, lChunkSize);
dwOffset = dwOffset + m_dwChunkSize;
}
}
else
{
_variant_t vBlob = pRs->GetFields()->GetItem(&quot;blob&quot;)->GetValue();
memcpy(*pBlob, vBlob.parray->pvData, *dwSize);
}
}
else
bResult = FALSE;
pRs->Close();
}
else
{
CString strMessage;
strMessage.Format(&quot;Record %u is not exist!&quot;, lRecID);
SendMessage(strMessage);
bResult = FALSE;
}

}
catch(const _com_error& e)
{
SendErrorMessage(e);
bResult = FALSE;
}
catch(...)
{
bResult = FALSE;
}

return bResult;
}


But on Access 2000 database those code is working without problems. What is wrong?

Informix server version - 7.31C4, Informix OLEDB driver version - 3.80
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top