IDENTIFICATION DIVISION.
       PROGRAM-ID. EXTXN01.
      *
      * InstantSQL Transaction Example 01.
      *
      *This example connects to the data
source named
      *Bank. 
It then executes a transfer transaction
      *from a checking account to a savings
account.
      *The transaction is committed only if it
is
      *successful, otherwise it is rolled
back.
      *
 
       DATA DIVISION.
       WORKING-STORAGE SECTION.
 
       COPY "lisqlall.cpy".
 
 
       01 WS-Handles.
          05 WS-QryHandleReadCkg   USAGE ISqlHandle.
          05 WS-QryHandleUpdtCkg   USAGE ISqlHandle.
          05 WS-QryHandleUpdtSvg   USAGE ISqlHandle.
 
       01 WS-Account-Data.
          05 WS-CkgAccountNo   PIC 9(09). 
*> checking acct number
          05 WS-SvgAccountNo   PIC 9(09). 
*> savings acct number
          05 WS-CkgBalance     PIC S9(16)V9(2). *> checking balance
          05 WS-SvgBalance     PIC S9(16)V9(2). *> savings balance
 
          05 WS-TrfAmount      PIC S9(16)V9(2). *> transfer amount
          05 WS-TxnFlag        PIC X.
             88 WS-TxnIsActive VALUE
"Y" FALSE "N".
          05 WS-Timeout        PIC S9(5) BINARY VALUE 20.
 
       01 PBuf                 PIC X(80) VALUE SPACES.
       01 P1                   PIC S9(5) BINARY VALUE 0.
       01 I                    PIC S9(5) BINARY VALUE 0.
 
       78 ErrMsgContSize       VALUE 50.
 
       PROCEDURE DIVISION.
       A.
 
 
      *Initialize.
           SET WS-TxnIsActive TO FALSE.
 
      *Connect to data source named Bank.
           SQL CONNECT DATASOURCE sql-ConnectionHandle
               "Bank"
               "MyName"
               "MyPassword".
           IF NOT sql-OK
             DISPLAY "<Error
connecting to Bank data source.>"
             PERFORM DescAndDisplaySqlError
             STOP RUN
           END-IF.
 
      *Prepare query for verifying Checking
balance larger than
 
      *transfer amount.
           SQL PREPARE QUERY
WS-QryHandleReadCkg
               sql-ConnectionHandle
               "SELECT Balance FROM Checking
WHERE AccountNo = ?"
               sql-Concur-Lock.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL BIND COLUMN WS-QryHandleReadCkg
               1 WS-CkgBalance OMITTED.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL BIND PARAMETER
WS-QryHandleReadCkg
 
               1 sql-Integer sql-Param-Input
                    WS-CkgAccountNo OMITTED.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
 
      *Prepare queries for updating Checking
and Savings balances.
           SQL PREPARE QUERY
WS-QryHandleUpdtCkg
               sql-ConnectionHandle
               "UPDATE Checking SET
Balance = ? WHERE AccountNo = ?".
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL BIND PARAMETER
WS-QryHandleUpdtCkg
 
               1 sql-Decimal sql-Param-Input
WS-CkgBalance OMITTED
               2 sql-Integer sql-Param-Input
WS-CkgAccountNo OMITTED.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
 
           SQL PREPARE QUERY
WS-QryHandleUpdtSvg
               sql-ConnectionHandle
               "UPDATE Savings SET
Balance = Balance + ?
      -       
"WHERE AccountNo = ?".
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL BIND PARAMETER
WS-QryHandleUpdtSvg
 
               1 sql-Decimal sql-Param-Input
WS-TrfAmount OMITTED
               2 sql-Integer sql-Param-Input
WS-SvgAccountNo OMITTED.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
 
      *Get account numbers and transfer amount.
           MOVE 001346759 TO WS-CkgAccountNo.
           MOVE 002478291 TO WS-SvgAccountNo.
           MOVE 1000.00 TO WS-TrfAmount.
 
      *Start transaction for transfer from
checking to savings.
           SQL START TRANSACTION
sql-ConnectionHandle
 
               sql-TXN-Repeatable-Read.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SET WS-TxnIsActive TO TRUE.
 
      *Read checking account balance.
           SQL START QUERY WS-QryHandleReadCkg
WS-Timeout.
           IF NOT sql-OK PERFORM TxnSqlError
END-IF.
           SQL FETCH ROW WS-QryHandleReadCkg.
           IF NOT sql-OK PERFORM TxnSqlError
END-IF.
 
      *Verify transfer does not exceed
checking balance.
           IF WS-TrfAmount > WS-CkgBalance
 
             DISPLAY "Transaction failed:
insufficient funds."
             PERFORM TxnCobolError
           ELSE
             *> Do transfer.
             SUBTRACT WS-TrfAmount FROM
WS-CkgBalance
             SQL START QUERY WS-QryHandleUpdtCkg
WS-Timeout
             IF NOT sql-OK PERFORM TxnSqlError
END-IF
             SQL START QUERY
WS-QryHandleUpdtSvg WS-Timeout
             IF NOT sql-OK PERFORM TxnSqlError
