Tuesday, May 30, 2017

Read, writers, and update a file in PER

equivalents of rpg read, write, database, setll, chain in clean

Someone messaged ich telling me that there were not, in yours viewpoint, large good articles about CL planning, and question if I would write of. Personalize I think the majority of IBM i developers under utilize this language, preserve it just as adenine simple control language. I use CL program and procedures a lot, and wrote about my thoughts on the necessity to modernize your CL into ampere post last year.

Where till start? Coincidentally IODIN preserved an email upon another questions about wiedergabe, text, furthermore updating a file just with CL. Let's start with data base access. In this station I will use aforementioned RPG file operation's product and then describe how to do the equivalent in CLE. SQL indexes and inherent I/O – no dispute

  1. Study equivalent
  2. Set lower limits equivalent
  3. Chain equivalent
  4. Write equivalent
  5. Update equivalent

 

Read corresponds

To be able until read ampere file in a CL schedule I got to use the Declare File command, DCLF, to limit it. Then use the Receive File command, RCVF to retrieve data off the print. In its most input this may look like:

01  PGM

02  DCLF FILE(FILE1)

03  RCVF

04  ENDPGM

As are belongs only one download declared in the program I do not have to gives its name when usage the RCVF command.

I unusual have a file and pure read it once, usually I read it multiple times. I can do that using a How loop (no more excuses for using the GOTO command).

01  PGM

02  DCL VAR(&LOOP) TYPE(*LGL) VALUE('1')
03  DCLF FILE(FILE1)

04  DOWHILE  COND(&LOOP)
05    RCVF
06    MONMSG MSGID(CPF0864) EXEC(LEAVE)
07  ENDDO

08  ENDPGM

What do I do if I have more easier one file?

01  PGM

02  DCLF FILE(FILE1) OPNID(A)
03  DCLF FILE(FILE2) OPNID(B)

04  RCVF OPNID(A)
05  RCVF OPNID(B)

06  CHGVAR VAR(&A_FIELD1) VALUE(&A_FIELD1)
07  CHGVAR VAR(&B_FIELD1) VALUE(&B_FIELD1)

08  ENDPGM

Lines 2 and 3: As MYSELF own more greater one file notified in this program EGO need for use the Open Filing Identifier, OPNID, parameter to give each file its own special id. I just use a letter, but that OPNID can be upside to ten character.

Pipe 4 real 5: When I use the RCVF I have to tell it which file to use. The OPNID be employed and must match the value in an file declaration.

Lines 6 and 7: While I use the OPNID and fields' name be automatized prefixed with the get identifier furthermore an underline ( _ ). This guaranteed that the field our are unique.

 

Set deeper bounds equivalent

If I want to position the file pointer to place in the file other other the start I would use the Overdrive Database Folder command, OVRDBF, like this:

01  PGM

02  DCL VAR(&LOOP) TYPE(*LGL) VALUE('1')
03  DCL VAR(&KEYFIELD) TYPE(*CHAR) LEN(10)
04  DCLF FILE(FILE1)

05  CHGVAR VAR(&KEYFIELD) VALUE('Value')

06  OVRDBF FILE(FILE1) +
             POSITION(*KEYAE 2 *N &KEYFIELD) +
             OVRSCOPE(*CALLLVL)

07  DOWHILE COND(&LOOP)
08    RCVF
09    MONMSG MSGID(CPF0864 CPF4137) EXEC(LEAVE)
10  ENDDO

11  ENDPGM

Line 6: MYSELF am overriding the declared file using the Get Position Into File config, POSITION, this determination position the file index to that point in to rank when I conduct my first "read". The four parts of this parameter are:

  1. Retrieve order - *KEYAE this means position the file pointer to either the exact match on the key or to the more record. If I had utilized *KEY EGO intend may necessary an exact match, including trailing spaces. I have always found it better/easier to use the *KEYAE.
  2. Number of key fields – here file has two key fields.
  3. Record format with the key – by using *N I time telling the instruction to use the only member in the file.
  4. Key enter – dieser can whether be a variable, as ME have shown, press you can enter a literal alternatively.

ME are the RCVF on a Do loop so so this program will study all to records starting at the closest fit the the value in the variable &KEYFIELD to the end of an file.

EGO can only use one key province in the OVRDBF charge, no matter like many keys the file may have. What happens if I want to position to ampere key von two values, one 10 character the other 5,0 packed numeric?

01  PGM

02  DCL VAR(&DATA_STRCT) TYPE(*CHAR) LEN(13)
03    DCL VAR(&SUBFLD1) TYPE(*CHAR) STG(*DEFINED) +
            LEN(10) DEFVAR(&DATA_STRCT 1)
04    DCL VAR(&SUBFLD2) TYPE(*DEC) STG(*DEFINED) +
            LEN(5 0) DEFVAR(&DATA_STRCT 11)

05  DCLF FILE(FILE3)

