01 - Programmazione01a - RPG

RPG – FAQ & Howtos (IT Part.2)

Last Updated on 27 Aprile 2020 by Roberto De Pedrini

La parte 1 di queste FAQ, le prima 10 Domande-Risposte sono disponibili a questo link: RPG – FAQ & Howtos (IT Part.1)

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

Per chi inizia a lavorare con RPG Free e Full-Free ci sono queste due ottime guide:

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

Nelle assegnazioni di valore alle variabili in RPG Free possiamo utilizzare le “short expressions”, rubate dal linguaggio C… sono comode perché si risparmia qualcosa in scrittura del codice ma bisogna prestare attenzione a non confondere la posizione del segno uguale (=) …. ad esempio ” i+=1″ incrementa di uno il valore di i … mentre “i=+1” setta i al valore 1 positivo!

i=i+1; --->equivale a ---> i+=1;
i=i-1; --->equivale a ---> i-=1;
r=r*2; --->equivale a ---> r*=2;  
r=r/2; --->equivale a ---> r/=2;  

Possiamo anche usare queste funzioni gestendo l'arrotondameno

eval(h) r/=2;


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

Se ne è discusso in Ottobre 2019 sul gruppo di discussione RPG-L di Midrange.com: che differenza c’è tra i due modi di definire una DS come 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);
 

I due metodi diversi arrivano allo stesso risultato … in entrambi i casi possiamo definire la variabile “custName” come “cust_t.name” campo esterno preso dalla tabella “CUSTFILE” … potremmo dire che il metodo con extName non obbliga a definire nelle specifiche ‘F’ (o meglio DCL-F) il nostro file.

Un’altra differenza tra i due metodi sta nella sintassi delle specifiche di definizione “DCL-DS”: con EXTNAME dobbiamo indicare END-DS mentre con LIKEREC no: forse non tutti sanno che con DLC-DS ExtName possiamo aggiungere dei campi esterni alla DS, vediamo un esempio:

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

RPG-FAQ-014: Differenti COMMIT LEVEL nello stesso source?

Da una domanda sulla mailing list di Midrange.com:

Ho un programma che ha due differenti step … nel primo crea una tabella in QTEMP (cosa possibile solo con commit=*none) e nel secondo passo esegue un JSON_TABLE leggendo il documento JSON con la funzione get_CLOB_from_file() (cosa non possibile se commit=*none): e’ possibile cambiare il livello di commit nello stesso programma?

Ecco le risposte dal forum:

  • Controllare il commit isolation level nelle singole istruzioni SQL: qualcosa come INSERT INTO QTEMP.MYFILE () WITH NC
  • Dividere la logica su due programmi o service program differenti con ognuno il suo livello di commit
  • Utilizzare il commit per “chiudere” le transazioni e utilizzare l’isolation level tra diversi commit
    • 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 nc; // change to commit *NONE
    • // do some uncommited stuff
    • exec sql commit;
    • set transaction …
  • Invece di creare la tabella temporanea con CREATE TABLE QTEMP.XXX è preferibile utilizzare DECLARE GLOBAL TEMPORARY TABLE X… che ha come vantaggio quello di poter utilizzare il controllo di COMMIT, cosa non possibile per le tabelle della QTEMP.

RPG-FAQ-015: Timestamp con precisione oltre al “millisecondo”

La BIF %Timestamp RPG non arriva oltre alle 3 cifre dopo i secondi … (millisecondo) … In alcuni casi potrebbe essere utile recuperare une precisione superiore, o tramite la API QWCCVTDT (fino al microsecondo) oppure con SQL Embedded: ecco un piccolo programma RPG proposto da Vernon Hamberg su Midrange.com:

       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; 

Con il seguente risultato:

 > 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: Invertire “segno” ad un indicatore RPG

