01 - Programming (EN)01a - RPG (EN)

RPG – FAQ & Howtos (EN Part.2)

Last Updated on 27 April 2020 by Roberto De Pedrini

Part 1 of this FAQ, the first 10 Questions and Answers are available at this link: RPG – FAQ & Howtos (IT Part.1)

RPG-FAQ-013: Programming in RPG / Free – A Beginner’s Tutorial

For those who start working with RPG Free and Full-Free there are these two excellent guides:

RPG-FAQ-012: Reduced expressions – short expressions (+ = …)

In the assignments of value to the variables in RPG Free we can use the “short expressions”, stolen from the language C … they are comfortable because you save something in writing the code but you have to be careful not to confuse the position of the equal sign (=) …. for example “i + = 1” increases the value of i by one while “i = + 1” sets i to the value 1 positive!

i = i + 1; ---> equals ---> i + = 1;
i = i-1; ---> equals ---> i- = 1;
r = r * 2; ---> equals ---> r * = 2;  
r = r / 2; ---> equals ---> r / = 2;  

We can also use these functions by managing the round

eval (h) r / = 2;


RPG-FAQ-013: Datastructure Likerec vs DS extname template

This was discussed in October 2019 on the Midrange.com RPG-L discussion group: what is the difference between the two ways of defining a DS as a qualified template:

Method 1
dcl-f CUSTFILE keyed template qualified;
dcl-ds cust_t likeRec (CUSTFILE.CUSTFILER) template;
dcl-s custName like (cust_t.name); 

Method 2
dcl-ds cust_t extName ('CUSTFILE') qualified template end-ds;
dcl-s custName like (cust_t.name);
 

The two different methods come to the same result … in both cases we can define the “custName” variable as “cust_t.name” external field taken from the “CUSTFILE” table … we could say that the method with extName does not oblige us to define our file in the ‘F’ (or rather DCL-F) specifications.

Another difference between the two methods lies in the syntax of the “DCL-DS” definition specifications: with EXTNAME we must indicate END-DS while with LIKEREC no: perhaps not everyone knows that with DLC-DS ExtName we can add fields outside the DS , let’s see an example:

 dcl-ds myds extname (mytable);
  extraFld1 char (10);
  extraFld2 char (15);
end-ds;

RPG-FAQ-014: Different COMMIT LEVELs in the same source?

From a question on the Midrange.com mailing list:

I have a program that has two different steps … in the first it creates a table in QTEMP (which is possible only with commit = * none) and in the second step it executes a JSON_TABLE reading the JSON document with the get_CLOB_from_file () function (which is not possible if commit = * none): it is possible to change the commit level in the same program?

The answer comes from the forum:

  • Check isolation level commit in individual SQL statements: something like INSERT INTO QTEMP.MYFILE () WITH NC
  • Divide the logic into two different programs or service programs with each its commit level
  • Use commit to “close” transactions and use isolation level between commits
    • exec sql commit; // end running transaction
    • exec sql set transaction isolation level ur; // change to commit * CHANGE
    • // do your commited stuff
    • exec sql commit; // end transaction
    • set transaction isolation level n / a; // change to commit * NONE
    • // do some uncommited stuff
    • exec sql commit;
    • set transaction …
  • Instead of creating the temporary table with CREATE TABLE QTEMP.XXX it is preferable to use DECLARE GLOBAL TEMPORARY TABLE X … which has the advantage of being able to use the COMMIT control, which is not possible for the QTEMP tables.

RPG-FAQ-015: Timestamp precision in RPG

RPG %Timestamp BIF resolve only milliseconds: if you need more granularity you can use the QWCCVTDT API (up to microseconds) or SQL Embedded. Have a look at this simpe RPG code by Vernon Hamberg

       dcl-s tstmp06 timestamp;
        dcl-s tstmp12 timestamp(12);
        dcl-s tstmp06from12 timestamp;
        dcl-s tstmp12from06 timestamp(12);

        dcl-s tstmp06sys timestamp;
        dcl-s tstmp12sys timestamp(12);

        dcl-s tstmp06s timestamp;
        dcl-s tstmp12s timestamp(12);
        dcl-s tstmp06sfrom12 timestamp;
        dcl-s tstmp12sfrom06 timestamp(12);

        // Use BIF timestamp alone
        tstmp06 = %timestamp;
        tstmp12 = %timestamp(*sys : 12);
        tstmp06from12 = %timestamp(*sys : 12);
        tstmp12from06 = %timestamp;

        // Use *SYS in BIF
        tstmp06sys = %timestamp(*sys : 6);
        tstmp12sys = %timestamp(*sys : 12);

        // Use SQL current timestamp
        exec sql
          set :tstmp06s = current timestamp;
        exec sql
          set :tstmp12s = current timestamp(12);
        exec sql
          set :tstmp06sfrom12 = current timestamp(12);
        exec sql
          set :tstmp12sfrom06 = current timestamp;

        *inlr = *on; 

Here the results:

 > EVAL tstmp06
   TSTMP06 = '2019-12-08-04.04.22.647000'
 > EVAL tstmp12
   TSTMP12 = '2019-12-08-04.04.22.647000000000'
 > EVAL tstmp06from12
   TSTMP06FROM12 = '2019-12-08-04.04.22.647000'
 > EVAL tstmp12from06
   TSTMP12FROM06 = '2019-12-08-04.04.22.647000000000'
 > EVAL tstmp06sys
   TSTMP06SYS = '2019-12-08-04.04.22.647000'
 > EVAL tstmp12sys
   TSTMP12SYS = '2019-12-08-04.04.22.647000000000'
 > EVAL tstmp06s
   TSTMP06S = '2019-12-08-04.04.22.647548'
 > EVAL tstmp12s
   TSTMP12S = '2019-12-08-04.04.22.647802819335'
 > EVAL tstmp06sfrom12
   TSTMP06SFROM12 = '2019-12-08-04.04.22.647935'
 > EVAL tstmp12sfrom06
   TSTMP12SFROM06 = '2019-12-08-04.04.22.648147000000' 

