I'm trying to retry from within a catch block
The manual https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref/catch-statement.html states
The code in any CATCH block can contain an explicit flow-of-control directive, meaning LEAVE, NEXT, RETRY, RETURN, or THROW. (RETRY and THROW require UNDO.) Since CATCH is an undoable block, LEAVE, NEXT, and RETRY without a label will apply to the CATCH block itself and not the associated block.
However if I run my sample code I get a compilation error.
Seems like a bug to me, or am I missing something ?
---------------------------
Syntax check:
Cannot UNDO to block 'tryblock' from within a CATCH block for block 'tryblock'. (14134)
---------------------------
define variable lInt as integer no-undo. define variable lText as character no-undo init "abc123". tryblock: do on error undo, retry: lint = integer(lText). catch err as Progress.Lang.Error : if lText > "" then do: substring(lText, 1, 1) = "". undo tryblock, retry tryblock. end. end catch. end.
Following variant compiles but it does not do what I expect either
I expect
instead I get
define variable lInt as integer no-undo. define variable lText as character no-undo init "abc123". tryblock: repeat while lTExt > "" on error undo, next: message "try" lText view-as alert-box. lint = integer(lText). catch err as Progress.Lang.Error : if lText > "" then do: substring(lText, 1, 1) = "". message "next" view-as alert-box. next tryblock. end. end catch. end. message "end" lInt lText view-as alert-box.
What happens if you replace REPEAT WHILE with DO WHILE?
There are definitely bugs using UNDO in a CATCH block. It definitely does not behave as documented. Though I thought it did work when a label is used. On the other hand, once the CATCH block runs, the associated block (tryblock in this case) has already been undone. So not sure saying UNDO in this context actually makes any sense.
How about something like this instead:
do while substring(lText, 1,1) >= 'a':
substring(lText, 1, 1) = "".
end.
You can't use DO WHILE with the CATCH because unless you RETRY, you will still leave the block after the error happens.
You can still fallback to using the NO-ERROR approach if CATCH is not playing well.
Something like:
lint = integer(lText) NO-ERROR
IF lint <> ? THEN
LEAVE.
[mention:04fbfb2e92784123a464ff2aade602b1:e9ed411860ed4f2ba0265705b8793d05] are these bugs already logged or is it better that I create a tech support case for this ? I did my tests in 11.7.4
As far as the alternatives are concerned, my actual use case doesn't look anything like the sample code I posted here.
I'll code it some other way but I was mainly wondering if I missed something in how to do a retry from within a catch block
Somethink like the following should do what you want:
tryblock: do while TRUE on error undo, retry: do on error undo, throw: lint = integer(lText). LEAVE tryblock. catch err as Progress.Lang.Error : if lText > "" then do: substring(lText, 1, 1) = "". NEXT tryblock. end. end catch. end. end.
There is an infinite loop protection for UNDO, RETRY block.
you should use the RETRY function or have user interaction before the error. If not it is replaced by undo, next
see :
knowledgebase.progress.com/.../What-is-Infinite-Loop-Protection
Infinite loop protection, indeed! THANK YOU. I never think of that. I was thinking that getting kicked out of the DO WHILE after a CATCH was also wrong. I was starting to get depressed!
In any case, Torben showed the right solution. And sorry - I never addressed the question of the error 14134. If you added yet another block level and lableled that as tryblock, it would compile. As I said, the associated block is already undone. I believe that is why.
tryblock:
do on error undo, leave: /* extra level here */
do on error undo, retry:
lint = integer(lText).
catch err as Progress.Lang.Error :
if lText > ""
then do:
substring(lText, 1, 1) = "".
undo tryblock, retry tryblock.
end.
end catch.
end.
END.