× 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.



Rich,


I also recommend that you write directly to the IFS.

In addition, you might want to consider replacing the native RPG I/O to InFile 
with embedded SQL.  Just make sure you FETCH more than 1 row at a time.  I'd 
recommend at fetching at least 100 rows if not more.

Charles Wilt
iSeries Systems Administrator / Developer
Mitsubishi Electric Automotive America
ph: 513-573-4343
fax: 513-398-1121
 

> -----Original Message-----
> From: rpg400-l-bounces@xxxxxxxxxxxx
> [mailto:rpg400-l-bounces@xxxxxxxxxxxx]On Behalf Of Rich Dotson
> Sent: Tuesday, May 24, 2005 4: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!
> -- 
> This is the RPG programming on the AS400 / iSeries (RPG400-L) 
> mailing list
> To post a message email: RPG400-L@xxxxxxxxxxxx
> To subscribe, unsubscribe, or change list options,
> visit: http://lists.midrange.com/mailman/listinfo/rpg400-l
> or email: RPG400-L-request@xxxxxxxxxxxx
> Before posting, please take a moment to review the archives
> at http://archive.midrange.com/rpg400-l.
> 
> 


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.