START FRDCCRD-FILE KEY >= FRDCCRD-KEY
IF FRDCCRD-OK
PERFORM READ-FRDCCRD-RECORDS
ELSE
DISPLAY 'CVDTR085-FRDCCRD-FILE START ERROR. '
'STATUS ' FRDCCRD-STATUS
UPON CONSOLE
MOVE 16 TO RETURN-CODE
GOBACK
END-IF
Last night we got "CVDTR085-FRDCCRD-FILE START ERROR. STATUS 23"
This was because the key we wanted to start on was higher than the highest
key in the file.
I made the obvious change:
START FRDCCRD-FILE KEY >= FRDCCRD-KEY
EVALUATE TRUE
WHEN FRDCCRD-OK
PERFORM READ-FRDCCRD-RECORDS
WHEN FRDCCRD-NOT-FOUND
CONTINUE
WHEN OTHER
DISPLAY 'CVDTR085-FRDCCRD-FILE START ERROR. '
'STATUS ' FRDCCRD-STATUS
UPON CONSOLE
MOVE 16 TO RETURN-CODE
GOBACK
END-EVALUATE
But it got me thinking, what if I had changed it to this?
START FRDCCRD-FILE KEY >= FRDCCRD-KEY
INVALID KEY
CONTINUE
NOT INVALID KEY
PERFORM READ-FRDCCRD-RECORDS
END-START
Looks good. Except what happens if there is a status other than '00' or
'23'? Well the answer is nothing. It does neither the code under INVALID
KEY nor the code under NOT INVALID KEY. So it looks like you *still* have
to do file status checking after the END-START. Which begs the question,
why use the INVALID KEY/NOT INVALID KEY clauses at all. Same with AT END
and NOT AT END. I don't have an answer. (Well, I sort of have one:
DECLARATIVES. See below.)
I do know that we have a lot of code that uses at least "INVALID KEY" and
"AT END", if not much that uses "NOT INVALID KEY" and "NOT AT END", and they
don't necessarily check for other bad file status conditions (though some
do). It's never really caused a problem that I know of. But I'm guessing
that it's simply that those other conditions *don't occur*. It's a bad
assumption to think that they could never occur, though I really can't think
of others that might occur. Generally the errors happen on the OPEN and not
on the READ (or START). In fact, to test out how the INVALID KEY/NOT
INVALID KEY stuff worked I actually commented out the OPEN, so that
condition '47' (file not open for input) would occur.
Now I do know that the use of DECLARATIVES would solve this, ie:
DECLARATIVES.
FRDCCRD-ERROR SECTION.
USE AFTER ERROR PROCEDURE ON FRDCCRD-FILE.
FRDCCRD-ERROR-START.
DISPLAY 'ERROR ON FRDCCRD: ' FRDCCRD-STATUS
UPON CONSOLE
MOVE 16 TO RETURN-CODE
GOBACK.
FRDCCRD-ERROR-EXIT.
EXIT.
END DECLARATIVES.
In this case a file status of anything other than '00' or '23' would go to
the FRDCCRD-ERROR section.
Personally I've grown somewhat fond of using DECLARATIVES for this type of
processing, though I have yet to convince anyone else of it's goodness. But
if you don't use it I don't see that I'd recommend the INVALID KEY/NOT
INVALID KEY coding as shown above. Just use the three test evaluate.
Comments?
Frank
--
Frank Swarbrick
Senior Systems Analyst - Mainframe Applications
FirstBank Data Corporation
Lakewood, CO USA
When testing for successful completion the first byte only should be
tested for '0'. There are several status values that are '0x' that
indicate success but have other information.
> '23'? Well the answer is nothing. It does neither the code under INVALID
> KEY nor the code under NOT INVALID KEY. So it looks like you *still* have
> to do file status checking after the END-START. Which begs the question,
> why use the INVALID KEY/NOT INVALID KEY clauses at all. Same with AT END
> and NOT AT END. I don't have an answer. (Well, I sort of have one:
> DECLARATIVES. See below.)
I have lots of code that does (for example reading all transactions
for a customer:
MOVE Customer-Code TO Transaction-Key
START Transaction-File
KEY NOT < Transaction-Key
INVALID KEY
MOVE HIGH-VALUES TO Transaction-Key
END-START
PERFORM UNTIL Transaction-Customer NOT = Customer-Code
READ Transaction-File
NEXT RECORD
WITH NO LOCK
AT END
MOVE HIGH-VALUES TO Transaction-Key
END-READ
IF (
I dislike DECLARATIVES. Code should be local unless it is explicitly
remote.
What's the difference between.....
READ filename
IF Status-OK THEN
perform good-read
ELSE
perform bad-read
END-IF
END-READ
READ FILENAME
NOT INVALID KEY
perform Good-Read
INVALID KEY
perform bad-read
END-READ
... ???
Basically: nothing, except you don't need to set up a FILE STATUS IS...
variable... but then you can't test the various values for the file on open
or start failures.
You have START operations to worry about, so maybe using FILE-STATUS makes
more sense - for your application.
But if an application is simply doing random reads - eg validation of some
entry - a simple "Yes I found a record with that key" or "No I didn't"
could be plenty good enough. INVALID KEY/NOT INVALID KEY provides the binary
solution set which is exactly what a 'data validation' application requires.
Do you NEED to use INVALID KEY, NOT INVALID KEY? Nope. Might it be handy?
Sure.
COBOL also includes a COMPUTE verb. Do you NEED it? Nope. Might it handy?
Sure.
MCM
If you are talking about a "general rule", then one needs to decide if ONLY "00"
is successful for this SPECIFIC piece of logic or if any "0x" is successful.
(For some places in logic it is one and in others it is the other case).
As far as declaratives go, it seems to me that "good defensive code"
Either
- one checks for ALL possible codes (or ranges of codes) possible from a
specific statement
or
- one uses <NOT>invalid key/at end
and
codes a declarative for what may "fall out"
The other "choice" is to let the system (or application) do whatever it wants
with "unhandled" file status values. I know some shops where this is the
"norm" - but it is certainly not something that I like.
--
Bill Klein
wmklein <at> ix.netcom.com
<rip...@Azonic.co.nz> wrote in message
news:62c39ff2-2ed8-4613...@o8g2000pre.googlegroups.com...
You may note that my sample code does not check the file status after
the START, it uses the INVALID KEY, which was the subject of the
question and the point about my reply.
> If you are talking about a "general rule", then one needs to decide if ONLY "00"
> is successful for this SPECIFIC piece of logic or if any "0x" is successful.
> (For some places in logic it is one and in others it is the other case).
The standard defines the codes for a 'successful' transfer as those
with a zero in the first byte. The second byte may contain additional
information. While currently the ones you list are those that may
currently appear there may be others implemented in future standards.
When testing for successful completion the first byte only should be
tested for '0'.
If you also want to test for specific additional information, then do
so, but these do not indicate 'unsuccessful' transfer.
For example an '02' returned after a WRITE or REWRITE does indicate
that the record has been successfully written.
> As far as declaratives go, it seems to me that "good defensive code"
> Either
> - one checks for ALL possible codes (or ranges of codes) possible from a
> specific statement
> or
> - one uses <NOT>invalid key/at end
> and
> codes a declarative for what may "fall out"
>
> The other "choice" is to let the system (or application) do whatever it wants
> with "unhandled" file status values. I know some shops where this is the
> "norm" - but it is certainly not something that I like.
While declaratives _MIGHT_ be defensive code, and possibly even
'good', it is still remote and not explicitly so. There are much
better ways for languages to implement mechanisms to write defensive
code, such as try: except: else: blocks.
My complaint was not what declaratives do (or don't do), but how they
do it.
In the first example, depending on how Status-OK is defined, there may
be cases where bad-read is done when good-read should have been.
In the second example there are cases where, in the absence of a file-
status, neither good-read nor bad-read will be executed.
D'you think... ? :-)
It is logically redundant and shows what happens when you think in English
instead of Symbolic logic...:-)
> START FRDCCRD-FILE KEY >= FRDCCRD-KEY
> NOT INVALID KEY
> PERFORM READ-FRDCCRD-RECORDS *> this WON'T get done if there is an
> INVALID KEY
*>
whether you specify INVALID KEY or not...
> END-START
...has exactly the same truth value but doesn't require the redundant
clause.
The construct you came up with is precisely what was used on the site I
mentioned. I suspect they followed the same logic path as you did. These are
not stupid people(I'm certainly NOT implying that you are, Frank :-)), but
sometimes it is necessary to step back. It is an axiom of Boole's algebra
that A.A' can never be TRUE... (just as A + A' is ALWAYS TRUE...) You
therefore only need one of them.
>Except what happens if there is a status other than '00'
> or '23'? Well the answer is nothing. It does neither the code under
> INVALID KEY nor the code under NOT INVALID KEY. So it looks like you
> *still* have to do file status checking after the END-START.
Yes, you do.
I considered at length what to do about this.
If a site is adept enough to have a standard abort routine that can
interrogate problems, log them, close things that are open and gracefully
abend, then it would be feasible to generate code to invoke it after the
END-START. However, there are many possibilities, the abort routine would
need parameters (which means an interface that may change) and the
permutations are pretty heavy. In the end I reluctantly decided not to
improve the existing COBOL with a robot and, after discussion, we agreed
that as long as the new generated code was no worse than the existing
manually written code, everyone would be happy... :-)
> Which
> begs the question, why use the INVALID KEY/NOT INVALID KEY clauses at
> all. Same with AT END and NOT AT END.
Because sometimes all you want to know is: "Did I get it or didn't I?" You
may not be concerned that there has been a catastrophic failure on a dataset
you won't be accessing again anyway... :-)
It gets even trickier when they convert to RDB and the possible SQLSTATEs
are much more plentiful than the FILE STATUS domain could ever be...
> I don't have an answer.
I don't think the question is very clear... :-)
DECLARATIVES are useful, but having them always at the start of the
Procedure divison makes it kludgy... you have to scroll or flip through code
to get to them and if you start "personalising" them for specific errors it
gets very unwieldy.
The answer is TRY...CATCH...FINALLY (which COBOL may implement around the
time that Satan starts wearing an anorak....)
Pete.
--
"I used to write COBOL...now I can do anything."
Sure there's a difference. What if the file goes offline after being opened
but before the START?
(IN)VALID key won't catch that problem, but FILE STATUS will (or at least I
hope it wll).
I hope the above simple syntax (Microsoft way) will do the thing. In
Cobol I usually use this code;
*>
*>Set up the exception handling
INVOKE entrycallback "new" USING z"onExceptionERR"
RETURNING osException
INVOKE exceptmgr "register" USING oleExceptMgr
osException
:
:
:
:
999-Callback section.
entry "onExceptionERR" using by reference lnkErrorObject
by reference lnkErrorNumber
by reference lnkErrorText.
:
:
:
:
exit program.
stop run.
It's quite long coding but you could modify it according to taste, but
then again "every error" will be trapped on this net and that's not
advisable.
>I haven't checked yet, but WHAT "0x" status value can be returned from a START
>statement - other than "00"? It seems to me that:
> 02 - only for READ, WRITE, or REWRITE
> 04 - only for READ
> 05 - only for OPEN
> 07 - only for OPEN or CLOSE
>So WHY should a program check for "0x" after a START statement?
>
>If you are talking about a "general rule", then one needs to decide if ONLY "00"
>is successful for this SPECIFIC piece of logic or if any "0x" is successful.
>(For some places in logic it is one and in others it is the other case).
Or with IBM mainframes with an open return code of 97, which is
successful open with file integrity verified.
--
"In no part of the constitution is more wisdom to be found,
than in the clause which confides the question of war or peace
to the legislature, and not to the executive department."
- James Madison
AT END, INVALID KEY, etc were introduced with the early COBOL
standards/definitions, File status was a later addition. I think that
these days it is better to check for file status, but sometimes
programs read better for using AT END and INVALID KEY as well.
Robert
Yeah, sort of like mixing COMPUTE and ADD. Whatever fits the flow.