SQL (Structured Query Language) is used to retrieve the data from the database (DB2).

In order to retrieve the data from DB2 from the application program, SQL queries are required to be coded in the program. The SQL queries should code between EXEC SQL and END-EXEC to identify quickly and get separated from the application program language.

Note! In this topic, we are using the COBOL language as application language.
"SQL statements" term referred to as "DB2 statements" for more understanding.

Suppose the SQL queries are not coded between EXEC SQL and END-EXEC. In that case, the COBOL compiler tries to recognize them as COBOL statements and throws the compilation error because they are not.

The compilation process of application language(COBOL, PL/I, etc.,) and DB2 (SQL queries) is called as Precompilation Process.

The compilation process of COBOL + DB2 Program (Precompilation process) -

The compilation process of the COBOL + DB2 program is different from the simple COBOL program compilation.

If the program has DB2 statements, then we should add the precompiler step to the compilation JCL. i.e., the Precompilation JCL = Precompile step + COBOL Compile JCL.

Diagram -

Precompilation process

PRECOMPILER -

  • Precompiler is mainly responsible for dividing the COBOL, DB2 statements separately.
  • Precompiler takes the COBOL + DB2 source code as an input and separates the COBOL, DB2 statements to the two different libraries (COBOL Loadlib and DBRM).
  • Precompiler is responsible for checking the syntax errors of DB2 statements before placing them in DBRM (DataBase Request Module).
  • Precompiler doesn't check the syntax errors of COBOL statements or any other programming language(PL/I etc.) statements.
  • The precompiler is used to generate timestamp tokens for each (COBOL and DB2) as specified in the diagram and these are validated while BINDing the program.

DBRM (DataBase Request Module) -

  • DBRM is DataBase Request Module where syntax-free (syntax verified) SQL statements are stored.
  • DBRM library is a user-defined PDS and syntax-free SQL statements stores with the program name.

BIND -

BIND is the process to find the optimized access path to retrieve the data from the DB2 for the SQLs coded in the program.

BIND takes DBRM as input and generates the optimized access path with the help of an optimizer that considers the below factors.

  • Table size
  • Number of columns retrieving
  • Number of rows retrieving
  • The availability of primary key
  • The availability of Foreign key
  • And many more.

The Utility used for BIND is IKJEFT01. BIND is used to specify isolation levels.

BIND process also checks some of the syntax errors of DB2 statements. For Example - Whenever we use the GROUP BY and ORDER BY clause, we get a BIND error if we can't specify the column in SELECT.

Package -

  • The package is an intermediate component between the DBRM and PLAN.
  • The package contains an optimized access path (OAP) that is generated at the BIND step.
  • The package is a non-executable component.
  • The package can contain one or more DBRMs.
  • The package's main advantage is that the rebound is not required when any change in the sub-program. Compiling subprogram alone is only sufficient.

Plan -

  • The plan also contains an optimized access path (OAP); however, it is an executable component.
  • The plan used to execute the program.
  • The plan has the best access path to retrieve the data from the database using the SQLs coded in the program.

RUNTIME SUPERVISOR mainly responsible for to check the what are the time stamps for COBOL & DB2

Precompilation JCL -

Note! Below precompilation JCL works as it is when you change your project-specific utility libraries and LOAD, COPY, DCLGEN, and DBRM libraries.

Code -

