Showing posts with label COBOL. Show all posts
Showing posts with label COBOL. Show all posts

Friday, October 6, 2017

Interpreting TSO ISRDDN command in mainframe ISPF

The TSO ISRDDN command is a useful tool that lets you browse/view your active TSO session libraries. From any session, type TSO ISRDDN and the below widow will open up.




















 On the right side of the display is a list of DDNAME(in white colour)  and their associated data sets ( (in Green colour) currently allocated to the user session.
**Dataset names in green are blurred on purpose

 The left side of the display contains columns of information about individual data sets like the volume information and all. When you scroll right (using F11)or left(or F10) , the left side of the screen changes. Initially, the left side of the screen contains the volume name and disposition,if the dataset is SMS managed or not ,etc . If the disposition is red, there are other jobs waiting to use this data set as shown. 

Generally the dataset associated with sysproc ddname contains the pds for the clist macros available in the system.

Try issuing  the command LINKLIST or LPA. Either command will add both the system LINKLIST and LPA libraries to the display.The LINKLIST and LPALIB (Link Pack Area LIBrary) are related concepts. The LINKLIST is a collection of libraries, established during the IPL, that contain system and user load modules. Any program in the LINKLIST does NOT require a JOBLIB or STEPLIB to point to the load library -- the system can find such programs without any JCL statements. The LPALIB basically contains read-only programs (which may system or user load modules) that are reenterable.

Saturday, July 30, 2016

Zoned Decimal and packed Decimal (COMP- 3) fields. How Does COMP 3 saves storage space?

Two computer codes which are used  for internal representation of data are EBCDIC and ASCII.
Extended Binary coded decimal interchange(EBCDIC)  code is a 8 bit character encoding standard used in IBM environment.
Most of the other Non IBM machines use ASCII standard.
Below is the EBCDIC representation of the alphabets and numbers followed in IBM environment.
EBCDIC represenation of Aphabets and Numerals

Following the chart, we can see 'a' (2nd row in above chart)  is represented in binary in 1000000001 and has the hex value of  81.

 All characters & numbers are represented in 8 bits. These 8 bits can be  broken into two 4 bit segments. For historical reasons, the  high order 4 bits are called zone part and low order 4 bits are called digits part.
Each of these 4 bits are represented by one hexadecimal character. Thus each 8 bit EBCDIC can be represented by  two character hexadecimal value. The high order 4 bits are used to represent whether the value stored is a letter,positive or negative number. Low order 4 bits represents numbers 0-9.

Let us see how the letter D is stored internally.(Map with the chart above)

In similar fashion, we can see how the letter 8 will be stored in the system( Map with the chart above)

Thus we see that in zoned decimal each byte represents one digit.

So, how will the positive number 62587 be stored in the system?
Zoned decimal number in EBCDIC repreentaion
In  zoned decimal, the zone portion of the rightmost byte represents the sign of the number.
For positive number, the zone portion is always 1111.
For negative number the zone portion becomes  1101.
Thus -6 can will be represented  as: 1101(Zone part) 0110(Digit part)

Packed Decimal fields: How does it save spaces?  Let's see how it works.

In  packed decimal format, the zone portion is stripped from each byte, so that two digits can be packed together in one byte.This way the space for zone portion of each byte can be used to represent another digit. Thus two digits are represented in single byte there by saving the space.
Only the zone portion of the low order or the rightmost byte is kept for storing the sign of the field.
Considering the same example, see how the number 62587 will be stored in packed decimal format.
Space utilized will be reduced from 5 bytes to 3 bytes.

Number :                                6               2              5             8                7
Packed decimal representation
We can see that two digits are packed in single byte by stripping of the zone portion of all the bytes except the last byte (marked in brown).
Had it been a negative number the last byte would have contained 1101 in place of 1111.

This way, a packed decimal number saves space by packing two digits in one byte.


Thursday, June 16, 2016

RENT compiler option in cobol - Understanding reentrant programming

For understanding RENT compiler option, we need to know  what is a  re-entrant program.
A re-entrant is a program that doesn’t change itself. “How can a program change itself?” Does the word "Multi threading " looks familiar?  Reentrant and mutithreading are related but somewhat different topics.
We can divide our program(logically) into  three parts:
1. Program code – the instructions that are executed when a program runs.
2. Constants – constants used in a program. These are set when the program is written, and never change.
3.Working  Storage area – or variables. This area changes when different user fires the same program.

"A reentrant Cobol program gives each user their own copy of working storage. " 
For every user,MVS supplies the GETMAIN and STORAGE macros to support this and they can be
used by subsystems such as CICS or IMS or whatever to support reentrant programs.

For each user the copy of the working storage is dynamically acquired and initialized from the original copy. When a user interacts with the program , he only modifies his copy of the variables.

When the program is interrupted to give another user a turn to use the program, information about the data area associated with that user is saved.

So, what will happen if we write a CICS program as non-renetrant?
When one transaction waits, a second transaction can come and modify the working storage variables, and thus providing unstable or undesirable results.

Thus, Re-entrant programs allow a single copy of a program or routine to be used concurrently by two or more processes.


For cobol, we use the compiler option RENT to generate reentrant object program.

Wednesday, December 30, 2015

Passing Data from JCL to COBOL program

We pass data from JCL to cobol program in two ways:
1. Using the PARM keyword 
2. Using SYSIN DD in JCL
The basic difference between these two ways of passing are as follows:
A. Using 'PARM=' on the exec keyword, we can pass only 100 characters of data. Also in cobol we need linkage section to take the values in.
B. When we pass data through SYSIN, we need to have the accept keyword in COBOL. For each row in SYSIN, we need to have corresponding ACCEPT verb in cobol.

Sample cobol program accepting PARM value through linkage
...
......
LINKAGE SECTION.
01 LS-TEST-PARM.
    05 LS-TEST-LENGTH PIC S9(04) USAGE COMP.
    05 LS-VAR1 PIC 9(02).
    05 LS-VAR2 PIC 9(02).

PROCEDURE DIVISION USING LS-TEST-PARM.
DISPLAY LS-VAR1.
DISPLAY LS-VAR2.
DISPLAY LS-TEST-LENGTH.
STOP RUN.

Have a look into the corresponding JCL.
//TTYYTST  JOB(TEST),CLASS=I,MSGCLASS=X,MSGLEVEL=(1,1)
//                NOTIFY=&SYSUID
//*
//JSTEP01  EXEC PGM=SAMPLE3,PARM='1211212'
//STEPLIB  DD DSN=TEST.LOAD.LIB1,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*

RESULT:
12
11
007

Sample program accepting data from SYSIN .
...
....
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-TOTAL
    05  WS-VAR1  PIC X(02).
    05  WS-VAR2  PIC X(02).
PROCEDURE DIVISION.
INITIALIZE WS-TOTAL.
ACCEPT WS-VAR1.
ACCEPT WS-VAR2.
DISPLAY WS-VAR1.
DISPLAY WS-VA22 .

Corresponding JCL:
//TTYAATST  JOB(TEST),CLASS=I,MSGCLASS=X,MSGLEVEL=(1,1)
//                NOTIFY=&SYSUID
//*
//JSTEP01  EXEC PGM=SAMPLE1
//STEPLIB  DD DSN=TEST.LOAD.LIB1,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=
//sysin dd*
12
31
/*
//*
Result:
12
31

If we do not have any data to be passed we can make SYSIN DD DUMMY. I tried passing blank values via SYSIN. Was Expecting an abend, but it did not. It displayed spaces in SYSOUT.

Wednesday, November 25, 2015

COBOL DB2 Program from scratch - step by step guide

This post is just to help/guide to a new programmer in writing a cobol db2 program from scratch.
Let us write  a cobol program  to read the EMPLOYEE table and get  the details of the employee with name 'RYAN'.
I am assuming the table is already created in the user database like below:.

EMPLOYEE
EMPID EMPNAME     DEPARTMENT          SALARY              DESIGNATION
1000     XXXXXXX       XX                     10000                  SE
1001     YYYYYYY          YY                      9000                    SE
1002     ZZZZZZZ       ZZ                     20000                   TL


STEP1:  We need to declare the  Table structure in the Working Storage section. Ideally we should DCLGEN Tool to generate the structure for our DB2 table. The option to go to our DCLGEN tool depends on the ISPF settings. Generally it can be invoked using 'D' option on the ispf menu to display DB2I Default pannel.
DCLGEN Screen 
On pressing ENTER, the DCLGEN will be generated and will look like below.

*****************************************************************
EXEC SQL DECLARE DEV.EMPLOYEE TABLE
 ( EMPID CHAR(10) NOT NULL,
   EMPNAME CHAR(30) NOT NULL,
   DEPARTMENT CHAR(2) NOT NULL,
  SALARY DECIMAL(10,2) NOT NULL,
  DESIGNATION CHAR(4) NOT NULL )
)
END-EXEC.
*************** COBOL DECLARATION FOR TABLE DEV.EMPLOYEE *********
01 EMPOYEE-RECORD.
    05 HV-EMPID PIC X(10).
    05 HV-EMPNAME PIC X(30).
    05 HV-DEPARTMENT PIC X(2).
    05 HV-SALARY PIC S9(8)V99 COMP-3.
    05 HV-DESIGNATION PIC CHAR(4).
*********** THE NUMBER OF COLUMNS IN THIS DECLARATION IS 5 *****
This DCLGEN  needs to be included into the Working Storage Section of our cobol program in the following way:
EXEC SQL
INCLUDE  EMPLOYEE
END-EXEC.
Also, the most important copybook SQLCA needs to be included . Apart from this we wont be able to capture the SQL Return codes

EXEC SQL
INCLUDE  SQLCA
END-EXEC.
Also since our query in the program might return more than single row, we need cursors in our program. Read About cursor programming here
I am not going into the details of cursor programming here, since those are there in other posts.
Once the program is ready and compiled , we need to bind it to a plan in the test region. Once the bind is successful, we can run the program using  the IKJEFT01 utility as below.

cobol db2 run jcl

Saturday, August 1, 2015

Date functions in cobol. Why and when do we use IGZEDT4 ,CEELOCT , CURRENT-DATE ?

We come across certain instance when we need to get the time/date in certain formats in cobol.
We all know that we can get the dates in cobol using ACCEPT verb in the following way.
                        ACCEPT WS-DATE FROM DATE
But we would not get it in the format we prefer to use ,say in the format YYYYMMDD.
DATE has the picture clause of PIC 9(6). So when we use the above cobol statement, we would get the date in the format like below when read  sequentially from left to right:
First 2 digits for the year of the century, next 2 for the month and next 2 digits with the date.
Example: This if the current date is 25-JUL-1994, we would get  as 940725.

VS cobol II does not support the date format giving results in YYYY format. However the results can be interpolated in many ways to get our desired result.Some of the utilities are described below.

For NON LE Cobol Environment 
1.IBM has offered a non-LE callable interface known as  IGZEDT4 which can be used to achieve our
desired function.  When we call it , it will give the desired result in the YYYYMMDD format.

01  WS-YYYYMMDD                         PIC  9(08).
01  WS-DATE-IGZEDT4                     PIC  X(08) VALUE 'IGZEDT4'.
*
CALL WS-IGZEDT4      USING WS-YYYYMMDD

2.  Another way to do this is to use the LE callable function CEELOCT. We need to check with the mainframe infrastructure team to know if LE is optionally installed in our LPAR. If yes, then we can call this function which returns the result in the format of YYYYMMDD.  CEELOCT returns the result in 3 formats.
 a: Lilian  Date
 b.Lilian Seconds
 c. Gregorian  character strings.
It also returns the feedback code(CEE000 if call is successful)  which decides whether the function executed successfully or not.

WORKING-STORAGE SECTION.
01 WS-LILIAN PIC S9(9) COMP.
01 WS-XSECONDS PIC S9(18) COMP.
01 WS-GREGORN PIC X(17).
01 WS-FC.
    03 CEEIGZCT-RC PIC X.
        88 CEE000 VALUE LOW-VALUE.
PROCEDURE DIVISION.
       MAIN-SECTION.
           CALL 'CEELOCT' USING WS-LILIAN
                                WS-XSECONDS
                                WS-GREGORN
                                WS-FC
           IF CEE000 OF WS-FC
             DISPLAY 'Time: '    WS-GREGORN
           ELSE
             DISPLAY 'CEELOCT error' UPON CONSOLE
           END-IF

For LE enabled environment

3.  CURRENT-DATE  FUNCTION has been introduced after cobol II, which makes life much simpler. It is a 21 byte alphanumeric value which contains the below fields when read from left to right .

01  WS-CURRENT-DATE-FIELDS.
             05  WS-CURRENT-DATE.
                 10  WS-CURRENT-YEAR    PIC  9(4).
                 10  WS-CURRENT-MONTH   PIC  9(2).
                 10  WS-CURRENT-DAY     PIC  9(2).
             05  WS-CURRENT-TIME.
                 10  WS-CURRENT-HOUR    PIC  9(2).
                 10  WS-CURRENT-MINUTE  PIC  9(2).
                 10  WS-CURRENT-SECOND  PIC  9(2).
                 10  WS-CURRENT-MS      PIC  9(2).
             05  WS-DIFF-FROM-GMT       PIC S9(4).
 We need to use the cobol code like below and use the appropriate values as per our requirement.
 MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-FIELDS

Monday, April 20, 2015

COMP-3 variable in cobol. Calculate the number of bytes for COMP-3 variable.

COMP3 in cobol enables a computer to store 2 digits in each storage position, except for the rightmost position where the sign is stored. Each digit takes half a byte.

Point to remember:  Even if we specify 'S' or not in the variable declaration,  the sign is stored.

Suppose we move the digit 1265875 into a field 9(7). In display mode, cobol will occupy 7 bytes, ie, 7 storage positions.
If we use COMP-3 in the variable declaration,  it will take only 4 Bytes like below.

12
65
87
5C

Had it been a negative number, then The rightmost digit would store 'D' in place of  C.

How many bytes does COMP-3 take ?
To calculate the byte-length of a comp-3 field, start with the total number of digits and divide by 2 giving a result (discarding the remainder if any), then add 1 to the result.
  
Note: For "normal" processing the maximum number of digits is 18 . If we use compiler option as the ARITH(EXTEND) , the compiler will allow us to extend it to 31 bytes

Just to share, if we use Odd number of digits for packed decimal, the processing becomes 5-20 % faster than what the speed would be if we use even number of digits!. (Source : Some Informative journal in comp-3 in google )

Thursday, April 9, 2015

USAGE Clause in cobol. COMP, COMP1, COMP2, COMP3 VARIABLES IN COBOL

When Defining the cobol variables, the first thing which we see around is the USAGE clause. It only signifies how the data item will be internally stored. What will be its size.? In most instances we would see that a variable has been declared as(just for example) PIC X(10), and there is no USAGE clause. When the usage clause is not specified ,then it is assumed by the compiler that the USAGE IS DISPLAY.This is the default.
The other kind of USAGE is COMPUTATIONAL. As the name suggests, this is used when we want to perform numeric operations on the data items. I found some of the points to be worth remembering. Will be highlighting them in Red in this post.

Can we use USAGE IS DISPLAY for NUMERIC items? 
For text items, or for numeric items that are not going to be used in a computation (like Phone Numbers,postal code), the USAGE IS DISPLAY will not be harmful; but for numeric items upon which some arithmetic operation will be performed,the default usage is definitely not the best way.
When we use numeric items (like pic 9(3) )with default usage, internally they will be stored in ASCII.
When performing operations on these items, computer need to convert them to binary.Once done, computer need to convert it back to ASCII. These conversions unnecessarily slows down performance. Hence COMP is preferable in these scenarios.

Further more, Computational Usage clause can be classified into the following fields depending on the numeric items we use in our program.
Binary (USAGE BINARY or COMP-4)
Internal floating-point (USAGE COMP-1, USAGE COMP-2)
Internal decimal (USAGE PACKED-DECIMAL or COMP-3)

The maximum length of a comp item is 18 digits.

Q.Why do we use COMP in usage clause. When to use COMP ?
We know computers are Binary machines. So binary numbers will be more favorite to computers for doing calculations.Hence always use COMP for the variables which will be involved in numeric calculations.
Also it is used  for defining internal counters, subscripts.

PIC Clause of a COMP data item will only contain 9 or S.
example:
 01 WS-LEN          PIC S9(02)  COMP.

Now, when we declare the variables in comp, the compiler allocates spaces to them in words.which can be a half word(2 bytes),  Full word(4 bytes), Double word(8 bytes)

So if the PIC specified is 9(1) COMP or 9(2) COMP or 9(3) or  COMP OR 9(4) COMP, the space allocated by the compiler will be half word (2 bytes).

From PIC 9(5) COMP to PIC 9(9) COMP, the space allocated will be 4 bytes

For a PIC clause with more than 9 bytes, compiler will allocate  double word(8 bytes).

In short,
S9(01) - S9(04)      Half word.
S9(05) - S9(09)      Full word.
S9(10) -  S9(18)     Double word.

Q.When to use COMP-1 and COMP-2 ? 
When we want to use Fractional numbers, numbers having decimal digits, then COMP-1 is the choice.Thus USAGE IS COMP-1 is used to store floating point numbers(real numbers)
COMP-1 uses 4 bytes of storage.
Exactly in the same way, we need to use COMP-2 for extremely big numbers requiring high precision.
COMP-2 occupies 8 bytes of storage. Hence no need to use PIC clause since size is already pre defined.
Remember: No picture clause is needed when defining COMP-1 and COMP-2 items.


Read COMP3 Variables Here.

Saturday, March 21, 2015

SEARCH and SEARCH ALL in COBOL with examples

SEARCH is a serial search.It can be used for both sorted and unsorted data inside the table.The table needs to be defined with an index .When we use the search function, the function starts with the current setting of the index and it goes on until to the end of the table.The starting value of the index is left upto the choice of the programmer. We can set the value of the index value just before the search starts using the SET keyword.

IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.

DATA DIVISION.
WORKING-STORAGE SECTION.
   01 WS-TABLE.
          05 WS-TEST PIC X(1) OCCURS 10 TIMES INDEXED BY I.

   01 WS-SRCH-STRNG PIC A(1) VALUE 'R'.

PROCEDURE DIVISION.
   MOVE 'ABCDEFRJKL' TO WS-TABLE.
   SET I TO 1.
   SEARCH WS-TEST
     AT END DISPLAY   'R NOT FOUND IN TABLE'
     WHEN WS-TEST(I)=WS-SRCH
     DISPLAY    'WE FOUND YOU IN THE TABLE'
   END-SEARCH.  

STOP RUN.

This linear Search will iterate through the entire table until the search-string is found or the end of table is reached.
In this case, since our search string 'R' is there in the table, the SYSOUT will display 'WE Found.. '.

SEARCH ALL is a binary search and the table must be sorted .That is the the prerequisite to use search all. The outcome of SEARCH ALL is either a yes or a no. Hence we can not code multiple search conditions when using SEARCH ALL function.
Contrary to search function, there is no need to initialize the index .

Check the following code:

IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.

DATA DIVISION.
   WORKING-STORAGE SECTION.
   01 WS-TABLE.
      05 WS-BIN-SRCH OCCURS 10 TIMES ASCENDING KEY IS WS-NUM INDEXED BY I.
      10 WS-NUM  PIC 9(2).
      10 WS-DEP   PIC A(3).

PROCEDURE DIVISION.
   MOVE '12ABC56DEF34GHI78JKL93MNO11PQR' TO WS-TABLE.
   SEARCH ALL WS-BIN-SRCH
     AT END DISPLAY 'BIN-SRCH NOT FOUND'
     WHEN WS-NUM (I)=93
     DISPLAY 'BIN-SRCH FOUND '
     DISPLAY WS-NUM(I)
     DISPLAY WS-DEP(I)

Just a point to note:  The table is searched in ASCENDING ORDER. If you see, the table is defined with ASCENDING key clause. In case we want, we can always define the table in DESCENDING KEY clause.
To use SEARCH ALL,a field must be in ASCENDING or DESCENDING key clause. This Identifier must be an entry within the table

When to use SEARCH and SEARCH ALL Function:
· For a table with less than 50 entries, go for SEARCH (Sequential Search)
· For a table with more than 50 entries go for SEARCH ALL (Binary Search)

Saturday, October 11, 2014

File Handling in cobol - COBOL TUTORIAL

A data file is nothing but a collection of relevant records. Cobol reads the records line by line. Read the first line and process the entire logic,then read the second record and so on... Generally we use two types of file in our program.
1. Sequential files
2. Vsam Files
What is a sequential File ?
A sequential file is one whose records are in sequential order, from first to last. When we want to process this file, we need to start from the first records and go on sequentially. We can not delete and insert record in the middle suddenly. We can only add the records in the end.
Coming on to Vsam file, we have mainly 3 types which we use frequently in program.
a) KSDS  b) ESDS c) RRDS. We will see what they are and how to handle them in subsequent posts.

Coming back to Cobol file handling, let us see steps and ways to read/write files:
Before going into details, we need to know the bare essentials needed for file handling.
1. Assign the file to cobol program
2. Open the file (Either in input or output mode. There are other modes as well.Will see later)
3. Read the file into Working storage variables
4. Write the logic in procedure division as per the requirement
5. Write the output and Close the file.

The Very First step in writing a Cobol is to assign the Files . We all know that to run the cobol program ,we need JCL. So, JCL is the place where we give the actual physical file needed to run our program.
But, Our cobol  program need to understand this thing.
So this association between the JCL file and the cobol program is established in Environment Division using 'ASSIGN TO' Clause .The mapping with JCL DDNAME is done here. The file is allocated to our program by this ASSIGN Statement.
Next, the layout of the file and its attributes are defined in the FILE SECTION of DATA DIVISION. We should have a copybook to identify what value corresponds to what fields. That needs to be predefined in a copybook and should be included in the program using COPY statement.
Cobol Assign Clause
 But, before cobol uses these files for reading or writing, we need to OPEN these files with some keywords which will make cobol understand, whether the file is a input file or it will be used as an output file.
We need to use  these statements  in the procedure division to instruct cobol the kind of operation we will be performing on the files.
PROCEDURE DIVISION.
OPEN INPUT   CMF-FILE
     OUTPUT     OUT-FILE1
                         OUT-FILE2.   
Have a look into the JCL for better understanding of the file association between cobol and JCL.
Look for the DD names  CMFIN,FILE1, FILE2.
CMFIN is used with Dispostion of SHR which we are using as input in cobol
FILE1, FILE2 has Disposition of (NEW,CATLG,DELETE) which implies this file will be created new and hence opened in output mode in cobol code (above code)
//STEP0010 EXEC PGM=TSTCLAIM                         
//STEPLIB  DD DSN=MYSTEP1.BTCHLOAD,DISP=SHR          
//SYSOUT   DD SYSOUT=*                               
//SYSDBOUT DD SYSOUT=*                               
//CMFIN    DD DSN=TEST.CLAIM.INPUT,DISP=SHR        
//********  OUTPUT FILES  ******                     
//FILE1    DD TEST.OP1.CLAIM,                        
//         DISP=(,CATLG,DELETE),                     
//         DCB=(LRECL=205,RECFM=FB,BLKSIZE=0),       
//         UNIT=TEST,SPACE=(TRK,(15,15),RLSE)        
//FILE2    DD DSN=TEST.OP1.CLAIM,                    
//         DISP=(,CATLG),UNIT=&UNIT,SPACE=(TRK,(15,15)
//         DCB=(LRECL=110,RECFM=FB,BLKSIZE=0)        
//**** END  ********                                  
Back to cobol:  Once the above declaration is made, we can use the input file to read the input records one by one and process it.
READ CMF-FILE  INTO   W-CMF-CLAIMS-DETAIL     
     AT END   DISPLAY 'ERROR - EMPTY INPUT FILE !!!!!'
              STOP RUN.                              
 So, what is this  W-CMF-CLAIMS-DETAIL ?  This is the copybook which is defined for the input file. This READ statement dumps the every line of the input file into this structure , so that we can use these variables and process the data.

Lets see how does the READ statement work
Suppose your input file looks like:
20140924001102000560
20140924004214000560
20111003233513000560
20111217000439000560
20120814225039000560
20120602011643000560
20140924004214000560
 Simply by looking into these values wont make you understand what these digits are. But if we have a copybook, say  W-CMF-CLAIMS-DETAIL defined in the WORKING STORAGE of your cobol like below:
01 W-CMF-CLAIMS-DETAIL
     05 WS-CLAIM-DT  PIC X(08).
     05 WS-CLAIM-STATUS PIC X(06).
     05 WS-CLAIM-COMPANY PIC X(06).
Once we use the read statement for the very first time after the OPEN statement,like above
READ CMF-FILE  INTO   W-CMF-CLAIMS-DETAIL , the first 8 bytes of data will be placed in
WS-CLAIM-DT, next 6 bytes in WS-CLAIM-STATUS, and next 6 bytes in WS-CLAIM-COMPANY  Resulting in like below:
WS-CLAIM-DT will have the value 20140924
WS-CLAIM-STATUS will contain 001102
WS-CLAIM-COMPANY will contain  000560
Every time the read statement is performed, these values will get changed for the next record and so on  until EOF (End OF file) is reached.
Do All the processing as per the requirement in the procedure division and then the very last steps in this process would be writing the output file and closing all the files.
WRITE OUT-REC1 FROM WS-OUT-REC1
WRITE OUT-REC2 FROM WS-OUT-REC2.
CLOSE CMF-FILE-IN
      OUT-FILE1  
      OUT-FILE2. 

Sunday, June 8, 2014

How to define KSDS, ESDS ,RRDS VSAM with IDCAMS.. Explanation of the VSAM parameters

VSAM is one file storage system used to store and retrieve data. It stores data, but not like a relational model or hierarchical model like DB2 or IMS. In fact, there are many structures in DB2, which are implemented using VSAM .We can use VSAM files in both batch and online(CICS) operations.
How do we create a vsam file?
The IBM Access Methods Services (AMS) utility,popular as IDCAMS is the utility to create and maintain VSAM files. In this context,we should know that VSAM is totally catalog driven.When ever we create a VSAM dataset,ie a VSAM file, an entry is recorded in the system catalog which stores the cluster informtion.
Vsam Cluster? what is it ? ::
In this VSAM world,simple VSAM files are often called clusters. A cluster is the set of catalog entries that represent a file.
So, how many types of VSAM can we create, rather how many types of VSAM are there?
The answer is 4 types:
1.ESDS    or Entry Sequenced dataset
2.KSDS    or Key Sequenced dataset
3.RRDS    or Relative record dataset
4.LDS     or Linear dataset
Frankly,till date i never came across the use of LDS or RRDS. The most Widely used VSAM are KSDS and ESDS.
Lets see the JCL to create a KSDS:
How to create a KSDS and the description of the parameters.

//STEP0020 EXEC PGM=IDCAMS
//SYSPRINT  DD SYSOUT=*           
//SYSIN     DD *

  DEFINE CLUSTER(             -                
       NAME(TEST.FILE.MYVSAM) -              
       RECSZ(300 2000)      -                
       KEYS(41 20)          -                
       MANAGEMENTCLASS(xxxx) -           
       INDEXED              -                
       SPEED                -                
       SHR  (2 3)           -                
       FSPC (24,7)          -                
       BUFSP (39936)        -                
       DATACLAS (DCVSEXT))  -                
       DATA(NAME(
TEST.FILE.MYVSAM.DATA) -    
         CISZ (18432)         -              
         CYL  (200,100))       -             
       INDEX (NAME(
TEST.FILE.MYVSAM.INDEX) - 
         CISZ (1024)          -              
         CYL  (10,10))

As we see, the CLUSTER have two components here. The DATA and the INDEX part.
The keywords are marked and highlighted in red.
Explanation of the VSAM parameters:

1. RECORDSIZE(300  2000)
Specifies the record length of the file. The first parameter specifies the average length of the record and second parameter tells the maximum record length.
RECORDSIZE(avg  max)
avg : Average length of records
max : Maximum length of records
e.g. :
 RECORDSIZE(300  2000) [Fixed Length records]
 RECORDSIZE(300  300)    [Variable Length records]
Note :  RECORDSIZE or RECSZ  can also be used in the IDCAMS define step.
We can use this parameter in the cluster level as well as in the data level.
If not used, VSAM will use its default recordsize which is  RECORDSIZE(4086 4086)
 
2. KEYS(41 20)
The first parameter defines the key length and the second parameter defines the offset, ie, the beginning of the key position from the starting of the record
Thus the general format is like :
        KEYS(length-of-the-key  offset-from-begining)

3. MANAGEMENTCLAS : Optional Clause

4. INDEXED: This specifies that the VSAM is a KSDS VSAM

5. SPEED or RECOVERY option is coded at the CLUSTER or DATA level.It just governs how the VSAM load data into the file.
   With the RECOVERY option, the VSAM pre-formats each Control area with binary  zeros before it  writes any control interval to it. When SPEED is specified, no such additional activity is performed and therefore the data loading is much faster with SPEED option.

6..FSPC (24,7): FSPC or FREESPACE(24,7) is same thing.
FREESPACE parameter applies to the KSDS.This free space can be used for adding new records or for expanding existing variable records.FREESPACE applies only to the data component. For the FREESPACE parameter, the first value defines the percentage of free space to be reserved within each control interval, and the second defines the number of control intervals within each control area that should be reserved as free space.
Default is FREESPACE(0 0)

7. SHR  (2 3)OR SHAREOPTIONS ( 2 3):
This parameter tells VSAM whether you want to let two or more jobs to process your file at the same time. It specifies how a VSAM dataset can be shared. This is a big topic to deal with .Read here to explore this feature.
8. BUFSP(39936):  The number of buffers that can be used to hold INDEX and DATA records.
9. CYLINDERS(Pri Sec)or CYL(200,100):Primary : Number of units of primary space to allocate.This amount is allocated once when the dataset is created.Secondary : Number of units of secondary space to allocate.

In the DEFINE CLUSTER command we need to mention the type of VSAM we are creating like:

INDEXED   for KSDS
NONINDEXED  for  ESDS
NUMBERED for  RRDS
LINEAR for  LDS

So, Here is the sample JCL for ESDS VSAM

DEFINE CLUSTER(                   -               
           NAME(TEST.RM3452.FILE) -             
           RECSZ(300 2000)        -                     
           NONINDEXED             -               
           SPEED                  -               
           SHR  (2 3)           
      DATA(NAME(TEST.RM3452.FILE.DATA) -   
             CISZ (18432)              -             
             CYL  (200,100))           -

Tuesday, May 6, 2014

Scrollable Cursor in DB2 : Sensitive cursor,insensitive cursor and asensitive cursor!!

Having completed the Basics of CURSOR in db2 ,we know there can be scrollable and non scrollable cursor. Further more There are two types of DB2 scrollable cursors .(a).Sensitive (b) Insensitive.
(We will difference between static and dynamic cursors in next post. Here we will see broadly what is sensitive/insensitive cursor)
To start with we will see first what is an insensitive cursor.Let us see how the  keyword 'INSENSITIVE' is used to declare this type of cursor. 
(We will see difference between STATIC and DYNAMIC cursor in next post)

DECLARE C1 INSENSITIVE SCROLL CURSOR FOR
 SELECT STAFF_ID,NAME  FROM EMP
....
OPEN C1
...
FETCH C1
..
CLOSE C1 
We will see how and where the INSENSITIVE feature is shown below.

Once we open the C1 cursor, a temporary table is created in the WORK File database  which holds the data from the base table ,ie, EMP table. (We must know that to use scrollable cursors we must use declared temporary  tables.DB2 places the rows returned from the cursor into these Temporary tables.)
TIMELINE T1: The Cursor is opened and result set is fetched. We will see that the  base table EMP and the result table(the result of cursor open statement) is same


STAGE1: The cursor is fetched and Main table and result table looks same
TIMELINE T2 (T2>T1) :  After some time T2,user deletes one row from the main table ie the EMP table.But since the cursor is INSENSITIVE, it does not sense the modification done to the base table, thereby shows the same rows even though main table has changed.

STAGE2: Row deleted from main table , yet the cursor result table shows the deleted row!!

Lets see now SENSITIVE CURSOR:
DECLARE C1 SENSITIVE STATIC SCROLL CURSOR FOR
 SELECT STAFF_ID,NAME  FROM EMP
....
Proceeding in the same way, let us review the Timelines T1 and T2 of the cursor life cycle.
TIMELINE T1: The Cursor is opened and result set is fetched. We will see that the  base table EMP and the result table(the result of cursor open statement) is same.  This is the same as shown above.
TIMELINE T2 (T2>T1) :  After some time T2,user deletes one row from the main table ie the EMP table.But since the cursor is SENSITIVE, the Temporary table will sense the modification done,ie the delete and will also delete the corresponding row in the Temporary table.
In Timeline T2, the cursor fetched reflects the same change as the base table EMP.
SENSITIVE CURSOR comes with the combination of  SENSITIVE STATIC and SENSITIVE DYNAMIC
Lets look at the FETCH statements for these scrollable type cursors.
All the possible FETCH options are shown here

To FETCH 5th Row from beginning of the Result set:
FETCH SENSITIVE ABSOLUTE +5 FROM C1
Fetch the FIRST ROW
FETCH SENSITIVE FIRST FROM C1
Move forward:
FETCH NEXT FROM C1
Move Backward:
FETCH PRIOR FROM C1 
Fetch 5th last row:
FETCH ABSOLUTE -5 FROM C1

RELATIVE n - will FETCH the row that is n rows away from the last row fetched
ABSOLUTE n - will FETCH the row that is n rows away from the first row in the results set

CURSORS in DB2 and how to use CURSOR in DB2?


A mechanism allowing an application program (cobol-db2 program for example) to retrieve a set of rows. Suppose our SQL query fetches many-rows result table. Using CURSOR our COBOL program can gain access to individual row of  the result table

There are two types of cursor:
1.Row-set positioned cursor : Here the result table are stored into Host variable arrays.
2.Row-positioned cursor : This type points to the current row/particular row in the result set.
It points to the next row to be passed to the application program.

The primary steps for using any  cursor are as follows:
Step1. Declare the cursor
Step2 Open the Cursor. This causes Db2 to build the result set.
Step3. Fetch each row ,one at a time, and pass it onto application program
Step4: Close the cursor.

DECLARE  the cursor:
EXEC SQL
 DECLARE EMP_CURSOR CURSOR FOR
 SELECT EMP_NAME,EMP_ID
 FROM EMP
 WHERE EMP_JOIN_DATE > '20000101'
END-EXEC.

DECLARE statement does not build result set.It simply forms the SQL statement we want to use to fetch the data. At DB2 precompile time, the definition of the CURSOR is stored in the bindfile, and the statement is commented.

OPEN  the cursor:
The open statement actually runs the SQL statement and builds the result set and makes it ready ready to be processed to be used to the application program in subsequent steps.
EXEC SQL
 OPEN EMP_CURSOR
END-EXEC.

Once the open is done, we need to fetch the data

FETCH the cursor:
EXEC SQL
 FETCH  EMP_CURSOR
 INTO :EMPNAME,:EMPID
END-EXEC.


FETCH is the only way to get the result into application program Host variable. We fetch each row into the Host variable and process the data. We can continue fetching of the data until we get a SQLCODE of +100  which implies END of the result table.
CLOSE the CURSOR
Once we are done with fetching of the records, we need to close the cursor.
EXEC SQL
 CLOSE EMP_CURSOR
END-EXEC.


How to UPDATE AND DELETE  records in cursor.
There can be instances where we need to modify the data in db2 table based on some values in a programmatic way. Had it been a spufi or QMF we have our update and delete statements ready to run and modify. But  we are in cobol program. Nevertheless we can do the same modifications using cursors again.!! We need to add special clause while declaring the cursor with  'FOR UPDATE OF'.
Even if we want to delete, we need to mention 'FOR UPDATE OF'  in declare statement  and we need to delete the entire row. Also we need to use WHERE CURRENT OF to update or delete the last row fetched.
Lets see the below example where we will update and delete some row in the cursor :

EXEC SQL
 DECLARE EMP_CURSOR CURSOR FOR
 SELECT EMP_NAME,EMP_ID
 FROM EMP
 WHERE EMP_JOIN_DATE > '20000101'

 FOR UPDATE OF NAME       <== DECLARE THE CURSOR WITH THIS CLAUSE
END-EXEC.

...............................
EXEC SQL
 UPDATE EMP
 SET EMP_NAME=:EMPNAME
 WHERE CURRENT OF EMP_CURSOR
END-EXEC

EXEC SQL
 DELETE  FROM EMP
 WHERE CURRENT OF EMP_CURSOR
END-EXEC.

****Important point Regarding the Usage of 'FOR UPDATE OF'  in CURSOR.****
If the select statement defining the cursor contains ORDER BY,GROUP BY, DISTINCT, SET OPERATORS ( UNION,EXCEPT, INTERSECT), JOIN, FOR FETCH ONLY/FOR READ ONLY, then the usage of 'FOR UPDATE OF' is NOT permitted. The above keywords make the cursor READ ONLY cursor.


Read about Cursor types: Sensitive and insensitive cursors

Wednesday, April 9, 2014

Static call and Dynamic call in cobol with example - compiler options for static and dynamic call

This is a much discussed topic among the COBOL programmers.We can identify the calls by seeing the 'CALL' structure.Lets see what is the difference between static and dynamic call and other information.
Static call implies that the objects modules(of called and calling) are bound together before they use each other.This bonding remains the same until one of the program gets changed and the whole set is compiled/linked again.
Dynamic call implies the calling program does not know about the called program until the call takes place.The bonding between the program happens right at the time the call is made 

Lets see in details how the calls are made and few other details
In case of static call, we refer to the called program name directly in the call statement. 
Ex: CALL ‘PGM1’.

In case of dynamic Call, we call one working-storage variable which is populated with the called program name at run time dynamically. 
01 WS-PGM PIC X(08). <<== Working storage variable
Move ‘PGM1’ to WS-PGM 
CALL WS-PGM                 
Here WS-PGM is the Working Storage item. In Procedure Division we are moving the called program name 'PGM1' to WS-PGM and then calling it.

When to go for Static and Dynamic call ?
Taking the decision to call statically or dynamically is upto the programmer.Generally we consider the size of the program and decide.If the size of the called program is  small (i mean, very few lines of code and non complex functions )then we can go for static call, otherwise dynamic call will be better.Both have its positive and negative points.
So in case of static call:
If we have the main program PGM-A and it calls two sub programs statically(pgm-b &pgm-c), we will have only 1 load module for all the three.Load modules of pgm-b and pgm-c will be linked edited into the load module of PGM-A making the size of the load bigger.
Negative points for a static call
Since the load modules exists together,it takes up more virtual space on disk 
If any changes are made to called program, then all the programs must be compiled/linkd.
Positive point:  Execution is fast

In case of Dynamic call:
As the name suggests, the program is called dynamically.The load module of the called program  will exists separately in the load module library. Thus here if PGM-A calls pgm-b and pgm-c, we will have 3 load modules our load library.
Positive point:
The main module does not take up unnecessary space.
Since these are stand alone programs, we can compile/link respective programs without touching all the programs and main program.
Negative points for a dynamic Call:
Since it executes with program call resolution, the call is a bit slow than static all.

Compiler options which can override the Static and dynamic calls:
If compiled with NODYNAM compiler option
CALL 'PGM-A' will be handled as  a static call
CALL WS-VARA  will be treated as dynamic call

If compiled with DYNAM compiler option:
CALL 'PGM-A' will be also treated as  a dynamic call
CALL WS-VARA will be treated as a dynamic call

Monday, September 9, 2013

Different forms of INSPECT clause in cobol

Below are the different INSPECT with REPLACE clause and their usage in cobol.

INSPECT WS-TEXT      REPLACING ALL LOW-VALUES BY SPACE
INSPECT WS-TEXT      REPLACING ALL ' ' BY '0'
INSPECT WS-TEXT      REPLACING ALL LOW-VALUES BY SPACES
INSPECT WS-TEXT      REPLACING FIRST '*' BY '%'
INSPECT WS-TEXT      REPLACING ALL '~' BY WS-INSPECT-VAL
INSPECT WS-TEXT      REPLACING ALL WS-INSPECT-VAL  BY '('
INSPECT WS-TEXT      REPLACING ALL  '('   BY    ')'     AFTER INITIAL '('

**
01 VAR-STRING PIC X(20) VALUE 'THIS IS COBOL'.
01 VAR-COUNT PIC 9(2).

INSPECT VAR-STRING TALLYING VAR-COUNT FOR ALL 'S'
O/P : VAR-COUNT = 2
**
VAR-STRING = "THIS IS COBOL"
INSPECT VAR-STRING TALLYING VAR-COUNG FOR ALL "S" AFTER INITIAL SPACE.

O/P : VAR-COUNT = 1 (Since first 'S' wont be counted . All the 'S' after the first space will be counted.)
**
VAR-STRING = "MY COBOL PROGRAMMING COURSE"
INSPECT VAR-STRING TALLYING VAR-COUNT FOR ALL LEADING 'M'

O/P : VAR-COUNT = 1 (ONLY THE FIRST 'M' WILL BE TAKEN INTO ACCOUNT)
**
01 WS-INPUT3='PTEST'
INSPECT WS-INPUT3 CONVERTING 'PTHASI' TO '3090RI'.
O/P:  30ES0
The exact number of characters need to be compared and mapped. Also duplicate is not
allowed in the parameters.
ex: INSPECT WS-INPUT3 CONVERTING 'PTPTSI' TO '3090RI' will result in error
because 'P' and 'T' is duplicated.
**