Query error raises a STOP?!?

Stefan

Well-Known Member
OpenEdge 10.2B04 GUI

A theoretically (based on the code) impossible entry outside range of list error was occurring in a static query on a temp-table. Since it was theoretically impossible I decided I would simply catch it, log it and analyze the results later. But then along came the fun...

At first I wanted to check which error message I would be getting so I used:

Code:
DEFINE TEMP-TABLE tt NO-UNDO FIELD cc AS CHAR.


DEF VAR cf AS CHAR INIT "ab".


CREATE tt. tt.cc = "aa".
           
DO ON ERROR UNDO, LEAVE:


   FOR EACH tt
      WHERE ENTRY( 0, cf ) > "" /* note that this is on the variable */
   ON ERROR UNDO, THROW:

   END.


   CATCH oe AS PROGRESS.lang.syserror:
      MESSAGE oe:getMessage(1) VIEW-AS ALERT-BOX.
   END CATCH.


END.


MESSAGE "done" VIEW-AS ALERT-BOX.

To my surprise this does not throw any error at all. So for sanity's sake:

Code:
DEF VAR cf AS CHAR INIT "ab".


DO ON ERROR UNDO, LEAVE:


   MESSAGE ENTRY( 0, cf ) > "" VIEW-AS ALERT-BOX.


   CATCH oe AS PROGRESS.lang.syserror:
      MESSAGE oe:getMessage(1) VIEW-AS ALERT-BOX.
   END CATCH.


END.


MESSAGE "done" VIEW-AS ALERT-BOX.

Yes, error 560 is being raised and trapped. So updated the test a bit more to what it should be:

Code:
DEFINE TEMP-TABLE tt NO-UNDO FIELD cc AS CHAR.
DEF VAR ii AS INT .
DEF VAR cf AS CHAR INIT "ab".
 
CREATE tt. tt.cc = "aa".
CREATE tt. tt.cc = "bb". 
          
DO ON ERROR UNDO, LEAVE:
 
   FOR EACH tt
      WHERE ENTRY( 0, tt.cc ) > "" /* note that this is on the temp-table field */
   ON ERROR UNDO, THROW:
 
      MESSAGE FILL( tt.cc, 20000 ) VIEW-AS ALERT-BOX.
 
      CATCH oe1 AS PROGRESS.Lang.ERROR:
         MESSAGE oe1:getMessage(1) VIEW-AS ALERT-BOX.
      END CATCH.
   END.
 
   CATCH oe2 AS PROGRESS.lang.syserror:
      MESSAGE oe2:getMessage(1) VIEW-AS ALERT-BOX.
   END CATCH.
 
END.
 
MESSAGE "done" VIEW-AS ALERT-BOX.

Hurrah, error 560 is back! But it is not caught (red cross error message) and message done is never reached. The query error is apparently raising a STOP and not an error:

Code:
DEFINE TEMP-TABLE tt NO-UNDO FIELD cc AS CHAR.
DEF VAR ii AS INT .
DEF VAR cf AS CHAR INIT "ab".


CREATE tt. tt.cc = "aa".
CREATE tt. tt.cc = "bb".
           
DO ON STOP UNDO, LEAVE:


   FOR EACH tt
      WHERE ENTRY( 0, tt.cc ) > "" 
   ON ERROR UNDO, THROW:


      MESSAGE FILL( tt.cc, 20000 ) VIEW-AS ALERT-BOX.


      CATCH oe1 AS PROGRESS.Lang.ERROR:
         MESSAGE oe1:getMessage(1) VIEW-AS ALERT-BOX.
      END CATCH.
   END.


   CATCH oe2 AS PROGRESS.lang.syserror:
      MESSAGE oe2:getMessage(1) VIEW-AS ALERT-BOX.
   END CATCH.


END.


MESSAGE "done" VIEW-AS ALERT-BOX.

Now error 560 is displayed as a red cross error message and message done is reached again...


So:

1. why is ENTRY( 0, cf ) > "" not raising an error when used in a query?
2. why is ENTRY( 0, tt.cf) > "" raising an uncatchable stop instead of a normal error?
 

GregTomkins

Active Member
I tried it quickly in CUI 10.1C HPUX and I got the identical errors, but if I just play around with ENTRY(0) by itself (eg. minus the UNDO,THROW which I don't use in P4GL so am therefore automatically suspicious of), all seems normal (it consistently returns error 560, for both variables and TT's and for both the function and statement version of ENTRY). Anyhow maybe this snip (from the documentation) helps?

Element: An integer value that corresponds to the position of a character string in a list of values. If the value of element does not correspond to an entry in the list, Progress raises the ERROR condition. If the value of element is unknown (?), ENTRY returns an unknown value. If element is less than or equal to 0, or is larger than the number of elements in list, ENTRY returns an error.
 

Stefan

Well-Known Member
I tried it quickly in CUI 10.1C HPUX and I got the identical errors, but if I just play around with ENTRY(0) by itself (eg. minus the UNDO,THROW which I don't use in P4GL so am therefore automatically suspicious of), all seems normal (it consistently returns error 560, for both variables and TT's and for both the function and statement version of ENTRY).

Strange... when I remove the witchcraft I still do not get an error 560 (which I expected).

Code:
DEFINE TEMP-TABLE tt NO-UNDO FIELD cc AS CHAR.

DEF VAR cf AS CHAR INIT "ab".

CREATE tt. tt.cc = "aa".
           
FOR EACH tt
   WHERE ENTRY( 0, cf ) > "" /* note that this is on the variable */
:
END.