Precompilation JCL
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
//MTH001P JOB MSGLEVEL=(1,1),NOTIFY=&SYSUID                             
//********************************************************************  
//*  COBOL + DB2 PRECOMPILE AND LINKEDIT                             *  
//********************************************************************  
//*        Precompile the IBM COBOL program                          *  
//********************************************************************  
//PCSTEP   EXEC PGM=DSNHPC,                                             
//             PARM='HOST(IBMCOB),XREF,SOURCE,FLAG(I),APOST'            
//STEPLIB  DD  DISP=SHR,DSN=MTHA10.DBAG.SDSNEXIT                        
//         DD  DISP=SHR,DSN=MTHA10.SDSNLOAD                             
//SYSCIN   DD  DSN=&&DSNHOUT,DISP=(MOD,PASS),UNIT=SYSDA,                
//             SPACE=(800,(500,500))                                    
//SYSIN    DD  DSN=MTH.COBDB2.SRCLIB(TESTPROG),DISP=SHR                 
//SYSLIB   DD  DSN=MTH.COBDB2.DCLGEN,DISP=SHR                           
//         DD  DSN=MTH.COBDB2.COPYLIB,DISP=SHR                          
//DBRMLIB  DD  DSN=MTH.COBDB2.DBRMLIB(TESTPROG),DISP=SHR                
//SYSPRINT DD  SYSOUT=*                                                 
//SYSTERM  DD  SYSOUT=*                                                 
//SYSUDUMP DD  SYSOUT=*                                                 
//SYSUT1   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT2   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//********************************************************************  
//*        Compile the IBM COBOL program if the precompile           *  
//*        return code is 4 or less.                                 *  
//********************************************************************  
//COB      EXEC PGM=IGYCRCTL,                                           
//             PARM=('SIZE(4000K),BUFSIZE(32760),LIST,LIB,MAP,OBJECT',  
//             'DATA(31),XREF,RENT'),                                   
//             COND=(4,LT,PCSTEP)                                       
//STEPLIB  DD  DSNAME=IGY420.SIGYCOMP,DISP=SHR                          
//SYSPRINT DD  SYSOUT=*                                                 
//SYSTERM  DD  SYSOUT=*                                                 
//SYSLIN   DD  DSN=&&LOADSET,DISP=(MOD,PASS),UNIT=SYSDA,                
//             SPACE=(800,(500,500))                                    
//SYSLIB   DD  DSN=MTH.COBDB2.COPYLIB,DISP=SHR                          
//SYSIN    DD  DSN=&&DSNHOUT,DISP=(OLD,DELETE)                          
//SYSUT1   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT2   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT3   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT4   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT5   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT6   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT7   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//********************************************************************  
//*        Linkedit if the precompile and compile                    *  
//*        return codes are 4 or less.                               *  
//********************************************************************  
//LKED     EXEC PGM=IEWL,PARM='MAP,XREF',                               
//         COND=((4,LT,PCSTEP),(4,LT,COB))                              
//SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED                                
//         DD  DISP=SHR,DSN=MTHA10.SDSNLOAD                             
//         DD  DISP=SHR,DSN=ISP.SISPLOAD                                
//         DD  DISP=SHR,DSN=GDDM.SADMMOD                                
//         DD  DISP=SHR,DSN=MTH.COBDB2.LOADLIB                          
//SYSLIN   DD  DSN=&&LOADSET,DISP=(OLD,DELETE)                          
//         DD  DDNAME=SYSIN                                             
//SYSLMOD  DD  DSN=MTH.COBDB2.LOADLIB(TESTPROG),DISP=SHR                
//SYSPRINT DD  SYSOUT=*                                                 
//SYSUT1   DD  SPACE=(1024,(50,50)),UNIT=SYSDA                          
//SYSIN    DD  DUMMY                                                    
**************************** Bottom of Data ****************************

Precompilation Ways -

In the real-time environment, the precompilation process takes place in two ways -

  • Using Version Control tools like Endeavor, Changeman, etc.
  • Using a personal compilation JCL

The main difference between these two types of processes is the Bind Step.

Using Version Control tools -

If compiling a COBOL +DB2 program using a version control tool, the JCL also has the Bind step at the end to bind the program to the mainframe region PLAN.

i.e., Compilation JCL = Precompilation JCL + Bind Step.

Using a personal compilation JCL -

If compiling a COBOL + DB2 program using JCL, the developer should bind the program separately after the compilation process is completed using compilation JCL.

i.e., Compilation JCL = Precompilation JCL.

BIND process should complete separately using another bind JCL. Refer to the BIND process described in a separate topic.

Practical Example -

Scenario - Below example describes how the COBOL + DB2 program precompiled using JCL.

Input - EMPLOYEE_DETAILS table

employee_details table

Program Code - To retrieve employee with id 5.

Constant program Code
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
       IDENTIFICATION DIVISION.                                         
       PROGRAM-ID. SELECT1.                                             
                                                                        
       ENVIRONMENT DIVISION.                                            
       DATA DIVISION.                                                   
       WORKING-STORAGE SECTION.                                         
                                                                        
           EXEC SQL                                                     
             INCLUDE SQLCA                                              
           END-EXEC.                                                    
                                                                        
           EXEC SQL                                                     
             INCLUDE EMPLDET                                            
           END-EXEC.                                                    
                                                                        
       01 WS-EMPID          PIC S9(9) USAGE COMP.                       
                                                                        
       PROCEDURE DIVISION.                                              
                                                                        
           MOVE 5    TO WS-EMPID.                                       
                                                                        
           EXEC SQL                                                     
                SELECT EMP_ID,                                          
                       EMP_NAME,                                        
                       DESIGNATION,                                     
                       MANAGER_ID,                                      
                       DATE_OF_HIRE,                                    
                       SALARY,                                          
                       DEPT_ID                                          
                INTO   :EMP-ID,                                         
                       :EMP-NAME,                                       
                       :DESIGNATION,                                    
                       :MANAGER-ID,                                     
                       :DATE-OF-HIRE,                                   
                       :SALARY,                                         
                       :DEPT-ID                                         
                FROM   EMPLOYEE_DETAILS                                 
                WHERE  EMP_ID = :WS-EMPID                               
           END-EXEC.                                                    
                                                                        
           IF SQLCODE = 0                                               
              DISPLAY  EMP-ID,"|",EMP-NAME,"|",DESIGNATION,"|",         
              MANAGER-ID,"|",DATE-OF-HIRE,"|",SALARY,"|",DEPT-ID        
           ELSE                                                         
              IF SQLCODE = 100                                          
                 DISPLAY "EMPLOYEE DETAILS NOT FOUND"                   
              ELSE                                                      
                 DISPLAY "DB2 ERROR"                                    
              END-IF                                                    
           END-IF.                                                      
                                                                        
           STOP RUN.                                                    
