DB2 Server for VSE & VM: Application Programming


Using Reentrant Assembler Language Programs

A reentrant program has the characteristic of dynamic allocation of space for data and save areas. This reentrant characteristic can be used in assembler programs. In this case, the data and save areas are allocated in a calling (driver) program and passed to a called (reentrant) program as parameters. Storage for these areas need not be allocated in the called program.

A convenient use for reentrancy is the use of an SQLDA structure declared as a DSECT in the calling program. This, in combination with an INCLUDE SQLDA statement in the called program, permits the passing back of values, extracted by a SELECT/FETCH in the called program, in a clean and simple manner. A DESCRIBE statement can be used by the called program to fill the SQLDA structure, or it can be hand-filled in the driver program. Other SQL statements (for example, INSERT, DELETE, UPDATE) utilize a single data location to communicate just an SQLCODE.

If statement results other than the SQLCODE are desired, an SQLCA structure can be allocated in the driver program. However, unlike the SQLDA structure allocation by a DSECT, the fields of the SQLCA structure must be hard-coded into the driver, because the driver will not be preprocessed. An INCLUDE SQLCA statement, within a DSECT, is then required in the called program. SQLCA communication between the two programs can be achieved by passing the address of the first field of the SQLCA structure to the reentrant program.

The "Locda DSECT" structure is hard-coded in the Driver Program, instead of being defined by an "EXEC SQL INCLUDE SQLDA", so that there is no need to preprocess the Driver Program. This example assumes there is only a single host variable returned by the FETCH. For production application programming, it is recommended that macros be created for defining the SQLCA and SQLDA structures (with optional DSECT statement) when used in programs that will not be preprocessed.

The following are skeleton programs illustrating the use of the SQLDA structure, and a single data location for communicating SQLCODEs. The reentrant example illustrates only a FETCH statement. If more than one "action" statement (INSERT, DELETE, and so on) is used, then various flags are needed to direct access to the individual operations. The required modifications to include an SQLCA structure follow these skeletons.

Figure 106. Driver Program

Driver   CSECT ,              Driver Program
* Standard Linkage Conventions ...
         STM   R14,R12,12(R13)     Save callers registers
         :
Qstring  DC   H'57',CL57'SELECT DESCRIPTION FROM INVENTORY WHERE QONHA $
               ND < 100'      SQL Statement to be executed
         :
         LA    R13,Save1      Subroutine Register Savearea Address
* Forward and backward chain saveareas together
         :
         LA    R4,1           '1' indicates 1st call to subroutine
         ST    R4,Loccode     SQLCODE returned from subroutine
*                             (Also used as 1st call switch)
         :
* Create SQLDA structure to pass to subroutine:
* (OR Subroutine could fill in by using DESCRIBE)
         LA    R4,LSQLDA      Point R4 at SQLDA area
         USING Locda,R4       reference SQLDA fields
         :
         LA    R7,Outarea+1   Address where DESCRIPTION stored
         ST    R7,Locdata
         LA    R7,Indaddr     Address where Indicator Value stored
         ST    R7,Locind
* NOTE: Setting of other SQLDA fields is not shown, but may be required
         :
*
* Loop to call reentrant subroutine (Loop needed for Cursor operation)
LOOP     EQU   *
*
* Blank Output area for next FETCH result:
         :
         LA    R1,Parmlist    Parms passed to subroutine through R1
         L     R15,=V(Reentran)    Load Subroutine Entry Point address
         BALR  R14,R15        Call Reentrant Subroutine
         CLC   Loccode,F0     Any error from subroutine ?
         BE    FetchOK        No, continue as normal
         CLC   Loccode,F100   Cursor EOF occurred ???
         BE    Final          Yes, all done.
         B     Errchk         No, some kind of error, go handle.
*
FetchOK  EQU   *
* Test indicator values for NULL, etc, and handle as appropriate:
         :
*
* Output result from a Fetch:   (Data conversion may be necessary)
         :
*
* Branch back to Loop for another Fetch
         B     LOOP
         :
Errchk   EQU   *
* Handle errors returned by subroutine.
         :
Final    EQU   *
* Program complete, restore registers and return to caller
         :
         BR    R14            Return to caller
         :
* Declare Section
         :
         :
F0       DC    F'0'           'NO ERRORS'  retcode from subroutine
F100     DC    F'100'         'CURSOR EOF' retcode from subroutine
         :
SaveRA   DS    18F            register savearea for use by Resource
*                             ... Adapter when called by subroutine
Save1    DS    18F            subroutine register savearea
Loccode  DS    F              SQLCODE variable passed to subroutine
*                             (return code from subroutine)
         :
Parmlist DS    0D             Subroutine Parameter List:
         DC    A(Qstring)     SQL Statement to execute
         DC    A(LSQLDA)      Local SQLDA area
         DC    A(Loccode)     Return Code from subroutine
         DC    A(Hostvar)     Host Variable Workarea
         DC    A(SaveRA)      Resource Adapter register savearea
         :
Indaddr  DS    F              Indicator area
Outarea  DS    CL80           Fetch value return area
         :
LSQLDA   DS    CL500          Local SQLDA area
Hostvar  DS    CL500          Subroutine Host Variable workarea
         :
Locda    DSECT ,              Describes SQLDA fields
Locdaid  DS    CL8
Locdabc  DS    F
Locn     DS    H
Locd     DS    H
Locvar   DS    0F              assumes one one Host Variable used
Loctype  DS    H
Loclen   DS    0H
Locprcsn DS    X
Locscale DS    X
Locdata  DS    A
Locind   DS    A
Locname  DS    H,CL30         ...end of Local SQLDA area
         :
         :
         END Driver           ...end of Driver Program

