Wednesday, April 4, 2018

Handling nulls in CL

in a cl program how to handle a null value from a file

I have written previously about how to handle nulls values in RPG and in SQL, but until this week I had never had a problem with null in a CL program.

The CL program was "reading" a SQL table, where some columns/fields were null.

    ORDNBR      ORDSTS       ORDVALUE
01 PO18087       P            145.67
02 PO18556       C             15.36
03 PO18223       -                  -
04 PO18777       D                  -

The CL program is simple.

01  PGM

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

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

07  ENDDO

08  ENDPGM

Line 4: I am using a DOWHILE loop to contain the "read". The end of the loop is at line 7.

Line 5: CL does not have a read command, the Receive File command,RCVF, does the same thing.

Line 6: When end of file or table is encountered message CPF0864 is issued. In this Monitor message command, MONMSG, when that error occurs the logic leaves the DOWHILE loop.

When I ran the program I received the following message:

CPF5029 received by procedure CLPGM1. (C D I R)

When I prompt the message I see:

                Additional Message Information

Message ID . . . . :   CPA0702
Message type . . . :   Inquiry

Message . . . . :   CPF5029 received by procedure WA107C0. 
  (C D I R)
Cause . . . . . :   ILE Control language (CL) procedure 
  CLPGM01 in module CLPGM01 in program CLPGM01 in library 
  MYLIB detected an error at statement number 0000000500.  
  Message text for CPF5029 is: Data mapping error on member 
  WORKFILE.  Use F10 (if available) or the Display Job Log
  (DSPJOBLOG) command to see the messages in the job log for
  a more complete description of what caused the error.  If 
  you still are unable to solve the problem, please contact
  your technical support person.

On the job log I could see the data mapping error messages:

     500 - RCVF DEV(*FILE) RCDFMT(*FILE) WAIT(*YES) OPNID(*NONE)
  File name is QTEMP/WORKFILE. */
  Data mapping error on member WORKFILE.
  Data mapping error on member WORKFILE.
  Data mapping error on member WORKFILE.
? C
  Data mapping error on member WORKFILE.
  Function check. CPF5029 unmonitored by CLPGM1 at statement 
    0000000500 instruction X'0000'.
  CPF5029 received by procedure CLPGM1. (C D I R)
  CPF5029 received by procedure CLPGM1. (C D I R)

When I prompted the first data mapping error the cause was revealed:

                Additional Message Information

Message ID . . . . . . :   CPF5035
Message type . . . . . :   Diagnostic

Message . . . . :   Data mapping error on member WORKFILE.
Cause . . . . . :   A data mapping error occurred on field
  ORDSTS in record number 3, record format WORKFILE, member 
  number 1, in member WORKFILE file WORKFILE in library QTEMP,
  because of error code 19. The error code meanings follow:

     19 -- An unexpected null field was found.

When I answered the CPA0702 message with a D for dump I could see that all the columns that were null had their CL variable default, blank for character and zero for decimal.

Variable     Type      Length     Value
&ORDNBR        *CHAR         10   'PO18223   '
&ORDSTS        *CHAR          2   '  '
&ORDVALUE      *DEC        10 2    0


&ORDNBR        *CHAR         10   'PO18777   '
&ORDSTS        *CHAR          2   'D '
&ORDVALUE      *DEC        10 2    0

The solution, I found, is in the Declare File command, DCLF. There is a parameter to "Allow field value of null", which defaults to *NO. When I press F4 on this parameter for the details I find the solution.

Help          Allow field value of null (ALWNULL) - Help

Specifies whether a field value of null is allowed.

*NO
    Values of null are not allowed.  For each field containing
    a null value at RCVF time, a diagnostic message is sent 
    with a single escape message for the entire record.  Default
    values are placed in the CL variables.

*YES
    Values of null are allowed.

My DCLF command becomes:

03  DCLF FILE(QTEMP/WORKFILE) ALWNULL(*YES)

When I run the program after this change I get no error messages, and the variables that were null contain their default values. This allows me to give these two columns values in my CL program, lines 7 and 8 below.

01  PGM

02  DCL VAR(&LOOP) TYPE(*LGL) VALUE('1')
03  DCLF FILE(QTEMP/WORKFILE) ALWNULL(*YES)

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

07    IF COND(&ORDSTS = ' ') +
         THEN(CHGVAR VAR(&ORDSTS) VALUE('?'))

08    IF COND(&ORDVALUE = 0) +
           THEN(CHGVAR VAR(&ORDVALUE) VALUE(1))

09  ENDDO

10  ENDPGM

 

You can learn more about the DCLF command from the IBM website here.

 

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

4 comments:

  1. Timely post. I’ve been working with nulls lately and having to modify programs to handle them correctly.

    ReplyDelete
  2. Thank you very much! Extremely useful information!!!

    ReplyDelete

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

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