Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

use of INVALID KEY clause

889 views
Skip to first unread message

Frank Swarbrick

unread,
Feb 27, 2009, 5:05:32 PM2/27/09
to
Interesting that Pete mentioned having seen use of INVALID KEY and NOT
INVALID KEY recently. I was pondering the use of this just yesterday. We
had a program that does this:


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

rip...@azonic.co.nz

unread,
Feb 27, 2009, 5:21:40 PM2/27/09
to
On Feb 28, 11:05 am, "Frank Swarbrick"

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.

Michael Mattias

unread,
Feb 27, 2009, 7:19:21 PM2/27/09
to
"Frank Swarbrick" <Frank.S...@efirstbank.com> wrote in message
news:49A8013C.6...@efirstbank.com...

> Interesting that Pete mentioned having seen use of INVALID KEY and NOT
> INVALID KEY recently. I was pondering the use of this just yesterday.

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


William M. Klein

unread,
Feb 27, 2009, 5:40:59 PM2/27/09
to
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).

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...

Richard

unread,
Feb 27, 2009, 10:14:36 PM2/27/09
to
William M. Klein wrote:
> 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?

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.

rip...@azonic.co.nz

unread,
Feb 27, 2009, 10:28:05 PM2/27/09
to
On Feb 28, 1:19 pm, "Michael Mattias" <mmatt...@talsystems.com> wrote:
> "Frank Swarbrick" <Frank.Swarbr...@efirstbank.com> wrote in message

>
> news:49A8013C.6...@efirstbank.com...
>
> > Interesting that Pete mentioned having seen use of INVALID KEY and NOT
> > INVALID KEY recently.  I was pondering the use of this just yesterday.
>
> 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.

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.

Pete Dashwood

unread,
Feb 28, 2009, 5:42:02 AM2/28/09
to

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."


HeyBub

unread,
Feb 28, 2009, 6:08:54 PM2/28/09
to
Michael Mattias wrote:
> "Frank Swarbrick" <Frank.S...@efirstbank.com> wrote in message
> news:49A8013C.6...@efirstbank.com...
>> Interesting that Pete mentioned having seen use of INVALID KEY and
>> NOT INVALID KEY recently. I was pondering the use of this just
>> yesterday.
>
> 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.
>

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).


Rene_Surop

unread,
Mar 1, 2009, 8:06:50 PM3/1/09
to
>
> 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....)
>

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.

Howard Brazee

unread,
Mar 2, 2009, 10:46:03 AM3/2/09
to
On Fri, 27 Feb 2009 16:40:59 -0600, "William M. Klein"
<wmk...@nospam.ix.netcom.com> wrote:

>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

Robert Jones

unread,
Mar 5, 2009, 4:58:01 PM3/5/09
to
On 27 Feb, 22:05, "Frank Swarbrick" <Frank.Swarbr...@efirstbank.com>
wrote:

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

HeyBub

unread,
Mar 5, 2009, 6:44:22 PM3/5/09
to
Robert Jones wrote:
>
> 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.
>

Yeah, sort of like mixing COMPUTE and ADD. Whatever fits the flow.


des....@gmail.com

unread,
May 16, 2013, 10:41:31 AM5/16/13
to
Hi,

I now use evaluate for example:

READ NMP.
EVALUATE NMP-STATUS
WHEN '00'
Process nomally...
WHEN '23'
DISPLAY 'Key not on NMP'
WHEN OTHER
DISPLAY 'NMP-STATUS: ' 'NMP-STATUS
CALL "ABORT"
END-EVALUATE.

I regard this as safer because nothing falls through the cracks.

Des

0rober...@gmail.com

unread,
May 16, 2013, 3:33:29 PM5/16/13
to
I agree. On reflection, it is normally better to use FILE STATUS and one can use condition-names to give some of the codes a more obvious meaning if so desired, though programmers quickly learn the more common ones anyway. At one point and possibly still the case for some implementations, the information one could get from a dump for a file error was much more helpful than the limited information available from FILE STATUS.
Robert

Pete Dashwood

unread,
May 16, 2013, 7:32:07 PM5/16/13
to
Hmmm... it seems to me that both of you have missed the AT END condition and
the code , as written, will abort at EOF... (Status '10')

What about this:

READ NMP
AT END
CLOSE NMP
PERFORM DISPLAY-CONTROLS
STOP RUN *> ...or whatever...
NOT AT END
EVALUATE NMP-STATUS
WHEN '00'
Process nomally...
WHEN '23'
DISPLAY 'Key not on NMP'
WHEN OTHER
DISPLAY 'NMP-STATUS: ' 'NMP-STATUS
CALL "ABORT"
END-EVALUATE.
END-READ

Richard

unread,
May 17, 2013, 12:15:05 AM5/17/13
to
When testing a file-status is is import to check only the first byte
being zero for success. The 2nd byte may contain additional
information.

Clark F Morris

unread,
Jun 15, 2013, 3:55:06 PM6/15/13
to
If file status 23 is a valid occurrence, then end file is not a valid
occurrence. The READ for random or dynamic files can not produce an
end file. READ NEXT for dynamic files can.

Clark Morris

Pete Dashwood

unread,
Jun 16, 2013, 3:28:20 AM6/16/13
to
Yes, I know.

The code above can be used in either case. Are you suggesting you would
rather have two separate evaluates (1 each for Random and Sequential
access), with possibly a third for skip sequential access or more program
logic to deal with selecting which one of the evaluates when dealing with
skip sequential?

Your prerogative.

I prefer ONE for everything. ( I LIKE generalized routines, even though they
may not be as efficient in certain circumstances.)

I'm lazy that way... (MY prerogative)

If you are going to publicly pat yourself on the pat for coming up with what
is still a primitive technique for handling I/O, then the least you can do
is show completeness. Don't just assume that random access is the ONLY
access people are going to use.

Pete

Pete Dashwood

unread,
Jun 16, 2013, 6:24:53 PM6/16/13
to

Pete Dashwood

unread,
Jun 16, 2013, 6:44:10 PM6/16/13
to
I was wrong about this.

In COBOL you CAN'T use ONE routine as shown.

If you OPEN for SEQUENTIAL access you can use the above, in which case you
won't get the 23 as Clark pointed out (and I did actually know).

I was trying to show a principle and simply copied previously posted code
which contained the 23.

If you OPEN for RANDOM access you can't get EOF (although I seem to remember
working on at least one COBOL system where you could - B500, now long dead.
It could return EOF or 23)

If you open for DYNAMIC access you would have to have a version of the above
with read NEXT, instead of READ and then the 23 check is unnecessary.

The water is further muddied by using (NOT) INVALID KEY instead of (NOT) AT
END. Some compilers care about this, others don't.

As far as I can tell, there is no easy way to have a single, "universal"
response checker, although I haven't investigated it thoroughly and simply
don't have time to do so at the moment.

The problem doesn't arise if you use a database. :-)

Pete.
0 new messages