ZDbcOracleResultSet ReadBlob is NOT worked. Lazarus

The alpha/beta tester's forum for ZeosLib 7.0.x series

Report problems concerning our Delphi 2009+ version and new Zeoslib 7.0 features here.

This is a forum that will be removed once the 7.X version goes into stable!!

Moderators: gto, EgonHugeist, olehs

Locked
Inferno
Fresh Boarder
Fresh Boarder
Posts: 2
Joined: 21.05.2010, 05:35

ZDbcOracleResultSet ReadBlob is NOT worked. Lazarus

Post by Inferno »

Problem 1.Original procedure ReadBlob from ZDbcOracleResultSet is not worked with CLOB data where length higher some ~4Kb. Error:OCI_NEED_DATA
Lazarus.Oracel 9i. NLS_LANG=RUSSIAN_CIS.UTF8
revision 807 from trunk

But, my procedure is worked:

Code: Select all

procedure TZOracleBlob.ReadBlob;
const
  MemDelta = 1 shl 12;  // read page (2^...)
  iBufferSize = 4096;
var
  Status: integer;
  Buf: PByteArray;
  ReadNum, Offset, Cap: ub4;
  Connection: IZOracleConnection;
  atmp: integer;
  i: integer;
  ond: boolean;

{$IFDEF FPC}
  function GetSizeAtmpLast(Abuf:Pointer;SizeBuf:integer):integer;
  Var
    gi: Integer;
    chLen: LongInt;
  begin
    result := 0;
    gi:=0;
    while gi<SizeBuf do
    begin
      chLen:=UTF8CharacterLength(Pchar(Abuf));
      if chlen<=0 then
        break;
      Inc(Abuf,chLen);
      Inc(gi,chLen);
      if Pchar(Abuf)='' then break;
    End;
    result:=gi;
  End;
{$ENDIF}

begin
  if not Updated and (FLobLocator <> nil) and (BlobData = nil) and
    (not FTemporary) then
  begin
    Connection := FHandle as IZOracleConnection;

    { Opens a large object or file for read. }
    Status := FPlainDriver.LobOpen(Connection.GetContextHandle,
      Connection.GetErrorHandle, FLobLocator, OCI_LOB_READONLY);
    CheckOracleError(FPlainDriver, Connection.GetErrorHandle,
      Status, lcOther, 'Open Large Object');
    try
      { Reads data in chunks by MemDelta or more }
      Offset := 0;
      Cap := 0;
      Buf := nil;
      try     
        atmp := 0;
        Status := OCI_SUCCESS;
        ond := False;
        while (Status = OCI_NEED_DATA) or (Status = OCI_SUCCESS) do
        begin
          Cap := Cap + iBufferSize;
          ReallocMem(Buf, Cap);
          FillByte(Buf[Offset],iBufferSize,0);
          ReadNum := iBufferSize;
          Status := FPlainDriver.LobRead(Connection.GetContextHandle,
            Connection.GetErrorHandle, FLobLocator, atmp, Offset +
            1, @Buf[Offset], ReadNum, nil, nil, 0, SQLCS_IMPLICIT);
          case Status of
            OCI_NEED_DATA:
            begin
              ond := True;
              if (atmp > 0) then
                Inc(Offset, ReadNum);
            end;
            OCI_SUCCESS:
            begin
              {$IFDEF FPC}
              if ond then
                Inc(Offset,GetSizeAtmpLast(@Buf[Offset],iBufferSize))
              else
                Inc(Offset, atmp);
              {$ELSE}
              Inc(Offset, atmp);
              {$ENDIF}
              Break;
            end;
            else
              break;
          end;
        end;
        CheckOracleError(FPlainDriver, Connection.GetErrorHandle,
          Status, lcOther, 'Read Large Object');
      except
        FreeMem(Buf);
        raise;
      end;
      ReallocMem(Buf, Offset);
    finally
      { Closes large object or file. }
      Status := FPlainDriver.LobClose(Connection.GetContextHandle,
        Connection.GetErrorHandle, FLobLocator);
      CheckOracleError(FPlainDriver, Connection.GetErrorHandle,
        Status, lcOther, 'Close Large Object');
    end;
    { Assigns data }
    InternalSetData(Buf, Offset);
  end;
end;
Problem 2. The LobLocator for all records of the table same
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

Hi,

Do you know the reason why there's a difference between Delphi and FPC handling? Doesn't Delphi need GetSizeAtmpLast?

Mark
Image
Inferno
Fresh Boarder
Fresh Boarder
Posts: 2
Joined: 21.05.2010, 05:35

Post by Inferno »

mdaems wrote:Hi,

Do you know the reason why there's a difference between Delphi and FPC handling? Doesn't Delphi need GetSizeAtmpLast?

Mark
Hi, Mark.

The method GetSizeAtmpLast it is necessary for Delphi. But I don't use Delphi, I use FreePascal and rewrited the ReadBlob method under the project. Maybe you can realise this method more correctly.
And what with are identical LobLocator to different records?

Alexei.
User avatar
mdaems
Zeos Project Manager
Zeos Project Manager
Posts: 2766
Joined: 20.09.2005, 15:28
Location: Brussels, Belgium
Contact:

Post by mdaems »

Hi Alexei,

I tried your code and except for the line

Code: Select all

FillByte(Buf[Offset],iBufferSize,0); 
it compiles fine for al compilers and the testsuite didn't give any more errors.

However, I don't know how to change GetSizeAtmpLast so it also compiles on Delphi either. Is your version worse for Delhi than the old version?

Concerning The identical Loblocator for all records seems to be a known problem. The reason may be that a pointer to a loblocator is stored inside the Blob object, and maybe the OCI uses the same address for each LOB again? Needs debugging... Feel like giving it a go?

Mark
Image
Locked