Subject Re: [firebird-support] Debugging BLOB problems
Author Volker Wegert
"Ivan Prenosil" <Ivan.Prenosil@...> writes:
>> BLOBDUMP writes files exactly the size of the input file.
>> At the first glance, these files look truncated, anyway. Closer investigation
>> reveals that the contents of this file re-start from the very beginning at
>> offset 0x7fff.
> As far as I can see, if the isc_put_segment is called several times,
> you still pass pointer to start of data buffer.
>
> | while (i < ba.size()) {
> | isc_put_segment(status, &handle, qMin(ba.size() - i, SHRT_MAX),
> | const_cast<char*>(ba.data()));
> | if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to write BLOB")))
> | return false;
> | i += SHRT_MAX;
> | }

Yep, noticed that, too. I'll spare you the original BLOB read code, it's even
worse. Turned out that both read and write functions were useless and
corrupting data. Now, before I submit my changes, could perhaps soneone with
more firefox experience than I have take a look at my code?

bool QIBaseResultPrivate::writeBlob(int i, const QByteArray &ba)
{
isc_blob_handle handle = 0;
ISC_QUAD *bId = (ISC_QUAD*)inda->sqlvar[i].sqldata;
isc_create_blob2(status, &ibase, &trans, &handle, bId, 0, 0);
if (!isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to create BLOB"),
QSqlError::StatementError)) {
int pos = 0;
while (pos < ba.size()) {
isc_put_segment(status, &handle, qMin(ba.size() - pos, SHRT_MAX), &(const_cast<char*>(ba.data()))[pos]);
if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to write BLOB")))
return false;
pos += SHRT_MAX;
}
}
isc_close_blob(status, &handle);
return true;
}

QVariant QIBaseResultPrivate::fetchBlob(ISC_QUAD *bId)
{
isc_blob_handle handle = 0;
ISC_STATUS result = 0;
unsigned short len = 0;
uint ba_size = 0;
uint ba_fill = 0;
bool isErr = false;
QByteArray ba;

isc_open_blob2(status, &ibase, &trans, &handle, bId, 0, 0);
if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to open BLOB"),
QSqlError::StatementError))
return QVariant();

// Fetch the blob in 32K pages - this is the usual page size and
// should not produce too much overhead.
while (result == 0) {
ba_size = ba_fill + 32768;
ba.resize(ba_size);
result = isc_get_segment(status, &handle, &len, (ba_size - ba_fill), ba.data() + ba_fill);
ba_fill += len;
if (result == isc_segment) // buffer too short for entire segment
result = 0; // don't care, we'll just fetch the rest with the next call
}
ba.resize(ba_fill);
if (result != isc_segstr_eof)
{
// eof is ok, just means that we reached the end of the blob
// anything else is wrong.
isErr = isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to read BLOB"),
QSqlError::StatementError);
}
isc_close_blob(status, &handle);
if (isErr)
return QVariant();
return ba;
}

The semantics of the Qt classes can be found at
http://doc.trolltech.com/4.0/index.html

Thanks again
Volker

--
* Volker Wegert * http://www.volker-wegert.de/contact *
* "Man muß immer wieder mit Leuten rechnen, auf die man nicht zählen
* kann!" (Hermann Kesten)
*