Page 1 of 1

Is it possible to browse a VSAM file in descending order?

PostPosted: Mon Apr 04, 2016 6:43 am
by Robert Barnes
Is there an easy way of finding out the highest key currently in use in a KSDS? I'm trying to implement a simple "Add new record" function in <advertising removed>. In my test data Custf is a VSAM file keyed on Custf.Account, and I'm trying to work out the COBOL that I want for a NewKey function in

   WHEN (Add);
* CustF.Account = NewKey;  [???
        GET custf KEY(CustF.Account) UPDATE;
            #243 E GET ... UPDATE with neither CHECKCOPY nor CHECKSUM MUST create a new record
            ACCEPT (IWSPG2.custf.*) EXCEPT(IWSPG2.Account) TO custf MESSAGE OWSPG2.ERROR;
            #447 I Numeric Data will already be converted to numbers
        END GET custf UPDATE RESPOND OWSPG2;
 

Code' d
If Custf were SQL I'd be able to use SELECT MAX(Account) FROM ..., and if STARTBR offered an DESC order option I could browse to the last record, but it doesn't. Setting Account = 999999 and then EXEC CICS STARTBR (which would immediately ENDFILE) wouldn't return the last record (would it?). So what's my best approach?

Thank you,
Robert Barnes

Advertising removed

Re: Is it possible to browse a VSAM file in descending order

PostPosted: Mon Apr 04, 2016 7:01 am
by Robert Barnes
Sorry everybody, I was too quick to post. The answer (which was obvious when I read further) was
STARTBR with RIDFLD value of X'FF'
then
READPREV

Duh!

Robert

Advertising removed

Re: Is it possible to browse a VSAM file in descending order

PostPosted: Mon Apr 04, 2016 12:04 pm
by BillyBoyo
And what is going to happen when two users do that around about the same time?

Re: Is it possible to browse a VSAM file in descending order

PostPosted: Mon Apr 04, 2016 12:44 pm
by Robert Barnes
BillyBoyo, thank you for your comment, but won't it be OK here? The logic is

WHEN (Add);
CustF.Account = Custf.$LastKey + 1;
GET custf KEY(CustF.Account) UPDATE;
#243 E GET ... UPDATE with neither CHECKCOPY nor CHECKSUM MUST create a new record
ACCEPT (IWSPG2.custf.*) EXCEPT(IWSPG2.Account) TO custf MESSAGE OWSPG2.ERROR;
END GET custf UPDATE RESPOND OWSPG2;
 

The reference to Custf.$LastKey [creates COBOL code that] performs a paragraph that reverse-browses Custf to determine the largest value of Custf.Account. Adding 1 to it creates the next free key, and then GET custf KEY(CustF.Account) UPDATE; reads and locks this record. There is no user interaction between the two Jazz statements so there is very little time for another user to have created a record with this key, but it is not impossible. However, as the error message indicates, this GET is not permitted to find an existing record, so that if the record does exist because the improbable has actually happened the update, which occurs at the END GET, will fail because it's attempting to WRITE rather than REWRITE.

For the update case the logic is: -
  WHEN (Update);
        ACCEPT (CustF.Account=IWSPG2.Account) MESSAGE OWSPG2.ERROR;
        GET custf KEY(CustF.Account) UPDATE CHECKSUM IWSPG2.CheckSum-custf;
            ACCEPT (IWSPG2.custf.*) EXCEPT(IWSPG2.Account) TO custf MESSAGE OWSPG2.ERROR;
            #447 I Numeric Data will already be converted to numbers
        END GET custf UPDATE RESPOND OWSPG2;
 

You'll notice that here the GET has the option CHECKSUM, which will compare the value returned in the input message (field IWSPG2.CheckSum-custf) with the value sent out with a CHECKSAVE option on the preceding Enquiry. Both CHECKSAVE and CHECKSUM use EXEC CICS BIF DIGEST to calculate a 40 hex character message digest.

Would you like me to send a copy of the generated COBOL? If yes, please send me a private email (e-mail address removed to reduce spamming) and I'll send you a sample of the generated code. I'd be delighted for you to look over it and give me feedback.

Regards, Robert.

Code' d