Sample program SYCCSAL2

This program accepts all valid Dynamic SQL requests except SELECT commands. DELETE requests must have a WHERE clause, or they will be rejected. Upon successful completion, this program sends a confirmation message to the client; otherwise, it sends an error message.

      *@(#) syccsal2.cobol 1.1 3/17/98        */
        IDENTIFICATION DIVISION.
        PROGRAM-ID. SYCCSAL2.

      ****** SYCCSAL2 - LANGUAGE REQUEST APPLICATION - COBOL2 - CICS **
       *
       *  TRANID:        SYL2
       *  PROGRAM:       SYCCSAL2
       *  PLAN NAME:     SYL2PLAN
       *  FILES:         n/a
       *  TABLES:        adhoc
       *
       *  This program is executed via a client language request
       *  from sample dblib program 'SYL2', or by SYBASE's ISQL if
       *  installed.  The client program must login to a transaction
       *  group with SYL2 as the language handler.
       *                                                                         
       *  The purpose of the program is primarily to demonstrate Server
       *  Library calls, especially those which would be used in a
       *  server application designed to handle language requests.
       *
       *  Server Library calls:
       *    TDACCEPT      accept request from client
       *    TDFREE        free TDPROC structure
       *    TDINFLOG      return trace settings
       *    TDINFPGM      return program information
       *    TDINIT        establish environment
       *    TDRCVSQL      receive language text
       *    TDRESULT      describe next communication
       *    TDSETSPT      set specific tracing
       *    TDSNDDON      send results-completion to client
       *    TDSNDMSG      send message to client
       *    TDSQLLEN      get length of incoming text
       *    TDSTATUS      get status information
       *
       *
       *  The program accepts all valid SQL requests other than
       *  'SELECT'.  A 'DELETE' must have a WHERE clause, or it is
       *  rejected.
       *
       *  A confirmation message is sent to the client if all is
       *  well, otherwise an error message is sent.
       *
       * CHANGE ACTIVITY:
       *    4/90    - Created, MPM
       *    10/93   - Some restructuring, TC
       *
       *---------------------------------------------------------------*
 
        ENVIRONMENT DIVISION.
        DATA DIVISION.
       ******************************************************************
        WORKING-STORAGE SECTION.
       ******************************************************************
 
       *-----------------------------------------------------------------
       *    DB2 SQLCA
       *-----------------------------------------------------------------
            EXEC SQL INCLUDE SQLCA END-EXEC.
 
       *-----------------------------------------------------------------
       *    DB2 MINIMUM SQLDA FOR COBOL II
       *-----------------------------------------------------------------
        01  SQLDA.
            02  SQLDAID                 PIC X(8)       VALUE 'SQLDA'.
            02  SQLDABC                 PIC S9(8) COMP VALUE 60.
            02  SQLN                    PIC S9(4) COMP VALUE 1.
            02  SQLD                    PIC S9(4) COMP VALUE 0.
            02  SQLVAR.
                03  SQLTYPE             PIC S9(4) COMP.
                03  SQLLEN              PIC S9(4) COMP.
                03  SQLDATA             POINTER.
                03  SQLIND              POINTER.
                03  SQLNAME.
                    49  SQLNAMEL        PIC S9(4) COMP.
                    49  SQLNAMEC        PIC X(30).
 
       *-----------------------------------------------------------------
       *    SERVER LIBRARY COBOL COPY BOOK
       *-----------------------------------------------------------------
            COPY SYGWCOB.
 
       *-----------------------------------------------------------------
       *    WORK AREAS
       *-----------------------------------------------------------------
        01  GW-LIB-MISC-FIELDS.
            05  GWL-PROC                POINTER.
            05  GWL-INIT-HANDLE         POINTER.
            05  GWL-RC                  PIC S9(9) COMP.
            05  GWL-SQLLEN              PIC S9(9) COMP.
            05  GWL-STATUS-NR           PIC S9(9) COMP.
            05  GWL-STATUS-DONE         PIC S9(9) COMP.
            05  GWL-STATUS-COUNT        PIC S9(9) COMP.
            05  GWL-STATUS-COMM         PIC S9(9) COMP.
            05  GWL-STATUS-RETURN-CODE  PIC S9(9) COMP.
            05  GWL-STATUS-SUBCODE      PIC S9(9) COMP.
            05  GWL-INFPGM-TDS-VERSION  PIC S9(9) COMP.
            05  GWL-INFPGM-LONGVAR      PIC S9(9) COMP.
            05  GWL-INFPGM-ROW-LIMIT    PIC S9(9) COMP.
            05  GWL-INFPGM-REMOTE-TRACE PIC S9(9) COMP.
            05  GWL-INFPGM-CORRELATOR   PIC S9(9) COMP.
            05  GWL-INFPGM-DB2GW-OPTION PIC S9(9) COMP.
            05  GWL-INFPGM-DB2GW-PID    PIC X(8).
            05  GWL-INFPGM-TYPE-RPC     PIC S9(9) COMP.
            05  GWL-INFLOG-GLOBAL       PIC S9(9) COMP.
            05  GWL-INFLOG-API          PIC S9(9) COMP.
            05  GWL-INFLOG-TDS-HEADER   PIC S9(9) COMP.
            05  GWL-INFLOG-TDS-DATA     PIC S9(9) COMP.
            05  GWL-INFLOG-TRACE-ID     PIC S9(9) COMP.
            05  GWL-INFLOG-FILENAME     PIC X(8).
            05  GWL-INFLOG-TOTAL-RECS   PIC S9(9) COMP.
            05  GWL-SETSPT-TRACE-LEVEL  PIC S9(9) COMP VALUE  4.
            05  GWL-SETSPT-RPC-NAME     PIC X(4)       VALUE 'SYL2'.
            05  GWL-SETSPT-RPC-NAME-L   PIC S9(9) COMP VALUE  4.
 
        01  LANGUAGE-FIELDS.
            05  LANG-MAX-L              PIC S9(9) COMP.
            05  LANG-ACTUAL-L           PIC S9(9) COMP.
            05  LANG-TEXT-SS            PIC S9(4) COMP.
 
        01  LANG-BUFFER.
            49  LANG-BUFFER-LL          PIC S9(4) COMP.
            49  LANG-BUFFER-TEXT        PIC X(1024).
 
        01  PARSESQL-BUFFER             REDEFINES LANG-BUFFER.
            05  PARSESQL-TEXT.
                10  PARSESQL-TEXT-LL    PIC S9(4)  COMP.
                10  PARSESQL-TEXT-CHARS OCCURS 1024 TIMES
                                        PIC X.
            05  PARSESQL-TEXT-DUMMY-LVL PIC X.
 
        01  SNA-FIELDS.
            05  SNA-SUBC                PIC S9(9) COMP.
            05  SNA-CONNECTION-NAME     PIC X(8)  VALUE SPACES.
 
        01  PARSE-FIELDS.
            05  PARSE-PTR               PIC S9(4) COMP VALUE 0.
            05  PARSE-TOKEN             PIC X(18) VALUE SPACES.
            05  PARSE-FROM              PIC X(04).
            05  PARSE-TABLE             PIC X(46).
            05  PARSE-CORRELATION       PIC X(18) VALUE SPACES.
            05  PARSE-WHERE             PIC X(05) VALUE SPACES.
 
        01  WORK-FIELDS.
            05  WRK-DONE-STATUS         PIC S9(9) COMP.
 
        01  MESSAGE-FIELDS.
            05  MSG-TYPE                PIC S9(9) COMP.
            05  MSG-SEVERITY            PIC S9(9) COMP.
            05  MSG-SEVERITY-OK         PIC S9(9) COMP VALUE  9.
            05  MSG-SEVERITY-ERROR      PIC S9(9) COMP VALUE 11.
            05  MSG-NR                  PIC S9(9) COMP.
            05  MSG-NR-OK               PIC S9(9) COMP VALUE  1.
            05  MSG-NR-ERROR            PIC S9(9) COMP VALUE  2.
            05  MSG-RPC                 PIC X(4)       VALUE 'SYL2'.
            05  MSG-RPC-L               PIC S9(9) COMP.
            05  MSG-TEXT                PIC X(50).
            05  MSG-TEXT-L              PIC S9(9) COMP.
            05  MSG-SQL-ERROR.
                10  MSG-SQL-ERROR-T     PIC X(31)
                    VALUE 'Invalid sql request, sqlcode = '.
                10  MSG-SQL-ERROR-C     PIC -9(3) DISPLAY.
            05  MSG-SELECT              PIC X(24)
                VALUE 'SQL select not supported'.
            05  MSG-NOT-LANG            PIC X(35)
                VALUE 'SYL2 not begun via language request'.
            05  MSG-BAD-LEN             PIC X(31)
                VALUE 'Request has too many characters'.
            05  MSG-NO-WHERE            PIC X(26)
                VALUE 'Delete has no where clause'.
            05  MSG-OK                  PIC X(22)
                VALUE 'Execute was successful'.
            05  MSG-NOT-OK.
                10  FILLER              PIC X(26)
                    VALUE 'Execute failed, sqlcode = '.
                10  MSG-NOT-OK-C        PIC -9(3) DISPLAY.
                10  FILLER              PIC X(18)
                    VALUE ', ROLLBACK issued.'.
 
        01  CICS-FIELDS.
            05  CICS-RESPONSE           PIC S9(9) COMP.
 
        01  SWITCHES.
            05  TRACING-SET-SW          PIC S9(9) COMP VALUE  0.
                88  TRACING-RESET                      VALUE  0.
                88  TRACING-SET                        VALUE  1.
            05  SEND-DONE-SW            PIC X          VALUE 'Y'.
                88 SEND-DONE-ERROR                     VALUE 'N'.
                88 SEND-DONE-OK                        VALUE 'Y'.
 
       *-----------------------------------------------------------------
       *    DECLARE STATEMENT AND CURSOR
       *-----------------------------------------------------------------
            EXEC SQL DECLARE S1 STATEMENT END-EXEC.
            EXEC SQL DECLARE C1 CURSOR FOR S1 END-EXEC.
 
       ******************************************************************
        PROCEDURE DIVISION.
       ******************************************************************
 
       *    Reset db2 error handlers
 
            EXEC SQL WHENEVER SQLWARNING CONTINUE END-EXEC.
            EXEC SQL WHENEVER SQLERROR   CONTINUE END-EXEC.                      
            EXEC SQL WHENEVER NOT FOUND  CONTINUE END-EXEC.
 
       *    Establish gateway environment
 
            CALL 'TDINIT' USING DFHEIBLK, GWL-RC, GWL-INIT-HANDLE.
 
       *    Turn on local tracing if not on globally or locally
 
            CALL 'TDINFLOG' USING GWL-INIT-HANDLE, GWL-RC,
                                  GWL-INFLOG-GLOBAL,
                                  GWL-INFLOG-API,
                                  GWL-INFLOG-TDS-HEADER,
                                  GWL-INFLOG-TDS-DATA,
                                  GWL-INFLOG-TRACE-ID,
                                  GWL-INFLOG-FILENAME,
                                  GWL-INFLOG-TOTAL-RECS.
 
            IF  GWL-INFLOG-GLOBAL NOT = TDS-TRACE-ALL-RPCS
            AND GWL-INFLOG-GLOBAL NOT = TDS-TRACE-SPECIFIC-RPCS THEN
                MOVE 1 TO TRACING-SET-SW
                PERFORM LOCAL-TRACING
            END-IF.
 
       *    Accept client request
 
            CALL 'TDACCEPT' USING GWL-PROC, GWL-RC, GWL-INIT-HANDLE,
                                  SNA-CONNECTION-NAME,
                                  SNA-SUBC.
 
       *    Ensure kicked off via language request
       *    (this could be handled more reasonably by TDRESULT)
 
            CALL 'TDINFPGM' USING GWL-PROC, GWL-RC,
                                  GWL-INFPGM-TDS-VERSION,
                                  GWL-INFPGM-LONGVAR,
                                  GWL-INFPGM-ROW-LIMIT,
                                  GWL-INFPGM-REMOTE-TRACE,
                                  GWL-INFPGM-CORRELATOR,
                                  GWL-INFPGM-DB2GW-OPTION,
                                  GWL-INFPGM-DB2GW-PID,
                                  GWL-INFPGM-TYPE-RPC.
 
            IF GWL-INFPGM-TYPE-RPC NOT = TDS-START-SQL
                MOVE MSG-NOT-LANG           TO MSG-TEXT
                MOVE LENGTH OF MSG-NOT-LANG TO MSG-TEXT-L
                PERFORM SEND-ERROR-MESSAGE
                GO TO END-PROGRAM
            END-IF.
 
       *    Prepare for receive
 
            CALL 'TDRESULT' USING GWL-PROC, GWL-RC.
 
       *    Get lenth of language text, ensure not too big for us
       *    (this could be handled without TDSQLLEN by checking
       *    LANG-ACTUAL-LEN doesn't exceed LANG-MAX-L in TDRCVSQL call)
 
            CALL 'TDSQLLEN' USING GWL-PROC, GWL-SQLLEN.
            MOVE LENGTH OF LANG-BUFFER-TEXT TO LANG-MAX-L.
 
            IF GWL-SQLLEN > LANG-MAX-L THEN
                MOVE MSG-BAD-LEN           TO MSG-TEXT
                MOVE LENGTH OF MSG-BAD-LEN TO MSG-TEXT-L
                PERFORM SEND-ERROR-MESSAGE
                GO TO END-PROGRAM
            END-IF.
 
       *    Get language text
 
            CALL 'TDRCVSQL' USING GWL-PROC, GWL-RC,
                                  LANG-BUFFER-TEXT,
                                  LANG-MAX-L,
                                  LANG-ACTUAL-L.
 
            MOVE LANG-ACTUAL-L TO LANG-BUFFER-LL.
 
       *    Ensure line feeds, low-values, etc. translated to blanks
 
            PERFORM VARYING LANG-TEXT-SS FROM 1 BY 1
                    UNTIL LANG-TEXT-SS > PARSESQL-TEXT-LL
 
                IF PARSESQL-TEXT-CHARS(LANG-TEXT-SS) < SPACE THEN
                    MOVE SPACE TO PARSESQL-TEXT-CHARS(LANG-TEXT-SS)
                END-IF
 
       *        Save position of first non-blank
 
                IF PARSE-PTR = 0 AND
                    PARSESQL-TEXT-CHARS(LANG-TEXT-SS) > SPACE THEN
                    MOVE LANG-TEXT-SS TO PARSE-PTR
                END-IF
 
            END-PERFORM.
 
       *    Let DB2 edit and tell us if SELECT
 
            EXEC SQL PREPARE S1 INTO SQLDA FROM :LANG-BUFFER END-EXEC.
 
            IF SQLD NOT = 0 THEN
                MOVE MSG-SELECT           TO MSG-TEXT
                MOVE LENGTH OF MSG-SELECT TO MSG-TEXT-L
                PERFORM SEND-ERROR-MESSAGE
                GO TO END-PROGRAM
            END-IF.
 
            IF SQLCODE < 0 THEN
                MOVE SQLCODE                 TO MSG-SQL-ERROR-C
                MOVE MSG-SQL-ERROR           TO MSG-TEXT
                MOVE LENGTH OF MSG-SQL-ERROR TO MSG-TEXT-L
                PERFORM SEND-ERROR-MESSAGE
                GO TO END-PROGRAM
            END-IF.
 
       *    Parse and handle special case of DELETE without WHERE clause
 
            UNSTRING LANG-BUFFER-TEXT DELIMITED BY ALL ' '
                INTO PARSE-TOKEN
                     PARSE-FROM
                     PARSE-TABLE
                     PARSE-CORRELATION
                     PARSE-WHERE
                POINTER PARSE-PTR.
 
            PERFORM XLATE-TOKEN-UPPERCASE.
 
            IF PARSE-TOKEN = 'DELETE' THEN
                MOVE PARSE-CORRELATION TO PARSE-TOKEN
                PERFORM XLATE-TOKEN-UPPERCASE
                MOVE PARSE-TOKEN TO PARSE-CORRELATION
 
                MOVE PARSE-WHERE TO PARSE-TOKEN
                PERFORM XLATE-TOKEN-UPPERCASE
 
                IF PARSE-CORRELATION NOT = 'WHERE ' AND
                   PARSE-TOKEN       NOT = 'WHERE ' THEN
                    MOVE MSG-NO-WHERE           TO MSG-TEXT
                    MOVE LENGTH OF MSG-NO-WHERE TO MSG-TEXT-L
                    PERFORM SEND-ERROR-MESSAGE
                    GO TO END-PROGRAM
                END-IF
            END-IF.
 
       *    Execute the SQL statement
 
            EXEC SQL EXECUTE S1 END-EXEC.
 
            IF SQLCODE < 0 THEN
                PERFORM CICS-ROLLBACK
                MOVE SQLCODE              TO MSG-NOT-OK-C
                MOVE MSG-NOT-OK           TO MSG-TEXT
                MOVE LENGTH OF MSG-NOT-OK TO MSG-TEXT-L
                PERFORM SEND-ERROR-MESSAGE
                GO TO END-PROGRAM
            END-IF.
 
            MOVE MSG-OK           TO MSG-TEXT.
            MOVE LENGTH OF MSG-OK TO MSG-TEXT-L.
            PERFORM SEND-CONFIRM-MESSAGE.
            GO TO END-PROGRAM.
 
       *-----------------------------------------------------------------
        XLATE-TOKEN-UPPERCASE.
       *-----------------------------------------------------------------
 
       *    All we care about is DELETE and WHERE
 
            INSPECT PARSE-TOKEN REPLACING ALL 'd' BY 'D'
                                              'e' BY 'E'
                                              'h' BY 'H'
                                              'l' BY 'L'
                                              'r' BY 'R'
                                              't' BY 'T'
                                              'w' BY 'W'.
 
       *-----------------------------------------------------------------
        SEND-CONFIRM-MESSAGE.
       *-----------------------------------------------------------------
            MOVE MSG-SEVERITY-OK TO MSG-SEVERITY.
            MOVE MSG-NR-OK       TO MSG-NR.
            MOVE TDS-INFO-MSG    TO MSG-TYPE.
            PERFORM SEND-MESSAGE.
 
       *-----------------------------------------------------------------
        SEND-ERROR-MESSAGE.
       *-----------------------------------------------------------------
            MOVE 'N'                TO SEND-DONE-SW.
            MOVE MSG-SEVERITY-ERROR TO MSG-SEVERITY.                             
            MOVE MSG-NR-ERROR       TO MSG-NR.
            MOVE TDS-ERROR-MSG      TO MSG-TYPE.
            PERFORM SEND-MESSAGE.
 
       *-----------------------------------------------------------------
        SEND-MESSAGE.
       *-----------------------------------------------------------------
            MOVE LENGTH OF MSG-RPC TO MSG-RPC-L.
 
       *    -------------------------------------------------------------
       *    ensure we're in right state to send a message
       *    -------------------------------------------------------------
            CALL 'TDSTATUS' USING GWL-PROC, GWL-RC,
                                  GWL-STATUS-NR,
                                  GWL-STATUS-DONE,
                                  GWL-STATUS-COUNT,
                                  GWL-STATUS-COMM,
                                  GWL-STATUS-RETURN-CODE,
                                  GWL-STATUS-SUBCODE.
 
            IF (GWL-RC = TDS-OK AND
                GWL-STATUS-COMM = TDS-RECEIVE) THEN
 
                CALL 'TDSNDMSG' USING GWL-PROC, GWL-RC,
                                      MSG-TYPE, MSG-NR,
                                      MSG-SEVERITY,
                                      TDS-ZERO,
                                      TDS-ZERO,
                                      MSG-RPC, MSG-RPC-L,
                                      MSG-TEXT, MSG-TEXT-L
            END-IF.
 
       *-----------------------------------------------------------------
        LOCAL-TRACING.
       *-----------------------------------------------------------------
            CALL 'TDSETSPT' USING GWL-INIT-HANDLE, GWL-RC,
                                  TRACING-SET-SW,
                                  GWL-SETSPT-TRACE-LEVEL,
                                  GWL-SETSPT-RPC-NAME,                           
                                  GWL-SETSPT-RPC-NAME-L.
 
       *-----------------------------------------------------------------
        CICS-ROLLBACK.
       *-----------------------------------------------------------------
            EXEC CICS SYNCPOINT
                      ROLLBACK
                      RESP(CICS-RESPONSE)
            END-EXEC.
 
       *-----------------------------------------------------------------
        END-PROGRAM.
       *-----------------------------------------------------------------
            IF TRACING-SET
                MOVE 0 TO TRACING-SET-SW
                PERFORM LOCAL-TRACING
            END-IF.
 
            IF SEND-DONE-OK
                MOVE TDS-DONE-COUNT TO WRK-DONE-STATUS
            ELSE
                MOVE TDS-DONE-ERROR TO WRK-DONE-STATUS
                MOVE ZERO           TO SQLERRD(3)
            END-IF.
 
            CALL 'TDSNDDON' USING GWL-PROC, GWL-RC,
                                  WRK-DONE-STATUS,
                                  SQLERRD(3),
                                  TDS-ZERO,
                                  TDS-ENDRPC.
 
            CALL 'TDFREE' USING GWL-PROC, GWL-RC.
            EXEC CICS RETURN END-EXEC.