Subject Re: [firebird-support] Debugging BLOB problems
Author Volker Wegert

Helen Borrie <helebor@...> writes:
> At 07:52 PM 25/08/2005 +0200, you wrote:
>>I'm currently experiencing some weird behaviour with BLOB fields, and I'm
>>having problems tracking down the cause of these problems. All I can see is
>>that the content looks ok "the last time I see it", then it passes through the
>>chain Qt --> libgds --> firebird, and when I fetch the data from the database,
>>the BLOB is reduced to 16510 bytes. I do not have the slightest idea which of
>>the components is responsible for this problem, so my question is - is there
>>any way to trace or debug the execution of my insert statement?
> You don't say what components you are using

I wasn't sure which parts of the code to quote - I just didn't want to c&p the
entire Qt library to this list. However, in the meantime I got ddd working and
was able to step through the Qt database driver components. I'll include the
relevant parts below.

> As far as Firebird is concerned: you should pass a blob to a blob column;

That's what I do. "My" part of the code says

| QSqlQuery insert;
| QByteArray raw;
| // ...
| insert.prepare("INSERT INTO raw_res (source_uri, last_change, raw_content, \
| raw_size) VALUES (:uri, :timestamp, :raw, :size)");
| // ...
| insert.bindValue( ":raw", raw );
| // ...
| insert.exec();

When I trace the execution of exec() down to the driver level, I find out that
the following part of code is executed:

| 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 i = 0;
| while (i < ba.size()) {
| isc_put_segment(status, &handle, qMin(ba.size() - i, SHRT_MAX),
| const_cast<char*>(;
| if (isError(QT_TRANSLATE_NOOP("QIBaseResult", "Unable to write BLOB")))
| return false;
| i += SHRT_MAX;
| }
| }
| isc_close_blob(status, &handle);
| return true;
| }

No error message is returned, and I can see that for blobs larger than 32K
(SHRT_MAX), the loop is executed multiple times. These are exactly the ones
that get chopped off.

> 1. your interface component is treating the content of a text blob as a
> multi-byte character set. Your numbers are not quite consistent with this
> idea, since (for example, a Kylix widestring, 2-bytes per character) 32767
> / 2 is slightly less than 16510. Still, if the interface was handling,
> e.g., blanks and unaccented characters as single bytes, this explanation
> might still be consistent with what you see.

I already thought of this, and this might have been the case if I used QString
instead of QByteArray which is "just" a convenient form of char *. However,
this idea also doesn't quite fit in this case as any content between 16510 and
32767 is not truncated in any way.

> 2. related to 1), the character set setting for the client (lc_ctype) is
> set to NONE, ASCII, or some other single-byte character set, while the
> database or the column is defined as some multi-byte set. A certain amount
> of tolerance to this condition was added to Fb 1.5.2...but you don't say
> what version of Firebird (client and server) are in use.

Sorry - 1.5.1, client and server from the very same package. I've already
tried defining the columns as BLOB or as BLOB SUBTYPE 1 - no change. I found
no other parameters I could tweak - are there any?

> 3. You are using a driver that supports an absolute size limit on strings
> (if strings are involved) or on blobs/clobs.

The Qt internal driver simply uses the isc_* functions from libgds, as you can
see above, so no third party driver software should be involved. And from what
I can tell, the calls to the isc_* functions to write the blob contents look

> 4. Or it may be the case that the blobs are being stored correctly, but
> the size of the client buffer that is being used to accommodate query
> output is limited.

I've used several different methods to verify whether the contents have been
truncated. Both Qt and isql show the truncation, so I'm rather sure that it's
not simply a selection buffer problem.


* Volker Wegert * *
* 141 Reasons why you can't find your system administrator: 84. rcp $FA
* RESTAURANT:$FAVFOOD /dev/stomach