Page 1 of 1

Firebird 1.5 and BLOB (as text)

Posted: 09.03.2006, 20:34
by gto
Hallo =)
here I'm, again and again

Today, my problem is with BLOB type (firebird 1.5)

Every time that I post a text to my BlobField (subtype :1 - text, BlobType: ftMemo) through a DbMemo, FastMM4 reports it as leaked memory (all the text from the DbMemo).

I tried to go deep into zeos code, but wasn't found anything good.

Some idea!? :shock:

Posted: 24.03.2006, 01:59
by DavidVTaylor
The leak is caused by a known bug in ZDbcInterbase6Utils. The problem is in the WriteBlob(const Index: Integer; Stream: TStream) of TZParamsSQLDA.

If you are feeling adventurous, the fix is simply to add a try finally block and a call to FreeMem as shown below:

.....
.....

Buffer := AllocMem(BlobSize);

try
Stream.ReadBuffer(Buffer^, BlobSize);

{ put data to blob }
CurPos := 0;
.....
.....
.....
Stream.Seek(0, 0);
UpdateQuad(Index, BlobId);
finally
FreeMem(Buffer); <-- Fix is here
end;

.....
.....

I have used this fix in production code for several months so I know it works properly.

Hopes this helps,

David

Posted: 24.03.2006, 13:48
by gto
Yeah! Works like a charm :thanks:

I'm posting the procedure here, if someone want copy it:

Code: Select all

procedure TZParamsSQLDA.WriteBlob(const Index: Integer; Stream: TStream);
var
   Buffer: PChar;
   BlobId: TISC_QUAD;
   BlobHandle: TISC_BLOB_HANDLE;
   StatusVector: TARRAY_ISC_STATUS;
   BlobSize, CurPos, SegLen: Integer;
begin
   BlobHandle := nil;
   Stream.Seek(0, 0);

  { create blob handle }
   FPlainDriver.isc_create_blob2(@StatusVector, FHandle, FTransactionHandle,
      @BlobHandle, @BlobId, 0, nil);
   CheckInterbase6Error(FPlainDriver, StatusVector);

   Stream.Position := 0;
   BlobSize := Stream.Size;
   Buffer := AllocMem(BlobSize);
   try
      Stream.ReadBuffer(Buffer^, BlobSize);

  { put data to blob }
      CurPos := 0;
      SegLen := DefaultBlobSegmentSize;
      while (CurPos < BlobSize) do
      begin
         if (CurPos + SegLen > BlobSize) then
            SegLen := BlobSize - CurPos;
         if FPlainDriver.isc_put_segment(@StatusVector, @BlobHandle, SegLen,
            PChar(@Buffer[CurPos])) > 0 then
            CheckInterbase6Error(FPlainDriver, StatusVector);
         Inc(CurPos, SegLen);
      end;

  { close blob handle }
      FPlainDriver.isc_close_blob(@StatusVector, @BlobHandle);
      CheckInterbase6Error(FPlainDriver, StatusVector);

      Stream.Seek(0, 0);
      UpdateQuad(Index, BlobId);
   finally
      FreeMem(Buffer);
   end;
end;

Posted: 19.04.2006, 00:28
by mdaems
Hi,

Added this small bugfix to the testing branch of theSVN repository. Can you please check if this works the way you expected? I don't use interbase and only compiled in D7 and Lazarus.

So, please test and report.....

Mark