Figure 107. Reentrant Program

Reentran CSECT ,              Reentrant Subroutine
* Standard Linkage Conventions. Register Savearea address in R13.
         STM   R14,R12,12(R13)     Save callers registers
         :
* Get Parameter addresses
         L     R3,0(0,R1)     Point to Qstring
         L     R4,4(0,R1)     Point to SQLDA area
         USING SQLDA,R4       Reference SQLDA fields
         L     R5,8(0,R1)     Point to Loccode (SQLCODE) return code
         USING LSQLCODE,R5    Reference Passed SQLCODE variable
         L     R6,12(0,R1)    Point to Hostvar workarea
         USING Hostvar,R6     Reference Hostvar workarea
         LR    R7,R13         R7 points to callers savearea
         L     R13,16(0,R1)   Point R13 at "our" passed savearea ...
*                             ... for use by Resource Adapter calls
* Forward and backward chain saveareas together
         ST    R13,8(0,R7)    Caller savearea points to "our" savearea
         ST    R7,4(0,R13)    "our" savearea points to caller savearea
         :
* Check if this is first call to subroutine:
         CLC   F0,0(R5)       If NOT zero, it is first call
         BE    Next           Is zero - NOT first call
    EXEC SQL CONNECT ...
         :
         LH    R1,0(R3)       Get length of Qstring
         LA    R1,1(R1,0)     Length minus 1 for EXecute ...
*                             ... plus 2 for length Halfword ...
*                             ... equals length + 1.
         EX    R1,MOVQSTR     move length & Qstring to Hostvar area
    EXEC SQL PREPARE S1 FROM :QSTRING
         CLC   SQLCODE,F0     Any errors ?
         BNE   Exit           Yes, return it to caller
         :
* Fill in passed SQLDA structure (possibly with DESCRIBE),
* if not done in Driver program.
         :
    EXEC SQL DECLARE C1 CURSOR FOR S1
         :
    EXEC SQL OPEN C1
         :
Next     EQU   *
    EXEC SQL FETCH C1 USING DESCRIPTOR SQLDA
         CLC   SQLCODE,F100   Cursor EOF reached ??
         BNE   Exit           No, return to caller (even if error)
         :
*
* All Fetched, Close Cursor before returning
Done     EQU   *
    EXEC SQL CLOSE C1
         CLC   SQLCODE,F0     Any error ?
         BNE   Exit           Yes, return error to caller
*
* Return 'CURSOR EOF' return code to caller
         MVC   0(4,R5),F100   R5 points to Loccode
         :
Exit     EQU   *              Return to caller
         :
* Restore registers and return to caller
* Our return code is in Loccode
         L     R13,4(0,R13)        Load callers savearea address
         LM    R14,R12,12(R13)     Restore callers registers
         BR    R14                 Return to caller
         :
* Declare section
MOVQSTR  MVC   QSTRING(1),0(R3)    EXecuted during 1st call
F0       DC    F'0'           'NO ERRORS'  retcode from subroutine
F100     DC    F'100'         'CURSOR EOF' retcode from subroutine
         :
* Include the SQLDA DSECT
    EXEC SQL INCLUDE SQLDA
         :
Hostvar  DSECT ,              Passed Host Variable Workarea
QSTRING  DS   CL500
         :
LSQLCODE DSECT ,              Passed SQLCODE variable
SQLCODE  DS   F
         :
         END   Reentran       ...end of Reentrant Subroutine

To include full SQLCA communications between the Driver Program and the Reentrant program, you must modify both programs.

Figure 108. SQLCA Changes for Driver/Reentrant Programs

In the Driver program, replace the "Loccode" variable definition with an
"SQLCA" structure definition and update the 3rd address constant in the
"Parmlist", as follows:

         :
Save1    DS    18F            subroutine register savearea
Locca    DS    0D             SQLCA structure passed to subroutine
Loccaid  DS    CL8
Loccabc  DS    F
Loccode  DS    F              SQLCODE
Locerrm  DS    H,CL70
Locerrp  DS    CL8
Locerrd  DS    6F
Locwarn  DS    0C
Locwarn0 DS    CL1
Locwarn1 DS    CL1
Locwarn2 DS    CL1
Locwarn3 DS    CL1
Locwarn4 DS    CL1
Locwarn5 DS    CL1
Locwarn6 DS    CL1
Locwarn7 DS    CL1
Locwarn8 DS    CL1
Locwarn9 DS    CL1
LocwarnA DS    CL1
Locstate DS    CL5            ... end of local SQLCA structure
         :
Parmlist DS    0D             Subroutine Parameter List:
         DC    A(Qstring)     SQL Statement to execute
         DC    A(LSQLDA)      Local SQLDA area
         DC    A(Locca)       SQLCA returned from subroutine  <----
         DC    A(Hostvar)     Host Variable Workarea
         DC    A(SaveRA)      Resource Adapter register savearea
         :


In the Reentrant program, change from just referencing the "SQLCODE"
variable, through the "LSQLCODE DSECT", to referencing the full "SQLCA"
structure, through the "PASSEDCA DSECT", as follows:

         :
         L     R5,8(0,R1)     Point to Locca (SQLCA) return codes
         USING PASSEDCA,R5    Reference Passed SQLCA structure
         :
         :
PASSEDCA DSECT ,              Passed SQLCA structure
    EXEC SQL INCLUDE SQLCA         include SQLCA field definitions
         :


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]