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.
Timely post. I’ve been working with nulls lately and having to modify programs to handle them correctly.
ReplyDeleteThanks !
ReplyDeleteThank you very much! Extremely useful information!!!
ReplyDeleteThank you so much
ReplyDelete