To operate on CLOB values aperio has some procedres: reqGetBlobValue() respAddBlobField() respAddBlobValue()
As the CLOB value length is not known when You write program these three procedures use pair of parameters to handle long data:
To add long data into response use respAddBlobField() or respAddBlobValue() and provide pointer to data and length in bytes Example:
D lText S 1600A
/FREE
lText = 'Sample long text bla bla bla bla';
respAddBlobField('data':'text':%ADDR(lText):%LEN(%TRMR(lText)));
To get CLOB value from request use procedure reqGetBlobValue(). This procedure returns pair of values, pointer to data and length of data.
Example:
gPtr = reqGetBlobValue('params':'text':gLen);
To transfer it to any internal value in program the best way is to use memcpy api to copy memory from one location to another.
D memcpy PR * ExtProc('memcpy')
D dst * value
D src * value
D length 10U 0 value
D lText S 1600C
/FREE
lText = *BLANKS;
memcpy(%ADDR(lText) :gPtr :gLen);
Lines above will copy CLOB value from original request memory to variable lText. Then You can freely use lText in your program.
NOTE: You need to make sure that there is enough space for the CLOB value in lText.
How to save CLOB value into file? In this case the best idea is to use CLOB field in file to store this information. To create file, you can use DDL (SQL) and CLOB field. You need to specify the maximum length in characters. In example bellow there is 16000 characters.
CREATE TABLE MYLIB.FILE02 (
FLD01 CHAR(32) NOT NULL,
FLD02 CLOB(16000) NOT NULL
)
or
The file can also be defined in DDS. But this time the length of field is constant:
Sample file with large data
A R F02
A FLD01 10A
A FLD02 32756A
A K FLD01
If file was created by DDL (SQL) then You need to use SQL variables in RPG program.
D lData S SQLTYPE(CLOB:16000)
The definition above actually creates structure which contains two elements: lData_data <– this element contains data lData_len <– this element contains length of data
Then in the RPG program you can use lData_data and lData_len to operate on CLOB fields
gPtr = reqGetBlobValue('params':'bigData':gLen);
lData = '';
memcpy(%ADDR(lData_data) :gPtr :gLen);
lData_len = gLen;
Then lData can be used in SQL to add/update record in file
EXEC SQL
INSERT INTO MYLIB.FILE02
(FLD01, FLD02)
VALUES
(:FLD01, :lData);
If file was created by DDS then the length of field is constant. This will utilize disk space of iSeries in not effective way. This time use local variable which will be used to temporary store CLOB data:
RPG Code to send response with long data (clob)
D l_bigData S 32766C VARYING
/FREE
//...Read file
l_bigData = %TRIMR(FLD02);
respAddBlobField('data': 'bigData'
:%ADDR(l_bigData) + 2
:%LEN(l_bigData) * 2);
NOTE: The address of destination element is calculated as %ADDR(l_bigData) + 2 because first two bytes of VARYING variable are reserved to keep length of data. The l_bigData is be defined as DBCS variable. Means 2 bytes per character. The length of l_bigData value in bytes is calculated as: %LEN(l_bigData) * 2
RPG code to save CLOB data into file. Here also we use memcpy:
D memcpy PR * ExtProc('memcpy')
D dst * value
D src * value
D length 10U 0 value
D l_bigData S 32766C VARYING
/FREE
gPtr = reqGetBlobValue('params':'bigData':gLen);
%len(l_bigData) = %INT(gLen/2);
memcpy(%ADDR(l_bigData) + 2 :gPtr :gLen);
Field02 = %CHAR(l_bigData);
NOTE: The address of destination element is calculated as %ADDR(l_bigData) + 2 because first two bytes of VARYING variable are reserved to keep length of data. The l_bigData is be defined as DBCS variable.
There are example programs in QSAMPLES source file: