midrange.com code scratchpad
Name:
Dennis Lovelady
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
05/25/2010 02:27:14 pm
IP:
Logged
Description:
Show result of SQL expression evaluation on the message line
Code:
  1.        // Evaluate an SQL expression; return the result as a message
  2.  
  3.        // Copyright (C) Dennis Lovelady, 2010
  4.        // Released to the public domain 2010-May-25
  5.  
  6.  
  7.        // This is a quick and dirty program to simply accept an expression
  8.        // to be evaluated by SQL, and return the result as a message to
  9.        // the calling program.   It's more or less a proof of concept
  10.        // to allow quick access to the result of some SQL question, or
  11.        // to play what-if games with SQL functions.
  12.  
  13.        // Due to the nature of the very long varying-length expression
  14.        // parameter, this program is intended to be used as a CPP.  The
  15.        // command defition should look like this:
  16.        //    CMD        PROMPT('Evaluate SQL expression')
  17.        //    PARM       KWD(RSLTTYPE) TYPE(*NAME) RSTD(*YES) +
  18.        //                 DFT(*DEC) SPCVAL((*DEC DECIMAL) (*STRING +
  19.        //                 STRING) (*FLOAT FLOAT) (*INT INTEGER)) +
  20.        //                 EXPR(*YES) PROMPT('Type of result')
  21.        //    PARM       KWD(EXPR) TYPE(*CHAR) LEN(16384) MIN(1) +
  22.        //                 EXPR(*YES) VARY(*YES *INT2) +
  23.        //                 PROMPT('SQL expression')
  24.  
  25.      H OPTION(*NOSHOWCPY:*NOEXPDDS:*NODEBUGIO:*SRCSTMT)
  26.      H DATFMT(*ISO) TIMFMT(*ISO) DFTACTGRP(*NO)
  27.      H CVTOPT(*VARCHAR:*NODATETIME)
  28.      H THREAD(*SERIALIZE)
  29.      
  30.      D sqlEval         PR                  ExtPgm('SQLEVAL')
  31.      D  resultType                   10    Const
  32.      D  parmExpr                  16384    Const Varying
  33.  
  34.  
  35.      D sqlEval         PI
  36.      D  resultType                   10    Const
  37.      D  parmExpr                  16384    Const Varying
  38.  
  39.  
  40.      D CheckSQL        PR              N
  41.      D  EOF_IS_OK                      N   Value Options(*NoPass)
  42.      D  parmWarnOnly                   N   Value Options(*NoPass)
  43.      D  parmLocation                 32    Value Varying
  44.      D                                     Options(*NoPass)
  45.      D  parmStmt                  16384    Varying Options(*NoPass)
  46.      D                                     Value
  47.  
  48.  
  49.      D SendEscape      PR                  ExtProc('sendEscape')
  50.      D   MSGID                             Const Like(QUSEC.messageID)
  51.      D   MSGDTA                            Const Like(QUSEC.messageData)
  52.      D   StackCount                   5I 0 Value Options(*NoPass)
  53.  
  54.  
  55.  
  56.      D sndPgmMsg       PR             4    ExtProc('sndPgmMsg')
  57.      D  parmMsgID                     7    Value
  58.      D  parmMsg                    4096    Value Options(*NoPass) Varying
  59.      D  parmMsgType                  10    Value Options(*NoPass)
  60.      D  parmMsgFile                  20    Value Options(*NoPass)
  61.      D  parmToPgmQ                   10    Value Options(*NoPass)
  62.      D  toPgmqCounter                10I 0 Value Options(*NoPass)
  63.  
  64.  
  65.      D SQL_EOF         C                   100
  66.      D SQL_EOF_IS_OK   C                   *On
  67.      D SQL_EOF_NOT_OK  C                   *Off
  68.      D SQL_WARN_ONLY   C                   *On
  69.      D SQL_ABORT       C                   *Off
  70.  
  71.  
  72.      D QUSEC           DS                  Inz Qualified
  73.      D  QUSBPRV                      10I 0 Inz(%Size(QUSEC))
  74.      D  QUSBAVL                      10I 0
  75.      D  QUSEI                         7
  76.      D                                1
  77.      D  QUSED01                    4096
  78.      D  bytesProvided                10I 0 Overlay(QUSEC: 1)
  79.      D  bytesAvailable...
  80.      D                               10I 0 Overlay(QUSEC: 5)
  81.      D  messageID                     7    Overlay(QUSEC: 9)
  82.      D  messageData                4096    Overlay(QUSEC: 17)
  83.  
  84.  
  85.  
  86.      D floatResult     S              8F
  87.      D intResult       S             10I 0
  88.      D decResult       S             31P 9
  89.      D stringResult    S          16384    Varying
  90.      D expression      S                   Like(parmExpr)
  91.  
  92.       /Free
  93.  
  94.        expression = 'Values(' + parmExpr + ') INTO ?' ;
  95.        Exec SQL Prepare dynamic from :expression ;
  96.        Select ;
  97.           When resultType = 'FLOAT' ;
  98.              Exec SQL Execute dynamic Using :floatResult ;
  99.              checkSQL(SQL_EOF_IS_OK: SQL_ABORT
  100.                     : 'Evaluating FLOAT expression'
  101.                     : expression
  102.                      ) ;
  103.              stringResult = %Char(floatResult) ;
  104.           When resultType = 'INTEGER' ;
  105.              Exec SQL Execute dynamic Using :intResult ;
  106.              checkSQL(SQL_EOF_IS_OK: SQL_ABORT
  107.                     : 'Evaluating INTEGER expression'
  108.                     : expression
  109.                      ) ;
  110.              stringResult = %Char(intResult) ;
  111.           When resultType = 'DECIMAL' ;
  112.              Exec SQL Execute dynamic Using :decResult ;
  113.              checkSQL(SQL_EOF_IS_OK: SQL_ABORT
  114.                     : 'Evaluating DECIMAL expression'
  115.                     : expression
  116.                      ) ;
  117.              stringResult = %Char(decResult) ;
  118.           When resultType = 'STRING' ;
  119.              Exec SQL Execute dynamic Using :stringResult ;
  120.              checkSQL(SQL_EOF_IS_OK: SQL_ABORT
  121.                     : 'Evaluating STRING expression'
  122.                     : expression
  123.                      ) ;
  124.           Other ;
  125.              sendEscape('CPF9898': 'Unknown output format') ;
  126.        EndSL ;
  127.        sndPgmMsg('CPI8859'
  128.                : 'Result is ' + stringResult
  129.                : '*INFO': *Blanks: '*CTLBDY': 1
  130.                 ) ;
  131.        *INLR = *On ;
  132.        Return ;
  133.  
  134.       /End-free
  135.  
  136.  
  137.      P CheckSQL        B
  138.       *********************************************************************
  139.       * Determine the Success/Failure of an SQL operation by checking     *
  140.       * SQLCODE and SQLSTATE.                                             *
  141.       * ---                                                               *
  142.       * Return *ON for success; *OFF for failure                          *
  143.       * ---                                                               *
  144.       * Send a message to the program message queue if a failure occurs.  *
  145.       *********************************************************************
  146.      D CheckSQL        PI              N
  147.      D  EOF_IS_OK                      N   Value Options(*NoPass)
  148.      D  parmWarnOnly                   N   Value Options(*NoPass)
  149.      D  parmLocation                 32    Value Varying
  150.      D                                     Options(*NoPass)
  151.      D  parmStmt                  16384    Varying Value
  152.      D                                     Options(*NoPass)
  153.  
  154.      D workLogStmt     S                   like(parmStmt)
  155.      D workLogStm2     S                   like(parmStmt)
  156.      D WarningOnly     S               N   Inz(SQL_ABORT)
  157.      D StmtLocation    S             32    Varying
  158.      D                                     Inz('Unspecified location')
  159.      D SQLerrID        S              7
  160.      D SuccessFlag     S               N
  161.      D IgnoreEOF       S               N   Inz(*On)
  162.  
  163.       /Free
  164.  
  165.        If %Parms > 0 ;
  166.           IgnoreEOF = EOF_IS_OK ;
  167.           If %Parms > 1 ;
  168.              WarningOnly = parmWarnOnly ;
  169.              If %Parms > 2 ;
  170.                 StmtLocation = parmLocation ;
  171.              EndIF ;
  172.           EndIF ;
  173.        EndIF ;
  174.        SQLErrID = *Blanks ;
  175.        SuccessFlag = *On ;
  176.        Select ;
  177.           When SQLCOD = -842 and SQLSTT = '08002' ; // Already connected
  178.              SuccessFlag = *On ;
  179.              SQLerrID = 'SQL9999' ;
  180.           When SQLCOD = 100 and IgnoreEOF ;
  181.              SuccessFlag = *On ;
  182.           When SQLSTT <> *Zero ;
  183.              SuccessFlag = *Off ;
  184.              SQLerrID = 'SQL9999' ;
  185.           When SQLCOD <> *Zero ;
  186.              SuccessFlag = *Off ;
  187.              SQLerrID = 'SQL9999' ;
  188.           When SQLCOD = *Zero ;
  189.              SuccessFlag = *On ;
  190.           Other ;
  191.              SuccessFlag = *On ;
  192.        EndSL ;
  193.        If SQLCOD = *Zero or (SQLCOD = 100 and IgnoreEOF) ;
  194.           // Couldn't think of another way to word it with readability
  195.        Else ;
  196.           EvalR SQLerrID = %EditC(%Abs(SQLCOD): 'X') ;
  197.           If %Subst(SQLerrID: 3: 1) = '0' ;
  198.              %Subst(SQLerrID: 1: 3) = 'SQL' ;
  199.           Else ;
  200.              %Subst(SQLerrID: 1: 2) = 'SQ' ;
  201.           EndIF ;
  202.           sndPgmMsg(SQLerrID: SQLERM: '*COMP') ;
  203.        EndIF ;
  204.        If Not SuccessFlag ;
  205.           If %Parms >= 4 and parmStmt <> *Blank ;
  206.              workLogStmt = 'Failing stmt: ' + parmStmt ;
  207.              DoW %Len(workLogStmt) > *Zero ;
  208.                 If %Len(workLogStmt) > 480 ;
  209.                    workLogStm2 = %Subst(workLogStmt: 1: 480) ;
  210.                    workLogStmt = %Subst(workLogStmt: 481) ;
  211.                 Else ;
  212.                    workLogStm2 = workLogStmt ;
  213.                    workLogStmt = '' ;
  214.                 EndIF ;
  215.                 sndPgmMsg('CPF9897'
  216.                         : workLogStm2
  217.                         : '*INFO') ;
  218.              EndDO ;
  219.           EndIF ;
  220.           If WarningOnly ;
  221.              sndPgmMsg('CPI8859'
  222.                   : 'Error occurred at ' + StmtLocation: '*COMP') ;
  223.           Else ;
  224.              SendEscape('CPF9898'
  225.                       : 'Abort due to SQL error at ' + StmtLocation
  226.                        ) ;
  227.           EndIF ;
  228.        EndIF ;
  229.        Return SuccessFlag ;
  230.  
  231.       /End-free
  232.  
  233.      P CheckSQL        E
  234.  
  235.  
  236.      P SendEscape      B                   Export
  237.        // ***************************************************************
  238.        // SendEscape will send an escape message to this program's caller
  239.        // Since this will cause execution of this program to fail, you
  240.        // should PERFORM BASIC CLEANUP BEFORE CALLING THIS ROUTINE.
  241.        // ***************************************************************
  242.      D SendEscape      PI
  243.      D   MSGID                             Const Like(QUSEC.messageID)
  244.      D   MSGDTA                            Const Like(QUSEC.messageData)
  245.      D   StackCount                   5I 0 Value Options(*NoPass)
  246.  
  247.      D SndStkCount     S              5I 0 Inz(-1)
  248.  
  249.       /Free
  250.  
  251.        sndPgmMsg(MSGID: MSGDTA: '*ESCAPE') ;
  252.        *INLR = *On ;                     // Really, this is documentary..   .
  253.        Return ;                          // But no harm done
  254.  
  255.       /End-free
  256.  
  257.      P SendEscape      E
  258.  
  259.  
  260.  
  261.      P sndPgmMsg       B                   Export
  262.        //******************************************
  263.        //*  Send an impromptu message to a pgmq
  264.        //******************************************
  265.      D sndPgmMsg       PI             4
  266.      D  parmMsgID                     7    Value
  267.      D  parmMsg                    4096    Value Options(*NoPass) Varying
  268.      D  parmMsgType                  10    Value Options(*NoPass)
  269.      D  parmMsgFile                  20    Value Options(*NoPass)
  270.      D  parmToPgmQ                   10    Value Options(*NoPass)
  271.      D  toPgmqCounter                10I 0 Value Options(*NoPass)
  272.  
  273.        //******************************************
  274.        //*  Local variables.
  275.      D myUSEC          DS                  LikeDS(QUSEC)
  276.      D msgf            DS            21
  277.      D  MsgFile                      10    Inz('QCPFMSG')
  278.      D  MsgFLib                      10    Inz('*LIBL')
  279.      D msgType         S                   Like(parmMsgType) Inz('*INFO')
  280.      D toPgmQ          S                   Like(parmToPgmQ)  Inz('*')
  281.      D msgid           S              7    Inz('CPF9897')
  282.      D msgData         S           4096    Varying
  283.      D nDataLen        S             10I 0 Inz(0)
  284.      D nRelInv         S             10I 0 Inz(1)
  285.      D nIncInv         S             10I 0 Inz(1)
  286.      D RtnMsgKey       S              4
  287.  
  288.      DQMHSNDPM_API     PR                  ExtPgm('QMHSNDPM')
  289.      D  MessageID                     7    const
  290.      D  MessageFile                  20    const
  291.      D  MessageData               65535    const Options(*varsize)
  292.      D  LengthMsgDta                 10I 0 const
  293.      D  MessageType                  10    const
  294.      D  CallStackEnt                 10    const Options(*varsize)
  295.      D  CallStkEntCtr                10I 0 const
  296.      D  MessageKey                    4
  297.      D  ErrorStruct                        LikeDS(QUSEC) Options(*varsize)
  298.  
  299.       /Free
  300.  
  301.        Clear myUSEC ;
  302.        myUSEC.bytesProvided = %Size(myUSEC) ;
  303.        if %addr(parmMsgType) <> *Null and parmMsgType = '*ESCAPE' ;
  304.           toPgmQ = '*PRVPGM' ;
  305.        endIF ;
  306.        If %Parms >= 1 and parmMsgID > *Blanks ;
  307.           msgID = parmMsgID ;
  308.        endif ; // %Parms >= 1
  309.        If %Parms >= 2 ;
  310.           msgData = %TrimR(parmMsg) ;
  311.        endif ; // %Parms >= 2
  312.        If %Parms >= 3 ;
  313.          msgType = parmMsgType ;
  314.          If %subst(msgType:1:1)<>'*' ;
  315.            msgType = '*' + %Trim(msgType) ;
  316.          endif ; // %subst(msgType:1:1)<>'*'
  317.          if msgType = '*ESCAPE' ;
  318.             toPgmQ = '*PRVPGM' ;
  319.          endIF ;
  320.        endif ; // %Parms >= 2
  321.        If %Parms >= 4 and parmMsgFile <> *Blanks ;
  322.           msgF = parmMsgFile ;
  323.           if MsgFLib = *Blanks ;
  324.              MsgFLib = '*LIBL' ;
  325.           EndIF ;
  326.        endif ; // %Parms >= 4
  327.        If %Parms >= 5 and parmToPgmQ <> *BLANKS ;
  328.          toPgmQ = parmToPgmQ ;
  329.        endif ; // %Parms >= 5
  330.        If msgType = '*STATUS' ;     // Status messages always go ToPgmQ(*EXT)
  331.          toPgmQ = '*EXT' ;
  332.        endif ; // msgType = '*STATUS'
  333.        If msgType = '*' ;
  334.          msgType = '*INFO' ;
  335.        endif ; // msgType = '*'
  336.        nDataLen = %len(msgData) ;  // Length of the message to be sent.
  337.        If msgType = '*INFO' ;
  338.           toPgmQ = '*CTLBDY' ;
  339.        EndIF ;
  340.        Select ;
  341.          When toPgmQ  = ' ' or toPgmQ = '*SAME' or toPgmQ = '*' ;
  342.            toPgmQ = '*' ;
  343.            nRelInv = *Zero ;
  344.            nIncInv = 1 ;
  345.          When toPgmQ = '*PRVPROC' or toPgmQ='*PRV' ;
  346.            toPgmQ = '*' ;
  347.            nRelInv = 1 ;
  348.            nIncInv = 1 ;
  349.          When toPgmQ = '*PRVPGM' ;
  350.            toPgmQ = '*CTLBDY' ;
  351.            nRelInv = *Zero ;
  352.            nIncInv = 1 ;
  353.          When toPgmQ = '*CTLBDY' ;
  354.            toPgmQ = '*CTLBDY' ;
  355.            nRelInv = *Zero ;
  356.            nIncInv = *Zero ;
  357.          When toPgmQ = '*EXT' ;
  358.            nRelInv = *Zero ;
  359.          Other ;
  360.            nRelInv = *Zero ;
  361.            nIncInv = *Zero ;
  362.        endsl ;
  363.        If %Parms >= 6 ;
  364.            nRelInv = toPgmqCounter ;
  365.            nIncInv = *Zero ;
  366.        EndIF ;
  367.  
  368.        If msgFile = 'QCPFMSG' and %Subst(msgid: 1: 2) = 'SQ' ;
  369.           msgFile = 'QSQLMSG' ;
  370.        EndIF ;
  371.        //*  Since we're a relative invocation, and we are
  372.        //*  one-level deep, we need to bump up the relative
  373.        //*  invocation by the calculated increment.
  374.        nRelInv += nIncInv ;
  375.        QMHSNDPM_API(msgid : msgf
  376.                           : msgData : nDataLen
  377.                           : msgType
  378.                           : toPgmQ
  379.                           : nRelInv
  380.                           : rtnMsgKey
  381.                           : myUSEC
  382.                            ) ;
  383.        return rtnMsgKey ;
  384.  
  385.       /End-free
  386.  
  387.      P sndPgmMsg       E
  388.  
  389.  
© 2004-2019 by midrange.com generated in 0.008s valid xhtml & css