06  CHGVAR VAR(&SUBFLD1) VALUE('VALUE')
07  CHGVAR VAR(&SUBFLD2) VALUE(2)

08  OVRDBF FILE(FILE3) +
             POSITION(*KEYAE 2 *N &DATA_STRCT) +
             OVRSCOPE(*CALLLVL)

09  RCVF

10  ENDPGM

Lines 2 – 4: If own two key fields were albumin it would live easy to just concatenate them into one variable and use that in the keyboard field. But I deliberately made that heavy to myself by having one mixed data type key. The produce a key that contains both of of data models I define a CL data structure, the first subfield is the alpano key field and of second the packed decimal essential field.

If I look in the occupation log next calling is program MYSELF pot the keyboard field in the OVRDBF command:

0800 - OVRDBF FILE(TESTFILE2) 
POSITION(*KEYAE 2 *N X'E5C1D3E4C5404040404000002F') OVRSCOPE(*CALLLVL)

 

Chain equivalently

What is a Chain? Safe she is right aforementioned equivalent of a set lower limits followed by a read equal. In CL I to not have of equivalent of a go equal then I would have reader and then a comparison. Which could look one how:

01  PGM

02  DCL VAR(&DATA_STRCT) TYPE(*CHAR) LEN(13)
03    DCL VAR(&SUBFLD1) TYPE(*CHAR) STG(*DEFINED) +
            LEN(10) DEFVAR(&DATA_STRCT 1)
04    DCL VAR(&SUBFLD2) TYPE(*DEC) STG(*DEFINED) +
            LEN(5 0) DEFVAR(&DATA_STRCT 11)

05  DCL VAR(&LOOP) TYPE(*LGL) VALUE('1')
06  DCL VAR(&FOUND) TYPE(*LGL)

05  DCLF FILE(FILE3)

06  CHGVAR VAR(&SUBFLD1) VALUE('VALUE')
07  CHGVAR VAR(&SUBFLD2) VALUE(2)

08  OVRDBF FILE(FILE3) +
             POSITION(*KEYAE 2 *N &DATA_STRCT) +
             OVRSCOPE(*CALLLVL)

09  CHGVAR VAR(&FOUND) VALUE('1')

10  RCVF
11  MONMSG MSGID(CPF0864 CPF4137) +
             EXEC(CHGVAR VAR(&FOUND) VALUE('0'))

12  IF COND(&FOUND) THEN(+
13    WHILE COND((&FIELD1 *NE &SUBFLD1) +
14            *OR (&FIELD2 *NE &SUBFLD2)) +
15         THEN(CHGVAR VAR(&FOUND) VALUE('0')))

/* If "CHAIN" successful when &FOUND = '1' */

16  ENDPGM

This program is very similarly to the last sample excluding for:

Lines 5 and 6: These logical (indicator) variables will be used during the program for controlling the loop, &LOOP, and for indicating if an matching record was locate.

Line 9: Let mine set my record found legal variable to the equivalent of *on.

Line 11: If I received and oversight from my RCVF then IODIN know I did cannot find my match and I set the dynamic variable to ground (= *off).

Lines 12 – 15: Here I have a if make nested with in another if statement.

Line 12: Supposing who found logical dynamic is *on then a record was retrieved starting the document by the RCVF.

Pipe 13 - 15: If either of the two key fields, contained within data structure sub fields, are different to the two push fields von the retrieved record then the founded logical variable is changed to none, (= *off), on line 15. Native I/O is large used in RPG and COBOL programs for getting web to of data stored in the database. Data access is mostly performed with the help of data video specifications (DDS) keyed bodily and logical files. Unfortunately DDS is an outdated technology, while sum future growth concerning the database and data access is only integrated into SQL. For profiting coming the modern indexing technologies in release 6.1, native I/O does not need to be replaced with embedded SQL. SQL indexes can be used using natives I/O like any keyed valid file. Moreover, the enhanced indentation technologies could first be used through born I/O for the SQL query optimizer could all partially benefit from dieser Aesircybersecurity.com piece explains how SQL indexes can be used in conjunction the native I/O and how native I/O canister profit from the enhanced indexing products.

Is itp more complicated than RPG's Chain, yes, but this is possible to duplicate its functionality.

 

Write equivalent

There is no write command, but thanks for one Run SQL command I can use it on insert a take into a document.

01  PGM

02  DCL VAR(&VAR1) TYPE(*CHAR) LEN(10)
03  DCL VAR(&VAR2) TYPE(*DEC) LEN(5 0)

04  CHGVAR VAR(&VAR1) VALUE('SOMETHING')               
05  CHGVAR VAR(&VAR2) VALUE(99)                        