Naturalmente stiamo parlando di variabili di tipo ind … non di indicatori numerici che spero non utilizziate più nei nuovi sorgenti RPG. E’ una cosa semplice, forse non vale la pena neanche di dedicarci una FAQ su questo Blog … ma mi rendo conto che mi sono trovato spesso nella condizione di “invertire” segno di un indicatore (il classico tasto funzione che attiva/disattiva una impostazione) e di aver spesso utilizzato ben 5 righe di codice invece di una sola

dcl-s viewDetails 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: Come portare su GIT i sorgenti dentro SOURCE-FILES della QSYS.LIB

In questo Github GIST di Niels Liisberg vediamo una interessante tecnica per copiare tutti i nostri sorgenti (anche da diverse librerie e file-sorgenti) a directory IFS come file di testo per poi sincronizzarle su un progetto GIT, GITHUB ecc.

Niels Liisberg: Export Source to GIT

Oppure puoi lavorare con GIT anche direttamente da RDI con il plung EGIT … o anche da Rdi e SEU con il progetto “iForGit”

Mobigogo “iForGit”

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

Se un programma RPG che vogliamo pubblicare come Web Service contiene delle Procedure Java potremmo ricevere l’errore “RNF0302 – Errors were found while generating the program information to be placed in the module” in fase di compilazione nella costruzione del “documento” PCML …

Per ovviare al problema dobbiamo indicare sulla Program Interface della procedure JAVA la keyword PGMINFO(*NO)

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 e varying-lenght arrays

Per gestire arrays a lunghezza variabile in programmi RPG con *PCML bisogna aggiungere l’opzione *V7 nella keyword PGMINFO():

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

RPG-FAQ-020: Sostituire programmi Oggetto in USO

Sappiamo che quando compiliamo un programma con l’opzione REPLACE(*YES), l’oggetto originale, prima di essere sostituito con il nuovo “compilato” viene spostato nella QRPLOBJ ed eventuali programmi in esecuzione continuano a funzionare utilizzando l’oggetto nella nuova posizione (QRPLOBJ) con un nome (Generato in fase di pre-compilazione).

Se avessimo la necessità di simulare questo tipo di gestione degli oggetti senza una vera e propria compilazione … quindi dobbiamo sostituire un oggetto programma mantenendo funzionanti eventuali JOB attivi al momento, possiamo ricorrere ad una API di sistema: QLIRNMO API

Come documentato nella IBM Knowledge Center la API QLIRNMO permette di spostare un oggetto, rinominarlo e sostiuirlo con un altro oggetto sempre nella stessa posizione … praticamente quello che fa il pre-compilatore con la QRPLOBJ:

In questa discussione di CODE400.com vediamo una interfaccia all’uso della API:

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 
Related Posts
DB2 for i SQL – Stringhe – POSSTR-LOCATE-LOCATE_IN_STRING (IT)

Introduzione Spesso, nelle nostre applicazioni, abbiamo la necessità di lavorare con le stringhe di testo e l'SQL del DB2 può Read more

DB2 for i & SQL – FAQ & Howto (Part. 1) (IT)

Database DB2 e SQL ... forse lo strumento più potente e completo che abbiamo sulla piattaforma IBM i: ecco una Read more

Annuncio IBM i 7.4

Arriva direttamente con l'uovo di Pasqua questo annuncio IBM per le novità della versione IBM i 7.4, versione iNext secondo Read more

Generated Always Columns – Approfondimenti (IT)

Introduzione "Generated Always Column": sono colonne, campi, di una tabella il cui contenuto è controllato direttamente dal sistema ... e Read more

--- Roberto De Pedrini Faq400.com
About author

Founder di Faq400 Srl, IBM Champion, ideatore del sito Faq400.com e del Blog blog.faq400.com. Sviluppatore RPG da quando avevo i pantaloni corti, forte sostenitore della piattaforma IBM i (ex AS400), ho sempre cercato di convididere le mie conoscenze con gli altri tramite forum, eventi e corsi. Oggi, tramite Faq400 Srl, cerchiamo di aiutare le aziende a sfruttare al meglio questa fantastica piattaforma IBM i.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *