DRDA example: ILE RPG program

This example program is written in the ILE RPG programming language.

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.
Figure 1. ILE RPG program example
 ...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 .
       //***************************************************************
       //                                                              *
       //   DESCRIPTIVE NAME = D-DB sample application                 *
       //                      Reorder point processing                *
       //                      IBM i                                   *
       //                      ILE RPG                                 *
       //                                                              *
       //   FUNCTION =  This module processes the PART_STOCK table and *
       //               for each part below the ROP (reorder point)    *
       //               creates a supply order and prints a report.    *
       //                                                              *
       //                                                              *
       //      INPUT = Parameters explicitly passed to this function:  *
       //                                                              *
       //              local_db         Local db name                  *
       //              remote_db        Remote db name                 *
       //                                                              *
       //    TABLES =  PART_STOCK       - Local                        *
       //              PART_ORDER       - Remote                       *
       //              PART_ORDLN       - Remote                       *
       //              SHIPMENTLN       - Remote                       *
       //                                                              *
       //   To be compiled with COMMIT(*CHG) RDB(remotedbname)         *
       //                                                              *
       //   Invoke by : CALL DDBPT6RG PARM(localdbname remotedbname)   *
       //                                                              *
       //   Cursors will be closed implicitly (by connect) because     *
       //   there is no reason to do it explicitly                     *
       //                                                              *
       //***************************************************************

       // Parameters
       dcl-pi *n;
          local_db char(18);   // Sample local database
          remote_db char(18);  // Sample remote database
       end-pi;

       dcl-f QPRINT printer(40) oflind(*INOF);

       dcl-s short_t int(5) template;
       dcl-s long_t int(10) template;

       dcl-s loc char(4) inz('SQLA');    // dealer's database name
       dcl-s part_table char(5);         // part number in table part_stock
       dcl-s quant_table like(long_t);   // quantity in stock, tbl part_stock
       dcl-s rop_table like(long_t);     // reorder point    , tbl part_stock
       dcl-s eoq_table like(long_t);     // reorder quantity , tbl part_stock
       dcl-s next_num like(short_t);     // next order nbr,table part_order
       dcl-s contl like(short_t);        // continuation line, tbl order_line
       dcl-s ord_table like(short_t);    // order nbr.       , tbl order_line
       dcl-s orl_table like(short_t);    // order line       , tbl order_line
       dcl-s qty_table like(long_t);     // ordered quantity , tbl order_line
       dcl-s ind_null like(short_t);     // null indicator for qty_table

       dcl-s qty_req like(long_t);
       dcl-s qty_rec like(long_t);
       dcl-s rtCod1 like(short_t);
       dcl-s rtCod2 like(short_t);
       dcl-s first_order ind;
       dcl-s abnormal_end ind;


       //***************************************************************
       //    SQL cursor declarations                                   *
       //***************************************************************

       // Next part which stock quantity is under reorder points qty
       EXEC SQL DECLARE NEXT_PART CURSOR FOR
                 SELECT PART_NUM,
                        PART_QUANT,
                        PART_ROP,
                        PART_EOQ
                 FROM   PART_STOCK
                 WHERE  PART_ROP > PART_QUANT
                   AND  PART_NUM > :part_table
                 ORDER BY PART_NUM ASC;

       // Orders which are already made for current part
       EXEC SQL DECLARE NEXT_ORDER_LINE CURSOR FOR
                 SELECT A.ORDER_NUM,
                        ORDER_LINE,
                        QUANT_REQ
                 FROM   PART_ORDLN A,
                        PART_ORDER B
                 WHERE  PART_NUM  = :part_table
                 AND    LINE_STAT  <> 'C'
                 AND    A.ORDER_NUM = B.ORDER_NUM
                 AND    ORDER_TYPE  = 'R';

       //***************************************************************
       //     SQL return code handling                                 *
       //***************************************************************
       EXEC SQL WHENEVER SQLERROR GO TO db_error;
       EXEC SQL WHENEVER SQLWARNING CONTINUE;

       //****************************************************************
       //    Process  - Main program logic                              *
       //    Main procedure works   with local database                 *
       //****************************************************************

       // Clean up to permit re-running of test data
       exsr cleanup;
          EXEC SQL DISCONNECT ALL;

       dou rtCod1 = 100;
          EXEC SQL CONNECT   TO  :local_db;
          EXEC SQL OPEN      NEXT_PART;
          EXEC SQL FETCH     NEXT_PART
                     INTO     :part_table,
                              :quant_table,
                              :rop_table,
                              :eoq_table;
          rtCod1 = SQLCOD;
          EXEC SQL COMMIT;
          if rtCod1 <> 100;
             exsr check_order;
          endif;

       enddo;

       exsr finish;
       return;      // Normal return from program


       //****************************************************************
       //    SQL return code handling on error situations               *
       //****************************************************************

     C     db_error      TAG

       except err_lines;
       abnormal_end = *ON;
       EXEC SQL WHENEVER  SQLERROR  CONTINUE;

       EXEC SQL ROLLBACK;

       EXEC SQL WHENEVER  SQLERROR  GO TO  db_error;

       exsr finish;
       return;      // Return after db_error processing

       //**************************************************************
       //  The end of the main procedure                              *
       //**************************************************************

       //**************************************************************
       // Subroutines                                                 *
       //**************************************************************

       begsr finish;

          EXEC SQL CONNECT   RESET;

          if not abnormal_end;
             except end_info;
          endif;
          *INLR = *ON;
       endsr;

       begsr check_order;
          //****************************************************************
          // Checks what is current order and shipment status for the part.*
          // if ordered and shipped is less than reorder point of part,    *
          // performs a subroutine which makes an order.                   *
          //****************************************************************

          rtCod2 = 0;
          qty_req = 0;
          qty_rec = 0;

          EXEC SQL CONNECT   TO   :remote_db;

          EXEC SQL OPEN      NEXT_ORDER_LINE;

          dow rtCod2 <> 100;

             EXEC SQL FETCH     NEXT_ORDER_LINE
                        INTO     :ord_table,
                                 :orl_table,
                                 :qty_table;

             if SQLCOD = 100;
                rtCod2 = 100;
             else;
                qty_req += qty_table;
                EXEC SQL SELECT    SUM(QUANT_RECV)
                            INTO    :qty_table:ind_null
                            FROM    SHIPMENTLN
                            WHERE   ORDER_LOC  = :loc
                              AND   ORDER_NUM  = :ord_table
                              AND   ORDER_LINE = :orl_table;
                if ind_null >= 0;
                   qty_rec += qty_table;
                endif;
             endif;
          enddo;

          EXEC SQL CLOSE NEXT_ORDER_LINE;

          qty_table = quant_table + qty_req;
          qty_rec -= qty_table;

          if rop_table > qty_table;
             exsr make_order;
          endif;

          EXEC SQL COMMIT;

       endsr;  // check_order


       begsr make_order;
          //****************************************************************
          // Makes an order. If first time, performs the subroutine, which *
          // searches for new order number and makes the order header.     *
          // after that, makes order lines using reorder quantity for the  *
          // part. For every ordered part, writes a line on report.        *
          //****************************************************************

          if first_order = *OFF;
             exsr start_order;
             first_order = *ON;
             except header;
          endif;

          contl += 1;
          EXEC SQL INSERT
                      INTO    PART_ORDLN
                             (ORDER_NUM,
                              ORDER_LINE,
                              PART_NUM,
                              QUANT_REQ,
                              LINE_STAT)
                    VALUES   (:next_num,
                              :contl,
                              :part_table,
                              :eoq_table,
                              'O');

           if *INOF;
              except header;
           endif;
           except detail;

       endsr; // make_order

       begsr start_order;
         //****************************************************************
         // Searches for next order number and makes an order header      *
         // using that number. Writes also headers on report.             *
         //****************************************************************

          EXEC SQL SELECT    (MAX(ORDER_NUM) + 1)
                      INTO    :next_num
                      FROM    PART_ORDER;

          EXEC SQL INSERT
                      INTO    PART_ORDER
                             (ORDER_NUM,
                              ORIGIN_LOC,
                              ORDER_TYPE,
                              ORDER_STAT,
                              CREAT_TIME)
                    VALUES   (:next_num,
                              :loc,
                              'R',
                              'O',
                              CURRENT TIMESTAMP);

       endsr; // start_order


       begsr cleanup;
         //****************************************************************
         // This subroutine is only required in a test environment
         // to reset the data to permit re-running of the test
         //****************************************************************

          EXEC SQL CONNECT   TO   :remote_db;

          EXEC SQL DELETE
                      FROM    PART_ORDLN
                     WHERE    ORDER_NUM IN
                             (SELECT    ORDER_NUM
                                FROM    PART_ORDER
                                WHERE   ORDER_TYPE = 'R');

          EXEC SQL DELETE
                      FROM    PART_ORDER
                     WHERE    ORDER_TYPE = 'R';

          EXEC SQL COMMIT;

       endsr; // cleanup


     O* Output lines for the report                                   *
     O*****************************************************************
     O*
     OQPRINT    E            header            2
     O                                         +  0 '***** ROP PROCESSING'
     O                                         +  1 'REPORT *****'
     O*
     OQPRINT    E            header      2
     O                                         +  0 '   ORDER NUMBER = '
     O                       next_num      Z   +  0
     O*
     OQPRINT    E            header      1
     O                                         +  0 '------------------------'
     O                                         +  0 '---------'
     O*
     OQPRINT    E            header      1
     O                                         +  0 '    LINE     '
     O                                         +  0 'PART          '
     O                                         +  0 'QTY    '
     O*
     OQPRINT    E            header      1
     O                                         +  0 '   NUMBER   '
     O                                         +  0 'NUMBER      '
     O                                         +  0 'REQUESTED '
     O*
     OQPRINT    E            header      1  1
     O                                         +  0 '------------------------'
     O                                         +  0 '---------'
     O*
     OQPRINT    EF           detail      1
     O                       contl         Z   +  4
     O                       part_table        +  3
     O                       eoq_table     1   +  3
     O*
     OQPRINT    E            end_info    2
     O                                         +  0 '------------------------'
     O                                         +  0 '---------'
     OQPRINT    E            end_info    1
     O                                         +  0 'NUMBER OF LINES '
     O                                         +  0 'CREATED = '
     O                       contl         Z   +  0
     O*
     OQPRINT    E            end_info    1
     O                                         +  0 '------------------------'
     O                                         +  0 '---------'
     O*
     OQPRINT    E            end_info    2
     O                                         +  0 '*********'
     O                                         +  0 ' END OF PROGRAM '
     O                                         +  0 '********'
     O*
     OQPRINT    E            err_lines   2
     O                                         +  0 '** ERROR **'
     O                                         +  0 '** ERROR **'
     O                                         +  0 '** ERROR **'
     OQPRINT    E            err_lines   1
     O                                         +  0 '* SQLCOD:'
     O                       SQLCOD        M   +  0
     O                                           33 '*'
     OQPRINT    E            err_lines   1
     O                                         +  0 '* SQLSTATE:'
     O                       SQLSTT            +  2
     O                                           33 '*'
     OQPRINT    E            err_lines   1
     O                                         +  0 '** ERROR **'
     O                                         +  0 '** ERROR **'
     O                                         +  0 '** ERROR **'