RPG-FAQ-016: How to flip an indicator in RPG

Of course we are talking about ind … variables, not numerical indicators that I hope you will no longer use in the new RPG sources. It’s a simple thing, maybe it’s not even worth dedicating a FAQ on this Blog … but I realize that I’ve often found myself in the condition to “invert” sign of an indicator (the classic function key that activates / deactivates a setting) and I’ve often used 5 lines of code instead of only one: have a look at the following code:

dcl-s view Details ind inz(*off); 

// Long version, up to five lines of code
...
 // Flip viewDetails indicator
    if viewDetails=*on;
       viewDetails=*off;
    else;
       viewDetails=*on;
    endif;


 // Here the short version ... one row only!
 ...
 // Flip viewDetails indicator
     viewDetails= not viewDetails;
 

RPG-FAQ-017: How to export source to GIT

If you need to export your source files to GIT you can schedule a simple job like in this Niels Liisberg’s Github Gist:

Niels Liisberg: Export Source to GIT

Or you can try this great Richar Shoen’s utility “IforGit”: you can work with your source in a Git repo with RDI and SEU too.

Mobigogo IforGit

RPG-FAQ-018: *PCML and Java Procedure dentro RPG

To avoid error “RNF0302 – Errors were found while generating the program information to be placed in the module” when you have an RPG with PGMINFO(*PCML:*MODULE) and some Java Procedure in the source you have to use PGMINFO(*NO) keyword on every Externa Java Procedur – Program Interface PI:

ctl-opt pgminfo(*PCML: *MODULE: *DCLCASE);
Dcl-Pr myrpgws ExtPgm('MYRPGWS');
         *n Char(8)    Const;
         *n Char(8)    Const;
         *n Char(1)    Const;
         *n Char(1000);
End-Pr;
*
Dcl-Pi myrpgws;
         InSundayDate   Char(8)    Const;
         InSaturdayDate Char(8)    Const;
         InFinalFlag    Char(1)    Const;
         OutResults     Char(1000);
End-Pi;
...
...
Dcl-Proc newString Export;
     D newString       PI              O   Class(*java: jStrConst) PGMINFO(*NO)
     D  pString                   32767A   Const
....

RPG-FAQ-019: *PCML and varying-length arrays

If you need varying length arrays on a RPG with PGMINFO(*PCML) you need the *V7 option:

ctl-opt pgminfo(*PCML: *MODULE:*DCLCASE: *V7);

RPG-FAQ-020: Replace an in-use-object

We know that when we are compiling a program with REPLACE(*YES) our original object is moved to the QRPLOBJ library and running jobs doesn’t care about it.

If you need to do something similar to this process without a real source-compile you could think about QLIRNMO API, a dedicated API who move one object to a new library or name and replace the object with a given new object:

Read about QLIRNMO API here and take a look at this thread on CODE400.com

Here’s the source of the program who call QLIRNMO API

https://code400.com/forum/forum/iseries-programming-languages/free-format/1756-the-rename-object-api-qlirnmo
The API (from https://code400.com/forum/forum/iseries-programming-languages/free-format/1756-the-rename-object-api-qlirnmo)

      * PROGRAM - @RENAME
      * PURPOSE - rename object use API QLIRNMO
      * WRITTEN -
      * AUTHOR  -

      * PROGRAM DESCRIPTION
      *--------------------------------------------------------
      *
      * Entry Plist
      *
     d @RENAME         pr
     d  OldFile                      10
     d  OldLib                       10
     d  NewFile                      10
     d  NewLib                       10
     d  inType                       10
      *
     d @RENAME         pi
     d  OldFile                      10
     d  OldLib                       10
     d  NewFile                      10
     d  NewLib                       10
     d  inType                       10
      *
      * Variable Definition
      *
     d Error           s             34
     d FromObject      s             20
     d ObjectType      s             10
     d ToObject        s             20
     d Replace         s              1
      *
      * Program Info
      *
     d                SDS
     d  @PGM                 001    010
     d  @PARMS               037    039  0
     d  @MSGDTA               91    170
     d  @MSGID               171    174
     d  @JOB                 244    253
     d  @USER                254    263
     d  @JOB#                264    269  0
       //
       //  external calls
       //
     d $Rename         pr                  extpgm('QLIRNMO')
     d   fromObject                  20
     d   ObjectType                  10
     d   ToObject                    20
     d   Replace                      1
     d   Error                       34

      /Free

        //--------------------------------------------------------
        // MAIN LINE
        //--------------------------------------------------------


                   // take parms and rename --and/or-- move object

                FromObject = OldFile + OldLib;
                ToObject = NewFile + NewLib;
                ObjectType = InType;
                replace = '1';
                $rename(FromObject : ObjectType : ToObject : Replace : Error);


               *inlr = *on;


        //--------------------------------------------------------
        // *Inzsr -  one time run subroutine
        //--------------------------------------------------------

             begsr *inzsr;


             endsr;
      /End-Free 
--- Roberto De Pedrini Faq400.com
About author

Founder of Faq400 Srl, IBM Champion, creator of Faq400.com and blog.faq400.com web sites. RPG developer since I was wearing shorts, strong IBM i supporter, I have always tried to share my knowledge with others through forums, events and courses. Now, with my company Faq400 Srl, I help companies to make the most of this great platform IBM i.

Leave a Reply

%d bloggers like this: