Subject Re: [ib-support] UDF with BLOB...
Author Ann W. Harrison
At 01:48 AM 10/11/2001 -0400, Claudio Valderrama C. wrote:

>In theory: create a stream blob (as opposed to typical segmented blobs) and
>use the blobcallback structure definition that's in FB's ibase.h, then
>you'll have a function to seek...
>Now, the problem is whether you can create such stream blobs. I know they
>are used internally for arrays.
>Ann, are you reading?

Yes. As it turns out, the segmented/stream difference happens not
at the time you define the column, but when you actually create the
blob itself. A single column can include both types of blob.

The second create blob call (isc_create_blob2) accepts a blob parameter
block which works like other parameter blocks. One of the items stuffed
there is isc_bpb_type which has values of isc_bpb_type_segmented or

So, it's pretty low level, but completely available - are you reading
tool makers?

Relevant code follows.


We have answers.

From blb.c/create_blob2

/* Create a blob large enough to hold a single data page */

type = gds__parse_bpb2 (bpb_length, bpb, &from, &to, &from_charset,
blob = allocate_blob (tdbb, transaction);

if (type)
blob->blb_flags |= BLB_stream;

from ibase.h

/* Blob Parameter Block */

#define isc_bpb_version1 1
#define isc_bpb_source_type 1
#define isc_bpb_target_type 2
#define isc_bpb_type 3
#define isc_bpb_source_interp 4
#define isc_bpb_target_interp 5
#define isc_bpb_filter_parameter 6

#define isc_bpb_type_segmented 0
#define isc_bpb_type_stream 1

from gds.c/gds__parse_bpb2

USHORT API_ROUTINE gds__parse_bpb2 (
USHORT bpb_length,
UCHAR *bpb,
USHORT *source,
USHORT *target,
USHORT *source_interp,
USHORT *target_interp)
* g d s _ p a r s e _ b p b 2
* Functional description
* Get blob type, source sub_type and target sub-type
* from a blob parameter block.
* Basically gds__parse_bpb() with additional:
* source_interp and target_interp.
UCHAR *p, *end, op;
USHORT type, length;

type = *source = *target = 0;

if (source_interp)
*source_interp = 0;
if (target_interp)
*target_interp = 0;

if (!bpb_length)
return type;

p = bpb;
end = p + bpb_length;

if (*p++ != gds__bpb_version1)
return type;

while (p < end)
op = *p++;
length = *p++;
switch (op)
case gds__bpb_source_type:
*source = (USHORT)gds__vax_integer (p, length);

case gds__bpb_target_type:
*target = (USHORT)gds__vax_integer (p, length);

case gds__bpb_type:
type = (USHORT)gds__vax_integer (p, length);

case gds__bpb_source_interp:
if (source_interp)
*source_interp = (USHORT)gds__vax_integer (p, length);

case gds__bpb_target_interp:
if (target_interp)
*target_interp = (USHORT)gds__vax_integer (p, length);

p += length;

return type;