How to use BLOB/CLOB values?

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:

  • Pointer to data
  • Length of data in bytes

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.

Use files to store CLOB values:

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:

  • EXAMPLE005 RPGLE blobData.get
  • EXAMPLE009 RPGLE blobDataFile.get
  • EXAMPLE011 RPGLE blobDataFile.add