**************************** Bottom of Data ****************************

Precompilation JCL -

Precompile JCL Code
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
//MATEGJP JOB MSGLEVEL=(1,1),NOTIFY=&SYSUID                             
//********************************************************************  
//*  COBOL + DB2 PRECOMPILE AND LINKEDIT                             *  
//********************************************************************  
//PCSTEP   EXEC PGM=DSNHPC,                                             
//             PARM='HOST(IBMCOB),XREF,SOURCE,FLAG(I),APOST'            
//STEPLIB  DD  DISP=SHR,DSN=DSNA10.DBAG.SDSNEXIT                        
//         DD  DISP=SHR,DSN=DSNA10.SDSNLOAD                             
//SYSCIN   DD  DSN=&&DSNHOUT,DISP=(MOD,PASS),UNIT=SYSDA,                
//             SPACE=(800,(500,500))                                    
//SYSIN    DD  DSN=MATEGJ.COBDB2.SRCLIB(SELECT1),DISP=SHR               
//SYSLIB   DD  DSN=MATEGJ.COBDB2.DCLGEN,DISP=SHR                        
//         DD  DSN=MATEGJ.COBDB2.COPYLIB,DISP=SHR                       
//DBRMLIB  DD  DSN=MATEGJ.COBDB2.DBRMLIB(SELECT1),DISP=SHR              
//SYSPRINT DD  SYSOUT=*                                                 
//SYSTERM  DD  SYSOUT=*                                                 
//SYSUDUMP DD  SYSOUT=*                                                 
//SYSUT1   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT2   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//********************************************************************  
//*        Compile the IBM COBOL program if the precompile           *  
//*        return code is 4 or less.                                 *  
//********************************************************************  
//COB      EXEC PGM=IGYCRCTL,                                           
//             PARM=('SIZE(4000K),BUFSIZE(32760),LIST,LIB,MAP,OBJECT',  
//             'DATA(31),XREF,RENT'),                                   
//             COND=(4,LT,PCSTEP)                                       
//STEPLIB  DD  DSNAME=IGY420.SIGYCOMP,DISP=SHR                          
//SYSPRINT DD  SYSOUT=*                                                 
//SYSTERM  DD  SYSOUT=*                                                 
//SYSLIN   DD  DSN=&&LOADSET,DISP=(MOD,PASS),UNIT=SYSDA,                
//             SPACE=(800,(500,500))                                    
//SYSLIB   DD  DSN=MATEGJ.COBDB2.COPYLIB,DISP=SHR                       
//SYSIN    DD  DSN=&&DSNHOUT,DISP=(OLD,DELETE)                          
//SYSUT1   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT2   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT3   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT4   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT5   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT6   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//SYSUT7   DD  SPACE=(800,(500,500),,,ROUND),UNIT=SYSDA                 
//********************************************************************  
//*        Linkedit if the precompile and compile                    *  
//*        return codes are 4 or less.                               *  
//********************************************************************  
//LKED     EXEC PGM=IEWL,PARM='MAP,XREF',                               
//         COND=((4,LT,PCSTEP),(4,LT,COB))                              
//SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED                                
//         DD  DISP=SHR,DSN=DSNA10.SDSNLOAD                             
//         DD  DISP=SHR,DSN=ISP.SISPLOAD                                
//         DD  DISP=SHR,DSN=GDDM.SADMMOD                                
//         DD  DISP=SHR,DSN=MATEGJ.COBDB2.LOADLIB                       
//SYSLIN   DD  DSN=&&LOADSET,DISP=(OLD,DELETE)                          
//         DD  DDNAME=SYSIN                                             
//SYSLMOD  DD  DSN=MATEGJ.COBDB2.LOADLIB(SELECT1),DISP=SHR              
//SYSPRINT DD  SYSOUT=*                                                 
//SYSUT1   DD  SPACE=(1024,(50,50)),UNIT=SYSDA                          
//SYSIN    DD  DUMMY                                                    
**************************** Bottom of Data ****************************

JOB Result - MAXCC

Precompile JOB MAXCC

JOB Result - Precompile Step

Precompile JOB Precompile Step

JOB Result - Precompile Step Final Report

Precompile JOB Precompile Step Result