invalid level number 'EXEC' error in OpenCOBOL - cobol

this is my code Here :
******************************************************************
* Open Cobol ESQL (Ocesql) Sample Program
*
* FETCHTBL --- demonstrates CONNECT, SELECT COUNT(*),
* DECLARE cursor, FETCH cursor, COMMIT,
* ROLLBACK, DISCONNECT
*
* Copyright 2013 Tokyo System House Co., Ltd.
******************************************************************
IDENTIFICATION DIVISION.
******************************************************************
PROGRAM-ID. FETCHTBL.
******************************************************************
DATA DIVISION.
******************************************************************
WORKING-STORAGE SECTION.
01 D-EMP-REC.
05 D-EMP-NO PIC 9(04).
05 FILLER PIC X.
05 D-EMP-NAME PIC X(20).
05 FILLER PIC X.
05 D-EMP-SALARY PIC --,--9.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 DBNAME PIC X(30) VALUE SPACE.
01 USERNAME PIC X(30) VALUE SPACE.
01 PASSWD PIC X(10) VALUE SPACE.
01 EMP-REC-VARS.
05 EMP-NO PIC S9(04).
05 EMP-NAME PIC X(20) .
05 EMP-SALARY PIC S9(04).
01 EMP-CNT PIC 9(04).
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL INCLUDE SQLCA END-EXEC.
******************************************************************
PROCEDURE DIVISION.
******************************************************************
MAIN-RTN.
DISPLAY "*** FETCHTBL STARTED ***".
* WHENEVER IS NOT YET SUPPORTED :(
* EXEC SQL WHENEVER SQLERROR PERFORM ERROR-RTN END-EXEC.
* CONNECT
MOVE "testdb" TO DBNAME.
MOVE "postgres" TO USERNAME.
MOVE SPACE TO PASSWD.
EXEC SQL
CONNECT :USERNAME IDENTIFIED BY :PASSWD USING :DBNAME
END-EXEC.
IF SQLCODE NOT = ZERO PERFORM ERROR-RTN STOP RUN.
* SELECT COUNT(*) INTO HOST-VARIABLE
EXEC SQL
SELECT COUNT(*) INTO :EMP-CNT FROM EMP
END-EXEC.
DISPLAY "TOTAL RECORD: " EMP-CNT.
* DECLARE CURSOR
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT EMP_NO, EMP_NAME, EMP_SALARY
FROM EMP
ORDER BY EMP_NO
END-EXEC.
EXEC SQL
OPEN C1
END-EXEC.
* FETCH
DISPLAY "---- -------------------- ------".
DISPLAY "NO NAME SALARY".
DISPLAY "---- -------------------- ------".
EXEC SQL
FETCH C1 INTO :EMP-NO, :EMP-NAME, :EMP-SALARY
END-EXEC.
PERFORM UNTIL SQLCODE NOT = ZERO
MOVE EMP-NO TO D-EMP-NO
MOVE EMP-NAME TO D-EMP-NAME
MOVE EMP-SALARY TO D-EMP-SALARY
DISPLAY D-EMP-REC
EXEC SQL
FETCH C1 INTO :EMP-NO, :EMP-NAME, :EMP-SALARY
END-EXEC
END-PERFORM.
* CLOSE CURSOR
EXEC SQL
CLOSE C1
END-EXEC.
* COMMIT
EXEC SQL
COMMIT WORK
END-EXEC.
* DISCONNECT
EXEC SQL
DISCONNECT ALL
END-EXEC.
* END
DISPLAY "*** FETCHTBL FINISHED ***".
STOP RUN.
******************************************************************
ERROR-RTN.
******************************************************************
DISPLAY "*** SQL ERROR ***".
DISPLAY "SQLCODE: " SQLCODE " " NO ADVANCING.
EVALUATE SQLCODE
WHEN +10
DISPLAY "Record not found"
WHEN -01
DISPLAY "Connection falied"
WHEN -20
DISPLAY "Internal error"
WHEN -30
DISPLAY "PostgreSQL error"
DISPLAY "ERRCODE: " SQLSTATE
DISPLAY SQLERRMC
*> TO RESTART TRANSACTION, DO ROLLBACK.
EXEC SQL
ROLLBACK
END-EXEC
WHEN OTHER
DISPLAY "Undefined error"
DISPLAY "ERRCODE: " SQLSTATE
DISPLAY SQLERRMC
END-EVALUATE.
******************************************************************

This is not "pure COBOL", but COBOL with embedded SQL, which in most cases needs a precompiler.
As-is there is a word EXEC where in COBOL a level-number would be expected, therefore the message from your compiler is correct.
In order to compile this source with your COBOL compiler, use an EXEC SQL precompiler to convert the SQL statements into COBOL for you first, most likely the one that the sample program references: ocesql - Open-COBOL-ESQL (PostgreSQL only).
As an alterative you can also use other preparsers (likely with some adjustments, especially for the CONNECT); here's an incomplete list:
esqlOC - ESQL for GnuCOBOL/OpenCobol (also works with other compilers, uses ODBC under the hood)
Gix ESQL, a recent addition, currently only as part of the Gix-IDE (GnuCOBOL only, currently uses a general ODBC or direct binding to PostgreSQL or MySql)
... and some proprietary variants (only to access their products)
Oracle Pro*COBOL
IBM DB2 precompiler
...

Related

CICS Transaction failed with abend U4038

This is CICS COBOL Program :-
IDENTIFICATION DIVISION.
PROGRAM-ID. ELECPRG.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INFL ASSIGN TO INFLDD
ORGANIZATION IS LINE SEQUENTIAL
ACCESS MODE IS SEQUENTIAL
FILE STATUS IS FS.
DATA DIVISION.
FILE SECTION.
FD INFL.
01 ELEC-REC.
05 P-NUM PIC X(5).
05 FILLER PIC X(1).
05 C-NAME PIC X(10).
05 FILLER PIC X(1).
05 C-UNIT PIC X(4).
WORKING-STORAGE SECTION.
COPY ELECMAP.
01 WS-MSG PIC X(20) VALUE 'BILL PROD DB UPDATE'.
01 FS PIC 9(2).
PROCEDURE DIVISION.
000-MAIN.
MOVE LOW-VALUES TO ELBILLI, ELBILLO
PERFORM 100-SEND-MAP.
PERFORM 200-RECEIVE-MAP.
PERFORM PROCESS-DATA.
PERFORM FILE-FUNC.
PERFORM 100-SEND-MAP.
PERFORM 300-RETURN.
STOP RUN.
100-SEND-MAP.
EXEC CICS
SEND
MAP('ELBILL') MAPSET('ELECMAP')
ERASE
END-EXEC.
200-RECEIVE-MAP.
EXEC CICS
RECEIVE
MAP('ELBILL') MAPSET('ELECMAP')
END-EXEC.
PROCESS-DATA.
MOVE CUSNOI TO CUSNOO.
MOVE NAMEI TO NAMEO.
MOVE UNITSI TO UNITSO.
MOVE UNITSI TO BILLO.
MOVE WS-MSG TO MSGO.
FILE-FUNC.
OPEN OUTPUT INFL.
DISPLAY 'OPEN FILE STATUS IS' FS.
MOVE CUSNOI TO P-NUM.
MOVE NAMEI TO C-NAME.
MOVE UNITSI TO C-UNIT.
WRITE ELEC-REC.
DISPLAY 'WRITE FILE STATUS IS' FS.
CLOSE INFL.
DISPLAY 'CLOSE FILE STATUS IS' FS.
300-RETURN.
EXEC CICS
RETURN
END-EXEC.
Mine compile jcl :-
//CICSCOB JOB CLASS=A,MSGCLASS=A,NOTIFY=&SYSUID,MSGLEVEL=(1,1)
//PROCLIB JCLLIB ORDER=DFH320.CICS.SDFHPROC
//STEP01 EXEC PROC=DFHYITVL,
// INDEX='DFH320.CICS',
// AD370HLQ='IGY410',
// LE370HLQ='CEE',
// PROGLIB='DFH320.CICS.SDFHLOAD',
// DSCTLIB='DFH320.CICS.SDFHMAC'
//TRN.SYSIN DD DISP=SHR,DSN=RAHUL.COBOL.PROGRAM(ELECPRG)
//INFLDD DD DSN=RAHUL.CICS.OUTPUT,DISP=SHR
//LKED.SYSIN DD *
NAME ELECPRG(R)
/*
Compilation complete a condition code = 0004 , few warnings.
But when I execute the transaction in CICS it terminates with CICS Transaction ELEC failed with abend U4038.
I don't understand the nature of this abend. I just want to update dataset RAHUL.CICS.OUTPUT from my CICS screen input. provided the output file location. Without the file use program is working fine , no abend occurs.
This program is a combination of COBOL file control commands and CICS SEND / RECEIVE MAP commands. COBOL file commands such as OPEN, READ, WRITE and CLOSE are not supported in a CICS transaction.
In a CICS program you have to use the CICS API as documented here https://www.ibm.com/docs/en/cics-ts/5.5?topic=programs-understanding-file-control

Error IGZ0035S when attempting to open an output dataset in COBOL

I have created two datasets PRT-DONE and PRT-LINE in output. But when I am submitting job it is showing unsuccessful opening of PRT-DONE output; PRT-LINE is working fine.
I think it cannot open the datasets PRT-DONE. Looks like opening error of the output PRTDONE. When I was removing that open statement there was only condition code error.
Error:
IGZ0035S There was an unsuccessful OPEN or CLOSE of file PRTDONE in program ADDONE at relative location X'318'.
IDENTIFICATION DIVISION.
PROGRAM-ID. ADDONE.
AUTHOR. STUDENT.
*
ENVIRONMENT DIVISION.
*
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PRT-LINE ASSIGN TO PRTLINE.
SELECT PRT-DONE ASSIGN TO PRTDONE.
DATA DIVISION.
FILE SECTION.
FD PRT-LINE RECORD CONTAINS 80 CHARACTERS RECORDING MODE F.
01 PRT-REC PIC X(80) VALUE SPACES.
FD PRT-DONE RECORD CONTAINS 80 CHARACTERS RECORDING MODE F.
01 PRT-REC-DONE.
05 PRT-DATE PIC X(8) VALUE SPACES.
05 FILLER PIC X(1) VALUE SPACES.
05 PRT-TIME PIC X(4) VALUE SPACES.
05 FILLER PIC X(2) VALUE SPACES.
05 PRT-COMMENT PIC X(27) VALUE SPACES.
05 FILLER PIC X(2) VALUE SPACES.
05 PRT-MY-NAME PIC X(36) VALUE SPACES.
WORKING-STORAGE SECTION.
01 PGM-VARIABLES.
05 PGM-COUNT PIC 9(05).
01 YYYYMMDD PIC 9(8).
01 INTEGER-FORM PIC S9(9).
01 REFMOD-TIME-ITEM PIC X(8).
****************************************************************
* PROCEDURE DIVISION *
****************************************************************
PROCEDURE DIVISION.
*
A000-START.
OPEN OUTPUT PRT-LINE.
PERFORM A000-COUNT 10 TIMES.
PERFORM A000-DONE.
CLOSE PRT-LINE.
STOP RUN.
*
A000-COUNT.
ADD 1 TO PGM-COUNT.
* DISPLAY PGM-COUNT.
WRITE PRT-REC FROM PGM-COUNT.
*
A000-DONE.
OPEN OUTPUT PRT-DONE.
MOVE SPACES TO PRT-REC-DONE.
ACCEPT REFMOD-TIME-ITEM FROM TIME.
MOVE FUNCTION CURRENT-DATE(1:8) TO YYYYMMDD.
MOVE YYYYMMDD TO PRT-DATE.
MOVE REFMOD-TIME-ITEM (1:4) TO PRT-TIME.
MOVE "My first z/OS COBOL program" TO PRT-COMMENT.
WRITE PRT-REC-DONE.
CLOSE PRT-DONE.
JCL:
//ADD1JCL JOB 1,NOTIFY=&SYSUID
//*****************/
//COBRUN EXEC IGYWCL
//COBOL.SYSIN DD DSN=&SYSUID..SOURCE(ADD1CBL),DISP=SHR
//LKED.SYSLMOD DD DSN=&SYSUID..LOAD(ADD1CBL),DISP=SHR
//*****************/
// IF RC = 0 THEN
//*****************/
//RUN EXEC PGM=ADD1CBL
//STEPLIB DD DSN=&SYSUID..LOAD,DISP=SHR
//PRTDONE DD DSN=Z12441.OUTPUT(PRTDONE),DISP=SHR,OUTLIM=15000
//PRTLINE DD DSN=Z12441.OUTPUT(PRTLINE),DISP=SHR,OUTLIM=15000
//SYSOUT DD SYSOUT=*,OUTLIM=15000
//CEEDUMP DD DUMMY
//SYSUDUMP DD DUMMY
//*****************/
// ELSE
// ENDIF
I assume your output data set Z12441.OUTPUT is of type PDS not PDS/E. You're trying to write to two members in the same PDS in parallel, which is not supported. In your job's output, you probably see a message IEC143I 213-30,.... Where 213 is the ABEND code which points to a problem with the OPEN service, and 30 is the return code. The explanation of messsage IEC143I can be found here Message description. The explanation for reason code 30 sais:
An attempt was made to open a partitioned data set (PDS) for OUTPUT,DISP=SHR. The PDS is already open in this condition, and a DCB is already open for output to the data set. The data set might be on the same system or on another system that is sharing the volume. Access was not serialized before the attempt to open the data set.
You need to allocate two distinct output data sets, one for PRTDONE, and one for PRTLINE. Two members of the same PDS are not two distinct data sets.
Note that PDS/E data sets allow multiple concurrent opens for output to different members, with some restrictions. I would advise to not get used to opening for output multiple members of the same PDS or PDS/E at the same time. Rather use PS data sets than PDS members for output. One reason being the restartability of jobs. With PS data sets, you can simply delete and reallocate the data set within a job, and then rerun the job. It is more complex to handle restartability with PDS members.

COBOL: syntax error, unexpected SORT, expecting Identifier and continuation character expected

I just started using COBOL for my COBOL class and I don't know what's wrong with lines 9, 30, and 62. Hope you could help me. Thank you.
******************************************************************
* Author: Emil
* Date: 12/02/21
* Purpose: Sorting and Debugging
* Tectonics: cobc
******************************************************************
PROGRAM-ID. InputSort.
PROCEDURE DIVISION
Using SORT and INPUT PROCEDURE. The program accepts records
* from the user and RELEASEs them to the work file
* where they are sorted. This program
* allows student records to be entered in any order but
* produces a file sequenced on ascending StudentId.
ENVIRONMENT DIVISION
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT StudentFile ASSIGN TO "SORTSTUD.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT WorkFile ASSIGN TO "WORK.TMP".
DATA DIVISION.
FILE SECTION.
FD StudentFile.
01 StudentDetails PIC X(30).
* The StudentDetails record has the description shown below.
* But in this program we don't need to refer to any of the items in
* the record and so we have described it as PIC X(32)
* 01 StudentDetails
* 02 StudentId PIC 9(7).
* 02 StudentName.
* 03 Surname PIC X(8).
* 03 Initials PIC XX.
* 02 DateOfBirth.
* 03 YOBirth PIC 9(4).
* 03 MOBirth PIC 9(2).
* 03 DOBirth PIC 9(2).
* 02 CourseCode PIC X(4).
* 02 Gender PIC X.
SD WorkFile.
01 WorkRec.
02 WStudentId PIC 9(7).
02 FILLER PIC X(23).
PROCEDURE DIVISION.
Begin.
SORT WorkFile ON ASCENDING KEY WStudentId
INPUT PROCEDURE IS GetStudentDetails
GIVING StudentFile.
STOP RUN.
GetStudentDetails.
DISPLAY "Enter student details using template below."
DISPLAY "Enter no data to end.".
DISPLAY "Enter - StudId, Surname, Initials, YOB, MOB, DOB, Course, Gender"
DISPLAY "NNNNNNNSSSSSSSSIIYYYYMMDDCCCCG"
ACCEPT WorkRec.
PERFORM UNTIL WorkRec = SPACES
RELEASE WorkRec
ACCEPT WorkRec
END-PERFORM.
General note: Watch your periods (full stops). They mean something. In COBOL many of them are optional but some are not. Be consistent about where you put them. In the procedure division, this is especially important!
Line 8, PROCEDURE DIVISION. Okay, this is the first problem. The divisions are IDENTIFICATION, ENVIRONMENT, DATA and PROCEDURE, in that order. Having PROCEDURE DIVISION here is way out of order and was missing the required period. Perhaps you meant IDENTICATION DIVISION. but even then it should be the first statement but for comments.
Line 9 and following: Typically remarks such as these are proceeded by a REMARKS. heading, or make them all (including line 9) into comments.
Line 30: I don't see a problem with a comment. Did you mean some other line?
Line 62: I don't see a problem. What was the error message?
BUT your perform loop will either never start or never end because nothing inside of the loop (PERFORM through END-PERFORM) changes WorkRec. Perhaps you want add an additional ACCEPT statement inside of the loop, use the WITH TEST AFTER clause on the PERFORM statement and move the ACCEPT statement into the loop.

COBOL: Can a GDG file descriptor (FD) reference multiple generations?

I have a program which reads a GDG file and moves data to working storage. I am interested to know if it can be made to repeat this process for multiple generations of the GDG using a reference to the file definition. Perhaps there is a way to use subscripts on the file definition? My thought is there must be a method to move different file definitions into a reference variable from which to access the files.
Code Sample based on suggested, setenv solution
FILE-CONTROL.
SELECT DATAIN ASSIGN TO UT-S-DATAIN.
DATA DIVISION.
FILE-SECTION.
FD DATAIN
BLOCK CONTAINS 0 RECORDS
RECORD CONTAINS 133 CHARACTERS
LABEL RECORDS ARE STANDARD
DATA RECORD IS DATA-REC.
01 DATA-REC PIC X(133).
WORKING-STORAGE SECTION.
01 ENV-VARS.
02 ENV-NAME PIC X(9).
02 ENV-VALUE PIC X(100).
02 ENV-OVERWRITE PIC S9(8) COMPUTATIONAL VALUE 1.
PROCEDURE DIVISION.
MOVE Z"DATAIN" TO ENV-NAME
MOVE Z"DSN(PROGRAMMER.TEST.GDGFILE(-1)),SHR" TO ENV-VALUE
MOVE 1 TO ENV-OVERWRITE
CALL "setenv" USING ENV-NAME ENV-VALUE ENV-OVERWRITE.
Notes
Pay special attention when moving DSN value to ENV-VALUE. On my first swing I left out the closing parentheses, most likely because of JCL muscle memory.
Be sure to empty out your DD statement in JCL/Step.
In mainframe COBOL, the FD refers to a SELECT which refers to a DD statement attached to the EXEC PGM statement for your program in the invoking JCL. The DD statement may refer to one or many GDGs. This is determined at compile time.
What I think you are asking for is dynamic allocation of a file at runtime. There are a couple of ways to accomplish that, one is BPXWDYN.
Identification Division.
Program-ID. SOMETEST.
Environment Division.
Input-Output Section.
File-Control.
Select MY-FILE Assign SYSUT1A.
Data Division.
File Section.
FD MY-FILE
Record 80
Block 0
Recording F.
01 MY-FILE-REC PIC X(080).
Working-Storage Section.
01 CONSTANTS.
05 BPXWDYN-PGM PIC X(008) VALUE 'BPXWDYN '.
05 ALCT-LIT-PROC PIC X(035)
VALUE 'ALLOC FI(SYSUT1A) SHR MSG(WTP) DSN('.
05 FREE-LIT-PROC PIC X(016)
VALUE 'FREE FI(SYSUT1A)'.
05 A-QUOTE PIC X(001) VALUE "'".
01 WORK-AREAS.
05 WS-DSN PIC X(044) VALUE 'MY.GDG.BASE'.
05 WS-GDG-NB PIC 999 VALUE ZEROS.
05 BPXWDYN-PARM.
10 PIC S9(004) COMP-5 VALUE +100.
10 BPXWDYN-PARM-TXT PIC X(100).
Procedure Division.
* Construct the allocation string for BPXWDYN.
MOVE SPACES TO BPXWDYN-PARM-TXT
STRING
ALCT-LIT-PROC
DELIMITED SIZE
WS-DSN
DELIMITED SPACE
'(-'
DELIMITED SIZE
WS-GDG-NB
DELIMITED SIZE
')'
DELIMITED SIZE
INTO
BPXWDYN-PARM-TXT
END-STRING
CALL BPXWDYN-PGM USING
BPXWDYN-PARM
END-CALL
IF RETURN-CODE = 0
CONTINUE
ELSE
[error handling]
END-IF
[file I/O with MY-FILE]
MOVE SPACES TO BPXWDYN-PARM-TXT
MOVE FREE-LIT-PROC TO BPXWDYN-PARM-TXT
CALL BPXWDYN-PGM USING
BPXWDYN-PARM
END-CALL
IF RETURN-CODE = 0
CONTINUE
ELSE
[error handling]
END-IF
GOBACK.
This is just freehand, so there may be a syntax error, but I hope I've made the idea clear.
There is another technique, using the C RTL function setenv, documented by IBM here. It looks like it might be simpler but I've never done it that way.

Error in rewrite cobol

I have the code,
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE3.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-SALARY ASSIGN TO 'input.txt'
ORGANIZATION IS SEQUENTIAL
ACCESS MODE IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD EMP-SALARY.
01 NEWFILE.
05 FS-EMPNO PIC 9(6).
05 FS-NAME PIC 9(4).
05 FILLER PIC X(63).
WORKING-STORAGE SECTION.
01 WS-EOF PIC A(1) VALUE "N".
PROCEDURE DIVISION.
MAIN-PARA.
OPEN I-O EMP-SALARY
PERFORM READ-PARA THRU READ-PARA-EXIT UNTIL WS-EOF="Y"
STOP RUN.
MAIN-PARA-EXIT.
EXIT.
READ-PARA.
READ EMP-SALARY
AT END
MOVE "Y" TO WS-EOF
NOT AT END
IF FS-EMPNO > 10000
MOVE '1000' TO FS-NAME
REWRITE NEWFILE
DISPLAY " RECORD " NEWFILE
END-IF
END-READ.
READ-PARA-EXIT.
EXIT.
I got the error read statement should be executed first Status=43, and implicit close of file.
This program is to rewrite a record in a file. what is the reason for this error.
It is best to include FILE STATUS processing for any files you use in a program, and always test the value after an IO.
If that is the code you are running, you must have an OPEN failing, a READ failing, and the REWRITE deciding that it just can't go on. Check that it is the code that you are running.
Can you show the version of GnuCOBOL you are running, and the OS you are running on, include the FILE STATUS in your program and test the values, and also include an explicit CLOSE of your file, which is always good practice.
See if structuring your program like this simplifies:
PROCEDURE DIVISION.
OPEN I-O EMP-SALARY
* do file status checking here
PERFORM READ-PARA
PERFORM PROCESS-PARA UNTIL END-OF-INPUT-FILE
* END-OF-INPUT-FILE (make the name relevant to your file) is an 88 on the FILE STATUS
* filed for that file
* close the file
* do file status checking here
STOP RUN
.
READ-PARA.
READ EMP-SALARY
* do file status checking here
PROCESS-PARA.
IF FS-EMPNO > 10000
MOVE '1000' TO FS-NAME
PERFORM UPDATE-RECORD
END-IF
PERFORM READ-PARA
.
UPDATE-RECORD.
REWRITE NEWFILE
* do file status checking here
DISPLAY " RECORD " NEWFILE
.

Resources