ZDbcOracleResultSet ReadBlob is NOT worked. Lazarus
Posted: 21.05.2010, 05:49
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:
Problem 2. The LobLocator for all records of the table same
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;