× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



Why not write directly to the IFS and have them pick it up from the IFS or FTP 
from the IFS? Writes to IFS are very fast. 

Also, why so many records to the data warehouse? In other words, could you 
summarize the data?

-----Original Message-----
From: Rich Dotson [mailto:rich_dotson@xxxxxxxxxxx]
Sent: Tuesday, May 24, 2005 1:35 PM
To: rpg400-l@xxxxxxxxxxxx
Subject: Help improve performance of RPG program - Long Post


   I have a program that we use to create export files that are ftp*d to our
   data warehouse application.  The program works great functionally but we
   would like to improve the performance on files that have a lot of fields
   and a lot of records (500,000+).
 
   The program specs were:

   1) Must be *generic* enough to process, without modification, any file on
   our iSeries.

   2) First row of file must contain:
      a) File Name

      b) Number of fields in file

      c) Number of Records in the file

      d) Last G/L posting date

   3) Second row of the file must contain the field names

   4) Subsequent rows will be the data

 

   A sample of the first three rows would look like:

   "XAT90090",5,1297,05/22/2005

   "EFFDATE","APPLCD","ACCTNO","ACCTTYP","TRANAMT"

   05/19/2005,20,1234567890,1,-190.78

   4) All dates must be in MM/DD/CCYY format.  For this I created a file
   (XAP10005L1) that contains the fields that contain dates and the format
   that they are in: a) File Name  b) Date Field Name  c)Stored Date
   Format  (*LongJul, *MDY, *JUL, *YMD, etc..)  When processing a field I
   check this file to see if it is a date field and reformat it if it is.

   5) Only the fields that the user selects should appear in the export
   file.    The way I solved this issue is if the user does not want all the
   fields in the data file, I created another PF DDS containing only the
   desired fields.   I pull the data from one file based on the fields this
   *template* file.

   I*ve borrowed a lot of code from this mail list and other web sites and
   pieced together the following program.

   Any suggestions on how it may be changed to improve the performance would
   be greatly appreciated.

   Thanks,  Rich*

 

        H DftActGrp(*NO) BndDir('QC2LE':'OSBBNDDIR')
        H OPTION(*NODEBUGIO: *NOSHOWCPY: *SRCSTMT)
         *
   *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        ^1* Generic File to process desired data
        FInFile    IF   F32766        Disk    ExtFile(InputFile) UsrOpn
        F                                     InFDS(FileInFDS)
        ^1* Field Date Format File
        FXAP10005L1IF   E           K Disk
        ^1* FTP Output File
        FFTPOutput O  A F32766        Disk    ExtFile(OutputFile) UsrOpn
        e* Prototype
        D Entry           PR                  ExtProc('XA90060')
        D  FileName                     10A
        D  LibName                      10A
        D  DDSName                      10A
        D  DDSLib                       10A
        D  Colum_Sep                     1A
        D  Alpha_Sep                     1A
        D  CBSName                      10A
        e* Prototype
        D Entry           PI
        D  FileName                     10A
        D  LibName                      10A
        D  DDSName                      10A
        D  DDSLib                       10A
        D  Colum_Sep                     1A
        D  Alpha_Sep                     1A
        D  CBSName                      10A
        ^1* Define the INTERNAL prototypes (Subroutines) used in this program
        D CloseSQLCursor  PR
        D DeclareCursor   PR
        D GetData         PR
        D GetFieldCount   PR
        D GetFieldDef     PR
        D IncludeInFile   PR              N
        D  inFieldName                        Like(FldName) CONST
        D SetSQLOptions   PR
        D ValidSQLRecord  PR              N
        D WriteHeaderRec  PR
        D WrtFieldNames   PR
        ^1* Define the EXTERNAL prototypes used in this program
         /COPY *LIBL/QOSBCPYSRC,SC9000PR
         /COPY *LIBL/QOSBCPYSRC,TA9000PR
         /COPY *LIBL/QOSBCPYSRC,XA1001PR
         /COPY *LIBL/QOSBCPYSRC,XA10006PR
        e* Procedure to get extract a NUMBER from a STRING
        D FmtNumber       PR            50A   Varying
        D  NbrValue                     50A   Varying CONST
        D  DecPos                        3  0 CONST
        e* Procedure to change the file date to 'MM/DD/CCYY' format
        D FormatDate      PR            10A   Varying
        D  inFormat                           Like(XAPDateF) CONST
        ^1* Input File Data Structure
        DFileInFDS        DS
        D RecordCount           156    159B 0
        ^1* Data Structure to hold Date Fields
        ^1* Work Fields
        D CurrentUserId   S             10A   Inz(*User)
        D DataPtr         S               *
        D FieldCount      S              9  0
        D FieldDSLen      S              9  0  Inz(%Len(FieldDS))
        D FieldDSPtr      S               *    Inz(*Null)
        D FldIdxPtr       S               *
        D FTPField        S          32766A    Inz Varying
        D i               S              9  0  Inz(0)
        D InputFile       S             21A    Inz
        D LastPostDate    S              7P 0 Inz
        D Offset          S              9  0 Inz(0)
        D OutputFile      S             21A   Inz('QTEMP/DB2EXPORT')
        D SQLCommand      S            256A   Varying Inz
        D AlphaFld        S            256A   Varying Inz
        D NumberFld       S             31 15 Inz
        D File            S                   Like(FileName) Inz
        D Lib             S                   Like(LibName) Inz
        ^1* This DS will contain the data being read into the program
        D DataRecord      DS         32766
        ^1* This DS is used to contain the Field Information for the record
        D FieldDS         DS                   Based(FldIdxPtr)
        D   FldNumber                   10  0
        D   FldName                     10
        D   TblName                     10
        D   Schema                      10
        D   FldType                     10
        D   FldLen                      10I 0
        D   FldDecPos                    3
        D   FldBytes                    10I 0
        D   FldOffset                   10I 0
        D   FldDateFmt                        Like(XAPDateF)
        D   FldExportFlg                 1A
        C
         /Free
 
   //^1*-----------------------------------------------------------------
          //^1*aM   A   I   N   L   I   N   E        R   O   U   T   I   N
   E
 
   //^1*-----------------------------------------------------------------
          //^1Get the Last Posting Date
          LastPostDate = GetLastPostDte( RtvBankDefault(CurrentUserId) );
          //^1Combine the Library and file to look like 'LIBNAME/FILENAME'
          LibName = toUpper(LibName);
          FileName = toUpper(FileName);
          InputFile = %Trim(LibName) + '/' + %Trim(FileName);
          //^1Make sure the file names are in UPPER case
          DDSName = toUpper(DDSName);
          CBSName = toUpper(CBSName);
          //^1Open the files to process
          Open InFile;
          Open FTPOutput;
          //^1Count the # of fields in the file containing the fields to
   export
          File = DDSName;
          Lib = DDSLib;
          GetFieldCount();
          //^1Write File Header Record
          WriteHeaderRec();
          //^1Count the # of fields in the file containing the data to
   process
          File = FileName;
          Lib = LibName;
          GetFieldCount();
          //^1Retrieve Field Definitions
          GetFieldDef();
          //^1Write a record containing the Field Names
          WrtFieldNames();
          //^1Read the input file into the DS for processing
          DoU %EOF(InFile);
            Read InFile DataRecord;
            If %EOF(InFile);
              Leave;
            EndIf;
            //^1Strip out each field from the Data Structure
            GetData();
          EndDo;
          //^1Close the files
          Close InFile;
          Close FTPOutput;
          *InLR = *On;
         /End-Free
        ^1*-----------------------------------------------------------------
        ^1*a        O   U   T   P   U   T       S   P   E   C   S
        ^1*-----------------------------------------------------------------
        OFTPOutput EADD         WriteRec
        O                       FTPField
         *=====================================================================
         *aGetFieldDef: Get the definitions of the fields in this file
         *=====================================================================
        P GetFieldDef     B
         /Free
           //^1Alloc Storage to hold FieldDS for Each Column in the Table
           FieldDSPtr = %Alloc(FieldDSLen * FieldCount);
           //^1Set the pointer to the first "Occurance" of FieldDS in
           //^1 the allocated Storage
           FldIdxPtr = FieldDSPtr;
           //^1Clearing the Data structure will init the fields in the
   FieldDS
           //^1data structure and avoid data decimal errors
           Clear FieldDS;
           //^1Build a cursor containing the list of columns (fields) in the
           //^1file that is being exported.
           DeclareCursor();
           //^1Read all the records from the SQL Cursor
           //^1and place the data into FieldDS
           DoW ValidSQLRecord();
             //^1Determine if this field is a date field
             Chain (FileName : FldName) XAP10005L1;
             If %Found( XAP10005L1 );
               FldDateFmt = XAPDateF;
             EndIf;
             //^1Determine the offset to the beginning of the field
             FldOffset = Offset;
             //^1Determine the field should be included in the export file
             //^1(All fields may not be exported to the Data Warehouse)
             FldExportFlg = 'Y';
             If Not IncludeInFile(FldName);
               FldExportFlg = 'N';
             EndIf;
             //^1If this is not the last column in the table, calculate
             //^1  the next offset and advance the pointer to the next
             //^1  "occurrence" of FieldDs in the allocated storage.
             If FldNumber <> FieldCount;
               Offset = Offset + FldBytes;
               FldIdxPtr = FieldDSPtr + (FieldDSLen * FldNumber);
               Clear FieldDS;
           EndIf;
           EndDo;
           CloseSQLCursor();
         /End-Free
        P GetFieldDef     E
         *=====================================================================
         *aGetData: Get the data from the input record
         *=====================================================================
        P GetData         B
        D AlphaFld        S            256A   Varying Inz
        D DataType        S              1A   Inz
         /Free
           //^1Set the pointer to the Field Description Data Structure
           FldIdxPtr = FieldDSPtr;
           //^1Set the Data Pointer to the beginning of the data record
           DataPtr = %Addr(DataRecord);
           //^1Clear the FTP Output field
           Clear FTPField;
           //^1Read each field and move it from the input record to output
           For i = 1 to FieldCount;
             Select;
              //^1Skip this field because it is not in the export file
              When FldExportFlg = 'N';
              //^1This is a DATE field so reformat it to MM/DD/CCYY
              When Not (FldDateFmt = *Blanks);
                FTPField += FormatDate(FldDateFmt);
              //^1This is a CHARACTER field move it to the FTP output field
              When FldType = 'CHAR';
                AlphaFld = %Trim(%SubSt(DataRecord : FldOffset+1 :
   FldBytes));
                //^1If there is something in the alpha field
                If %Len(%Trim(AlphaFld)) > 0;
                  //^1Remove any quotes (") or commas (,) from the field
                  AlphaFld = %Trim(%XLate('"' : '''' : AlphaFld));
                  FTPField += Alpha_Sep + AlphaFld + Alpha_Sep;
                EndIf;
              //^1Extract the ZONED or PACKED data from the input buffer
              When FldType = 'NUMERIC' or FldType = 'DECIMAL';
                If FldType = 'NUMERIC';
                  DataType = 'S';
                Else;
                  DataType = 'P';
                EndIf;
                AlphaFld  = CvtNumFmt(%SubSt(DataRecord  :
                                             FldOffset+1 :
                                             FldBytes)   :
                                      DataType        :
                                      %Uns(FldLen)    :
                                      %Uns(FldDecPos) :
                                      'S'            );
                FTPField += FmtNumber(%SubSt(AlphaFld    :
                                             1           :
                                             FldLen)     :
                                      %Int(FldDecPos)   );
              //^1Define other field types here
              Other;
             EndSL;
             //^1If this is not the last field and the prior field was
             //^1exported to the FTP file, add the Column Separator
             If i < FieldCount and FldExportFlg = 'Y';
               FTPField += Colum_Sep;
             EndIf;
             //^1Position to the next Field Definition in the DS
             FldIdxPtr += FieldDSLen;
           EndFor;
           //^1Write the FTP Record to the output file
           Except WriteRec;
         /End-Free
        P GetData         E
         *================================================================
         *aSetSQLOptions: Insure the SQL options are set correctly
         *================================================================
        P SetSQLOptions   B
        C/EXEC SQL
         + Set Option
         +     Commit    = *NONE,
         +     CloSqlCsr = *ENDMOD
        C/END-EXEC
        P SetSQLOptions   E
         *=====================================================================
         *aDeclareCursor: Declare the SQL cursor used to retrieve field defs
         *=====================================================================
        P DeclareCursor   B
        ^1* Build the list of columns in the Table
        C/Exec SQL
         + Declare FileLayout Cursor for
         + SELECT ORDINAL_POSITION,
         +        Char(COLUMN_NAME,10),
         +        Char(TABLE_NAME,10),
         +        Char(TABLE_SCHEMA,10),
         +        Char(DATA_TYPE,10),
         +        LENGTH,
         +        Char(IfNull(Char(NUMERIC_SCALE),' '),3),
         +        STORAGE,0,'          ',' '
         +   FROM SYSCOLUMNS
         +   WHERE Table_Schema = :LibName
         +     AND Table_Name   = :FileName
         +   ORDER BY ORDINAL_POSITION
        C/End-Exec
        ^1* Open the Cursor
        C/Exec SQL
         + Open FileLayout
        C/End-Exec
        P DeclareCursor   E
         *================================================================
         *aValidSQLRecord: Fetch the next record from the SQL cursor
         *================================================================
        P ValidSQLRecord  B                   Export
        ^1* Procedure Interface
        D ValidSQLRecord  PI             1N
        C/EXEC SQL
         + Fetch from FileLayout into :FieldDS
        C/END-Exec
        C                   Return    (%SubSt(SQLStt:1:2)='00' or
        C                              %SubSt(SQLStt:1:2)='01')
        P ValidSQLRecord  E
         *================================================================
         *aCloseSQLCursor: Close the SQL Cursor
         *================================================================
        P CloseSQLCursor  B
        C/Exec SQL
         + Close FileLayout
        C/End-Exec
        P CloseSQLCursor  E
         *======================================================================
         *aIncludeInFile: Check to see if the field should be included in
   export
         *======================================================================
        P IncludeInFile   B                   Export
        ^1* Procedure Interface
        D IncludeInFile   PI             1N
        D  inFieldName                        Like(FldName) CONST
        D f               S              3P 0 Inz
        C                   Clear                   f
        C/EXEC SQL
         + SELECT Count(*) INTO :f
         +   FROM SYSCOLUMNS
         +   WHERE Table_Schema = :DDSLib
         +     AND Table_Name   = :DDSName
         +     AND COLUMN_NAME  = :inFieldName
        C/END-Exec
        C                   Return    (f > 0)
        P IncludeInFile   E
         *================================================================
         *aGetFieldCount: Get the # of fields in the file being processed
         *================================================================
        P GetFieldCount   B
        C/Exec SQL
         + SELECT Count(*) INTO :FieldCount
         +  FROM SYSCOLUMNS
         +  WHERE Table_Schema = :Lib
         +        and Table_Name = :File
        C/End-Exec
        P GetFieldCount   E
         *=====================================================================
         *aWriteHeaderRec: Write the FTP File Header Record
         *=====================================================================
        P WriteHeaderRec  B
         /Free
           FTPField = Alpha_Sep + %Trim(CBSName) + Alpha_Sep  + Colum_Sep +
                           %Trim(%EditC(FieldCount  : '3'))   + Colum_Sep +
                           %Trim(%EditC(RecordCount : '3'))   + Colum_Sep +
                           %Char(%Date() - %Days(1) : *USA);
           Except WriteRec;
         /End-Free
        P WriteHeaderRec  E
         *=====================================================================
         *aWrtFieldNames: Write the field names to the output record
         *=====================================================================
        P WrtFieldNames   B
         /Free
           //^1Set the first Field Description Data Structure
           FldIdxPtr = FieldDSPtr;
           //^1Clear the output field
           Clear FTPField;
           //^1Add each field name to the end of the output field
           For i = 1 to FieldCount;
             If FldExportFlg = 'Y';
               FTPField += Alpha_Sep + %Trim(FldName) + Alpha_Sep +
   Colum_Sep;
             EndIf;
             //^1Position to the next Field Definition in the DS
             FldIdxPtr += FieldDSLen;
           EndFor;
           //^1Remove the Column Separator from the end of the record
           FTPField = %SubSt(FTPField : 1 : %Len(FTPField) - 1);
           Except WriteRec;
         /End-Free
        P WrtFieldNames   E
         *=====================================================================
         *aFmtNumber: Format a Number that is in a string
         *=====================================================================
        P FmtNumber       B
        e* Prototype
        D FmtNumber       PI            50A   Varying
        D  inNbrValue                   50A   Varying CONST
        D  inDecPos                      3  0 CONST
         *^1Define Local Work Fields
        D DecPos          S                    Like(inDecPos)
        D IntIsNegative   S               N    Inz(*Off)
        D NbrValue        S                    Like(inNbrValue) Inz
        D Number          S             50A    Varying Inz
        D ValidChars      C                    '1234567890- '
        D n               S             31 15  Inz
        D x               S              5P 0  Inz
         /FREE
           NbrValue = inNbrValue;
           DecPos = inDecPos;
           //^1The negative sign is stored as an alpha character
           IntIsNegative = %Check('0123456789':%TrimR(NbrValue)) > 0;
           //^1Convert the negative character to its corresponding numeric
   value
           NbrValue = %XLate('}JKLMNOPQR' : '0123456789' : NbrValue);
           //^1The number has decimal positions
           If DecPos > 0;
             n = %Int(NbrValue);
             For x = 1 to DecPos;
               n /= 10;
             EndFor;
             Number = %SubSt(%Trim(%EditC(n : 'L')) : 1 :
                        (%CheckR(ValidChars : %Trim(%EditC(n :
   'L')))+DecPos));
            Else;
             //^1The number does not have any decimal positions
             Number = %Trim(%EditC(%Dec(NbrValue:31:0):'L'));
           EndIf;
           If IntIsNegative;
             Number = '-' + %Trim(Number);
           EndIf;
           If %Len(Number) < 1;
             Number += '0';
           EndIf;
           Return Number;
         /END-FREE
        P FmtNumber       E
         *=====================================================================
         *aFormatDate: Format the date field into MM/DD/CCYY format
         *=====================================================================
        P FormatDate      B
        e* Prototype
        D FormatDate      PI            10A   Varying
        D  FromFormat                         Like(XAPDateF) CONST
         *^1Define Local Work Fields
        D NumericDate     S              8S 0 Inz
         /FREE
          //^1Extract the Date from the input buffer
          If FldType = 'NUMERIC';
            NumericDate = ZonedToInt(DataPtr+FldOffset:FldLen:0);
           ElseIf FldType = 'DECIMAL';
             NumericDate = PackedToInt(DataPtr+FldOffset:FldLen:0);
          EndIf;
          //^1Convert the NumericDate to an alpha MM/DD/CCYY field
          Monitor;
            Select;
              When NumericDate = *Zeros;
                RETURN '';
              When FromFormat = '*MDY';
                RETURN %Char(%Date(NumericDate : *MDY):*USA);
              When FromFormat = '*DMY';
                RETURN %Char(%Date(NumericDate : *DMY):*USA);
              When FromFormat = '*YMD';
                RETURN %Char(%Date(NumericDate : *YMD):*USA);
              When FromFormat = '*JUL';
                RETURN %Char(%Date(NumericDate : *JUL):*USA);
              When FromFormat = '*LONGJUL';
                RETURN %Char(%Date(NumericDate : *LONGJUL):*USA);
              When FromFormat = '*USA';
                RETURN %Char(%Date(NumericDate : *USA):*USA);
              Other;
                RETURN '';
            EndSL;
          On-Error;
            RETURN '';
          EndMon;
         /END-FREE
        P FormatDate      E

     ----------------------------------------------------------------------

   Find just what you're after with the new, more precise MSN Search - try it
   now!





As an Amazon Associate we earn from qualifying purchases.

This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.