MESSAGE "done" VIEW-AS ALERT-BOX.

Anyhow maybe this snip (from the documentation) helps?

Element: An integer value that corresponds to the position of a character string in a list of values. If the value of element does not correspond to an entry in the list, Progress raises the ERROR condition. If the value of element is unknown (?), ENTRY returns an unknown value. If element is less than or equal to 0, or is larger than the number of elements in list, ENTRY returns an error.

Yes, it is the ERROR 560 that I am after, but

1. an error is not raised when on a variable in the query
2. a STOP is being raised and not an ERROR
 

UncleNel

New Member
First, Stefan thanks for a very interesting issue. I did some research, and some testing and came away with the following:

1) Research: STOP & QUIT are not captured by CATCH.
2) ENTRY(0,...) when used in the FOR-EACH where clause can only be trapped (ON STOP) in the outer FOR-EACH block, not within the FOR-EACH. I still haven't been able to obtain the 560 error message, other than it is directed to standard out. Note: Using ENTRY() in the FOR-EACH where clause may cause you to loose the desired index (which I assume you knew, but were only trying to trap the error in your examples).
3) Moving the ENTRY(0,...) to within the FOR-EACH block, you are able to trap the error.
4) The attached code (one of your examples, modified) attempts to display error handling in both situations.

Code:
DEFINE TEMP-TABLE tt NO-UNDO 
    FIELD cc AS CHAR.

DEF VAR i      AS INT NO-UNDO.

DEF VAR sysMsg AS CHAR NO-UNDO.
DEF VAR appMsg AS CHAR NO-UNDO.
DEF VAR errMsg AS CHAR NO-UNDO.

MAIN:
DO i = 1 TO 2 
    ON ERROR UNDO, LEAVE
    ON STOP  UNDO, LEAVE:

    HIDE ALL NO-PAUSE.
    MESSAGE SUBSTITUTE("TEST#(&1)",i) VIEW-AS ALERT-BOX.
    
    RUN Proc-AA (INPUT i) .
    
    CATCH anyError AS PROGRESS.LANG.ERROR.
        MESSAGE SUBSTITUTE("Proc-AA_ReturnedError(Test#:&1):~n&2", 
                            i, RETURN-VALUE) 
                SUBSTITUTE("~nanyError=&1",anyError:GETMESSAGE(1))
            VIEW-AS ALERT-BOX.
    END. /*catch*/
END. /*MAIN: do i*/




PROCEDURE Proc-AA.
    DEF INPUT PARAM pi AS INT NO-UNDO.
    DEF VAR ii AS INT NO-UNDO.
    DEF VAR cf   AS CHAR INIT "ab" NO-UNDO.
    DEF VAR cMsg  AS CHAR NO-UNDO.

    CREATE tt. tt.cc = "aa".
    CREATE tt. tt.cc = "bb".

    PROC-MAIN:
    DO ON ERROR UNDO, RETRY
       ON STOP  UNDO, RETRY
        :
       IF RETRY THEN DO:
            IF ERROR-STATUS:NUM-MESSAGES GT 0 THEN
                cMsg = SUBSTITUTE("ERROR:&1",ERROR-STATUS:GET-MESSAGE(1)).
            ELSE 
                IF errMsg + sysMsg + appMsg GT ""  /*any messages?*/
                THEN
                    cMsg = SUBSTITUTE("errMsg=&1~nappErr=&2~nsysErr=&3",
                                       errMsg,appMsg,sysMsg).
                ELSE
                    cMsg = SUBSTITUTE("ERROR:&1",
                                "A runtime STOP condition has occured.").
          RETURN ERROR cmsg. /*return error to calling program*/  
       END.
       ASSIGN   errMsg = ""
                sysMsg = ""
                appMsg = ""
                .
       FOR EACH tt  
          WHERE   /*Test#2 Use the entry(0,...) filter in the for-each select*/
            (IF pi EQ 1 THEN TRUE /*dummy up where clause*/
             ELSE ENTRY( 0, tt.cc ) > "") 
          ON ERROR UNDO, LEAVE
          :
          /*pi=1 (Test#1 Filter entry(0,...) within the for-each block*/
          IF pi EQ 1 THEN DO:
            MESSAGE "Before ENTRY(0,....)" 
                VIEW-AS ALERT-BOX.
            IF NOT ENTRY( 0, tt.cc ) > "" THEN  NEXT.
          END.
          MESSAGE FILL( tt.cc, 20000 ) VIEW-AS ALERT-BOX.
          CATCH oe1 AS PROGRESS.LANG.ERROR:
            errMsg = oe1:GETMESSAGE(1).
            /*MESSAGE substitute("ERR1:&1",oe1:getMessage(1)) VIEW-AS ALERT-BOX.*/
            UNDO, THROW oe1.
          END CATCH.
       END.
       CATCH oe2 AS PROGRESS.LANG.appERROR:
          appMsg = oe2:GETMESSAGE(1).
          /*MESSAGE substitute("ERR2:&1",oe2:getMessage(1)) VIEW-AS ALERT-BOX.*/
          UNDO, THROW oe2 . 
          CATCH oe3 AS PROGRESS.LANG.SYSERROR:
            sysMsg = oe3:GETMESSAGE(1).
            /*MESSAGE substitute("ERR3:&1",oe3:getMessage(1)) VIEW-AS ALERT-BOX.*/
            UNDO, THROW oe3 . 
          END CATCH.
       END CATCH.
    END. 
    MESSAGE "done" VIEW-AS ALERT-BOX.
END PROCEDURE.
 
Top