END-IF
             IF WS-TxnIsActive
               SQL COMMIT TRANSACTION
sql-ConnectionHandle
 
               SET WS-TxnIsActive TO FALSE
               IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF
               DISPLAY "Transfer
completed."
             END-IF
           END-IF.
 
      *End queries
           SQL END QUERY WS-QryHandleUpdtSvg.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL END QUERY WS-QryHandleUpdtCkg.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
           SQL END QUERY WS-QryHandleReadCkg.
 
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
 
      *Disconnect from Bank data source.
           SQL DISCONNECT DATASOURCE
sql-ConnectionHandle.
           IF NOT sql-OK PERFORM
DescAndDisplaySqlError END-IF.
 
      *Terminate InstantSQL and application
           SQL SHUTDOWN.
           STOP RUN.
 
       TxnSqlError.
           DISPLAY "Transaction failed:
SQL error or account busy."
           PERFORM DescAndDisplaySqlError.
           PERFORM TxnCobolError.
 
 
       TxnCobolError.
           IF WS-TxnIsActive PERFORM RollBackTxn END-IF.
 
       RollBackTxn.
           DISPLAY "Rolling back
transaction.".
           SQL ROLLBACK TRANSACTION
sql-ConnectionHandle.
           SET WS-TxnIsActive TO FALSE.
           IF NOT sql-OK PERFORM DescAndDisplaySqlError
END-IF.
 
       DescAndDisplaySqlError.
            PERFORM WITH TEST AFTER UNTIL
sql-EndOfData
              SQL DESCRIBE ERROR
sql-Error-Description
              IF NOT sql-OK
 
                IF sql-EndOfData
                  DISPLAY "--->End of
error list."
                ELSE
                  DISPLAY "Error
describing error:  " sql-Return
CONVERT
              ELSE
                PERFORM DisplayErrorDesc
              END-IF
            END-PERFORM.
            STOP "*** Transfer error
occurred. ***".
 
       DisplayErrorDesc.
 
           STRING "   Error type      = " sql-ErrType
               DELIMITED SIZE INTO PBuf
POINTER P1.
 
           EVALUATE TRUE
           WHEN sql-IsOdbcError
             STRING "   (ODBC error)"
                 DELIMITED SIZE INTO PBuf
POINTER P1
           WHEN sql-IsInternalError
             STRING "   (internal error)"
                 DELIMITED SIZE INTO PBuf
POINTER P1
           WHEN OTHER
             STRING "   (unknown error type)"
                 DELIMITED SIZE INTO PBuf POINTER P1
           END-EVALUATE.
           PERFORM OutputPBuf.
 
           STRING "   Error statement = " sql-ErrStatement
 
               DELIMITED SIZE INTO PBuf
POINTER P1.
           PERFORM OutputPBuf.
 
           STRING "   Error
SQL state = " sql-ErrSqlState
               DELIMITED SIZE INTO PBuf
POINTER P1.
           PERFORM OutputPBuf.
 
           STRING "   Error number    = " sql-ErrNo(3:)
               DELIMITED SIZE INTO PBuf
POINTER P1.
           PERFORM OutputPBuf.
 
           STRING "   Error msg len   = " sql-ErrMsgLength(2:)
               DELIMITED SIZE INTO PBuf
POINTER P1.
 
           PERFORM OutputPBuf.
 
           STRING "   Error message   = """
               DELIMITED SIZE INTO PBuf
POINTER P1.
           IF sql-ErrMsgLength > 0
             IF sql-ErrMsgLength <=
ErrMsgContSize
               STRING sql-ErrMsg(1:
sql-ErrMsgLength)
                   DELIMITED SIZE INTO PBuf
POINTER P1
             ELSE
               STRING sql-ErrMsg(1: ErrMsgContSize)
                   DELIMITED SIZE INTO PBuf
POINTER P1
             END-IF
 
             SUBTRACT ErrMsgContSize FROM
sql-ErrMsgLength
             ADD ErrMsgContSize 1 GIVING I
             PERFORM VARYING I FROM I BY
ErrMsgContSize
                     UNTIL sql-ErrMsgLength
<= 0
               PERFORM OutputPBuf
               STRING "                        "
                   DELIMITED SIZE INTO PBuf
POINTER P1
               IF sql-ErrMsgLength <=
ErrMsgContSize
                 STRING sql-ErrMsg(I:
sql-ErrMsgLength)
                     DELIMITED SIZE INTO PBuf
POINTER P1
 
               ELSE
                 STRING sql-ErrMsg(I:
ErrMsgContSize)
                     DELIMITED SIZE INTO PBuf
POINTER P1
               END-IF
               SUBTRACT ErrMsgContSize FROM
sql-ErrMsgLength
             END-PERFORM
           END-IF.
           STRING """"
DELIMITED SIZE INTO PBuf POINTER P1
           PERFORM OutputPBuf.
 
       OutputPBuf.
           DISPLAY PBuf.
           MOVE SPACES TO PBuf.
           MOVE 1 TO P1.
 
       END PROGRAM EXTXN01.