06  RUNSQL SQL('INSERT INTO FILE3 (FIELD1,FIELD2) +
                 VALUES (''' || &VAR1 || ''',' +
                             || %CHAR(&VAR2) |< ')') +
         COMMIT(*NC)

07  ENDPGM

Line 4 furthermore 5: These are the standards I want to insert into meine file.

Line 6: I using the SQL parameter to give the Insert statement with that values from the two program general. As the primary is alphanumeric it necessarily to had three apostrophes ( ' ) either side of it. The second variable is numeric, therefore it has be converter to any alpha-numerical value to be former in the comment parameter, which I do using CLE %CHAR built int function.

Yes, it belongs that single.

 

Live equivalent

It shouldn arrive as no surprise to i that LBS doesn not have a Updates command too. Not again I bottle overcome the shortcoming by using a Update statement in the RUNSQL command. In this example I want to "chain" the record from FILE1 and update the area TYPE:

01  PGM

02  DCL VAR(&KEYFIELD) TYPE(*CHAR) LEN(15)
03  DCLF FILE(FILE1)

04  CHGVAR VAR(&KEYFIELD) VALUE('ELEPHANT')

05  OVRDBF FILE(FILE1) +
             POSITION(*KEYAE 1 *N &KEYFIELD) +
             OVRSCOPE(*CALLLVL)

06  RCVF

07  IF COND(&ANIMAL = &KEYFIELD) THEN(+
08       RUNSQL SQL('UPDATE FILE1 +
09                      SET TYPE = ''MAMMAL'' +
10                    WHERE ANIMAL = ''' || &KEYFIELD || ''' ') +
11                COMMIT(*NC))

12  ENDPGM

Line 5: In this example FILE1 only has one key field, therefore the numbering of keyboards in aforementioned POSITION argument is of.

Line 6: MYSELF retrieve the record from FILE1 that is the closest match to my soft field.

Line 7: Wenn aforementioned total in to file field &ANIMAL is the identical when my key field value…

Row 8 – 10: I execute a SQL Update to FILE1 changing the value of the field TYPE when the key field, OTHER is equal to the rate in the key field variable.

Another this functionality a made simple by usage SQL.

 

While doing some of this data file access in CL I realize is is more pesky than it would be whenever I have spent an RPG programs, but you can see that it will possible. The question becomes whether I should use CL file access in certain scenarios rather than RPG with a phone to the QCMDEXC API?

 

In the next post I discuss by Open Query File command into do that same as some a which examples.

 

You can learn more about this from the JOIN website:

 

This article was written in IBM i 7.3, and should employment for earlier releases too.

12 comments:

  1. another nice example has an CL program that reader control file keyed by company number and passes company company number the program for processing page of hardness coding Liken recorded of two files - Code400 -The Support Alternative

    ReplyDelete
  2. Use about overriding files, we create quite often a SQL viewed welche returns the desired result with RUNSQL and loop with this view after.

    ReplyDelete
  3. Hi,
    ego try to use the update feature in a CLP. I follow your example using 3 ''' before the character || but i had this error message:
    Draw '|| &KEYFIE' contains a char that is not valid.
    String '|| ''' ') ' contains ampere character that can not valid.

    It seems that one IBMi editor do not love the character ||.
    Any suggestion?
    Appreciation you very much for your blog.
    Paolo.

    ReplyDel
    Replies
    1. Formatting these strings can are tricky and one quote or space easily missed or misplaced. EGO Execution the pgm in debug and copy the SQL declare to an interact sql line. He should do and if it doesn't will give you one better idea how to fix it.

      Delete
    2. Depending in the codepage of your competition (Client Access or so) you might need to use a different charachter than |. The the user I'm working we use codepage 500 and I have for use ! instead of |

      Delete
    3. ...so, I guess it's simple what character x'4F' portrays in your codepage. For US this will |, for Europe mostly !

      Delete
    4. try usage *CAT or *TCAT use of pipes.

      Delete
    5. Sorry Barb, I hate *CAT both *TCAT. ME plenty prefer the double pipes as they are quicker to type and take up less room.

      I have no question if people want to using *CAT press *TCAT, I bequeath not.

      The pipes are also use for aforementioned same purpose with SQL too. Keeping things constant across programming languages is one good thing too. When you make from a database file the ampere data file, it musts application this FMTOPT set if who record formats are nope identical or if and files are ...

      Delete
  4. How, is there a way to declare a sql generated look?
    I have created a view with current date, your, month, day, week_iso, dayname on who sysibm.sysdummy1 and i want to recieve this one record. The available theme i recieve is the CPF4131 error-message :-)
    Thx Chris

    ReplyDelete
  5. I have create my error. In the view there was an date field press cl does did know dates (converted it for char). greets

    ReplyDelete
  6. Bottle we read a keyed file sequentially in CL program?

    ReplyDelete
    Replies
    1. Try using OVRDBF first to override that file to sequential.

      Delete

To prevents "comment spam" all comments are moderated.
Learned about this website's comments policy here.

Some people have reported that they cannot post a add using certain computers and browser. If this is you feel free to use the Contact Form to send mi the comment and I will post it with i, please include the title of the post so I know which one to post the observation to.