Tuesday, June 12, 2007

Buffered LOB_APPEND

Jens Ulrik asked to see the code for a buffered LOB_APPEND mentioned in an earlier post LOB_APPEND eats resources....

Here it is as part of a package. Apologies for the rush job at the time; inelegant, but it was worth it...



gi_chunk_length integer := 0;
gv_chunk varchar2(32767);

-- add a character value to the CLOB being built up; catch null values
-- NOTE - final flush is done elsewhere
-- and we assume max(length(av_value)) < ki_maxchunksize

PROCEDURE lob_append (at_doc_clob IN OUT NOCOPY CLOB, av_value IN VARCHAR2)
IS
li_value_length integer;
li_new_chunk_length integer;
ki_maxchunksize constant integer := 32000;
BEGIN
-- prt_common_pkg.print_xml_string(av_value);
IF av_value IS NOT NULL THEN
li_value_length := length(av_value);
li_new_chunk_length := gi_chunk_length + li_value_length;

if li_new_chunk_length >= ki_maxchunksize
then
-- pad out the chunk as much as possible
gv_chunk := gv_chunk || substr(av_value,1,ki_maxchunksize - gi_chunk_length);
-- write out
DBMS_LOB.append (at_doc_clob, gv_chunk);
-- initialise remainder into next chunk
gi_chunk_length := li_new_chunk_length - ki_maxchunksize;
gv_chunk := substr(av_value,li_value_length +1 - gi_chunk_length);
else
gv_chunk := gv_chunk || av_value;
gi_chunk_length := li_new_chunk_length;
end if;
ELSE
prt_common_pkg.LOG ('lob_append null ignored',
prt_common_pkg.klog_ret
);
END IF;
END;

The final flush of the last chunk of a LOB is called like this:


IF gi_chunk_length > 0 THEN
-- flush out the last chunk of the CLOB
dbms_lob.append(at_doc_clob, gv_chunk);
gi_chunk_length := 0;
gv_chunk := null;
END IF;

1 comment:

Unknown said...

I made this VBScript-version of your StringBuilder.

My conclusion is that this technique does not work well in VBScript. You need to concatenate the small strings "normally" first, and use the StringBuilder when the accumulated length of the small strings reaches a few hundred characters.

Regards,

Jens Ulrik



Class clsStringBuilderArr

Private arr, strAdd, lngSize, lngCount, strChunk, lngChunck, lngChunckNew, lngAdd, lngChunckMax

Public Property Get Length
Length = Len(Value)
End Property

Public Property Get Value
Value = Join(arr, "") & strChunk
End Property

Public Sub Add(ByRef pstrAdd)
strAdd = "" & pstrAdd
lngAdd = Len(strAdd)
If (lngAdd = 0) Then Exit Sub
lngChunckNew = lngChunck + lngAdd
If (lngChunckNew >= lngChunckMax) Then
If (lngCount > lngSize - 1) Then lngSize = 2 * lngSize: ReDim Preserve arr(lngSize - 1)
arr(lngCount) = strChunk & strAdd
lngCount = lngCount + 1
lngChunck = 0
strChunk = ""
Else
strChunk = strChunk & strAdd
lngChunck = lngChunckNew
End If
End Sub

Public Sub Clear()
Class_Initialize
End Sub

Private Sub Class_Initialize()
lngSize = 32768
lngCount = 0
lngChunck = 0
strChunk = ""
lngChunckMax = 1024
ReDim arr(lngSize - 1)
End Sub

End Class