Skip to content

Instantly share code, notes, and snippets.

@BirgittaHauser
Last active August 30, 2023 10:08
Show Gist options
  • Select an option

  • Save BirgittaHauser/041e1fb82b5f8bbeee26578b0a438f4e to your computer and use it in GitHub Desktop.

Select an option

Save BirgittaHauser/041e1fb82b5f8bbeee26578b0a438f4e to your computer and use it in GitHub Desktop.
Access a PDF document (with RPG) and pass the PDF document as Parameter to another Program/Procedure
//*********************************************************************************************
// I recently get asked how to read a small PDF document into a BLOB and pass it as parameter
// to another function or procedure
// 1. When working with embedded SQL character host variables can only be used up to 32k
// Larger data (up to 16 MB - RPG restriction)
// can be read into a LOB-Variable defined with the SQLTYPE keyword
// 2. Unfortunately the SQLTYPE Keyword cannot be used in a Prototype or Procedure Interface
// 3. But the SQL precompiler generates for the LOB variable a data structure with an
// UNS(4) Subfield _LEN and
// CHAR(xxx) Subfield _DATA
// and this is exactly the structure of a Varying Length field with a 4 digit length prefix
// --> for solving the problem the CLOB data must be transferred into varying lenth field
// this varying length field then can be passed as Parameter to the next procedure/program
// and in the next program the data can be transferred back into a LOB variable (if needed)
//---------------------------------------------------------------------------------------------
// Note: I'd normally not pass the CLOB but only the path where the PDF document is located
// and then read it in the second procedure/Program
//*********************************************************************************************
// In this program I read a PDF-Document into a BLOB Variable and then
// pass it to an (internal) procedure.
// And then write the PDF document back into the IFS with a differen name.
//---------------------------------------------------------------------------------------------
// Note: will only work for small (up to 16 MB) IFS Files
// Should work for Release 7.3 or higher
//*********************************************************************************************
Ctl-Opt DatFmt(*ISO);
/If Defined (*CRTBNDRPG)
CTL-Opt DftActGrp(*No) ActGrp(*NEW);
/EndIf
//*********************************************************************************************
DCL-S GblBlobPDF SQLTYPE(BLOB: 10000000);
DCL-S GblBlobVar VarChar(10000000: 4);
Dcl-S GblErrText VarChar(50);
//*********************************************************************************************
Exec SQL Set Option Commit=*None, DatFmt=*ISO, TimFmt=*ISO,
Naming=*SYS, CloSQLCsr=*EndActGrp;
//*********************************************************************************************
*InLR = *On;
Clear GblBlobPDF;
Exec SQL
Select Line into :GblBlobPDF
from Table(Qsys2.Ifs_Read_Binary(
Path_Name => '/home/Hauser/PDF/PDFDocument_01.pdf'));
If SQLCODE < *Zeros;
Exec SQL Get Diagnostics Condition 1 :GblErrText = MESSAGE_TEXT;
dsply GblErrText;
EndIf;
GblBlobVar = GblBlobPDF;
Int_WriteBack(GblBlobVar);
Return;
//********************************************************************************************
// Write Back
//********************************************************************************************
DCL-Proc Int_WriteBack;
DCL-PI Int_WriteBack;
GblBlobVar VarChar(10000000: 4);
End-Pi;
DCL-S LocBLOBPDF SQLTYPE(BLOB: 10000000);
//---------------------------------------------------------------------------------------------
Clear LocBLOBPDF;
LocBlobPDF = GblBlobVar;
Exec SQL
CAll QSYS2.IFS_Write_Binary(
Path_Name => '/home/Hauser/PDF/PDFDocument_XXX.pdf',
Line => :LocBlobPDF,
File_CCSID => 850,
Overwrite => 'REPLACE');
If SQLCODE < *Zeros;
Exec SQL Get Diagnostics Condition 1 :GblErrText = MESSAGE_TEXT;
dsply GblErrText;
EndIf;
End-Proc;
@bobcozzi

Copy link
Copy Markdown

`
Ctl-Opt DatFmt(*ISO);
/If Defined (*CRTBNDRPG)
CTL-Opt DftActGrp(*No) ActGrp(*NEW);
/EndIf

   DCL-S  PDFData             SQLTYPE(BLOB: 10000000);
   Dcl-S  GblErrText           VarChar(50);
   DCL-S  pdf_CCSID  int(10);
   DCL-S  pdf_size   int(20);
   DCL-S  pdfFile varchar(256) Inz('/home/cozzi/sample.pdf');

     Exec SQL   Set Option  Commit=*CHG, NAMING=*SYS;

     *InLR       = *On;

     Clear PDFData;

       // Get PDF Size and CCSID
     Exec SQL
         SELECT ccsid, data_size
              INTO :pdf_ccsid, :pdf_size
           FROM TABLE(qsys2.IFS_OBJECT_STATISTICS( :pdfFile ))
           LIMIT 1;

     Exec SQL
          Select LINE  INTO :PDFData
             from Table(Qsys2.Ifs_Read_Binary(
                       Path_Name => :PDFFile ));
     If SQLCODE < *Zeros;
        Exec SQL Get Diagnostics Condition 1 :GblErrText = MESSAGE_TEXT;
        snd-msg gblErrText;
     EndIf;

     Int_WriteBack( PDFData );

     Return;

   DCL-Proc Int_WriteBack;

     DCL-PI Int_WriteBack;
        pdfInfo    LIKEDS(PDFDATA) options(*VARSIZE);
     End-Pi;

     DCL-S  l_sc       char(6);
     DCL-S  l_st       char(5);
     pdfFile = %ScanRPL('.pdf' : '_2.pdf' : pdfFile);
     // Note this assumes you want the target PDF file
     // to be the Windows CCSID regardless of what the
     // original PDF file CCSID is.
     Exec SQL
          CAll QSYS2.IFS_Write_Binary(
               Path_Name  => :PDFFILE,
               Line       => :pdfInfo,
               File_CCSID => 850,
               Overwrite  => 'REPLACE');

     If SQLCODE < *Zeros;
        l_sc = %char(sqlCode);
        l_st = sqlstate;
        Exec SQL Get Diagnostics Condition 1 :GblErrText = MESSAGE_TEXT;
        snd-msg gblErrText +
                  ' SQLState: ' + l_st +
                  ' SQLCODE: ' + l_sc;
     EndIf;

   End-Proc; `

@dancarlosgabriel

Copy link
Copy Markdown

cool stuff, thanks for sharing Birgitta, and Bob.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment