[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference clt::cobol

Title:VAX/DEC COBOL
Notice:Kit,doc,performance talk info-->DIR/KEY=KIT or DOC or PERF_TALK
Moderator:PACKED::BRAFFITT
Created:Mon Feb 03 1986
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3250
Total number of notes:13077

3216.0. "Read alternate key with duplicates" by CCAD14::MCCULLOCH () Thu Mar 13 1997 19:27

Hi All,


I have a customer who has been having problems reading alternate keys from a
file.  I am not much (not at all!) of a COBOL programmer, so I require some
assistance. I have looked at the latest VAX COBOL User Guide and Reference but
cannot find an explicit example of the file access used here.

System details:
  VAX VMS V6.1
  COBOL V4.4 (yes I know it is an old unsupported version - I am trying to get
  the customer to upgrade).
  File in question - about 100000+ records
  Each alternate key has about 2-3 duplicates (no more).


From what I can gather, the basic idea of the program is to:

  start reading the file using alternate key.
  Read the record.
  loop until no more records which match alternate key.
    If data contained therein matches condition
      process it
    else
      read next record
      if end of record
        terminate loop
      endif
    endif
  endloop

I have appended some code fragments which demonstrate the code I have been
given to look at (note that these are extracted from various interface files
and therefore do not constitute a compilable complete program).

I can see some faults in the program logic particularly checking the file
status codes.  The program assumes that it will get some sort of "no more
records" file status when no more records which match the alternate key are
present. (BTW I have tried STARTing with alternate key "=").


    I wish to confirm how it SHOULD work.  I looked at Note 56 and others
    (dir/title="alt") in this conference and it seems to suggest that the
    way to do it is:

  start reading the file using alternate key (as at present)
  read the record
  loop until no more records which match alternate key.
    check that this is still the same alternate key value
    if it is
      process the record

      read next record
      if end of file (?)
        terminate loop
      endif
    else
      terminate loop
  endloop

ie. The program has to do its own MANUAL checking of the alternate key after
the read to see if it has changed. Am I am on the right lines here ?

Why doesn't the KEY IS EQUAL TO on the START statement make any difference to
the way the file is read.  Is it just an "initial key value" on the file ?

Thanks for your attention.

Malcolm McCulloch
DIGITAL ADC
Christchurch
New Zealand


*** PROGRAM extracts follow

INPUT-OUTPUT SECTION.

FILE-CONTROL.

    SELECT OPTIONAL TIPOSTCODE_REQ
           ASSIGN TO "TIPOSTCODE_REQ"
           ORGANIZATION IS INDEXED
           ACCESS MODE IS DYNAMIC
           RECORD KEY IS PR_DBKEY with duplicates
           ALTERNATE RECORD KEY IS PR_ALT_DBKEY with duplicates
           FILE STATUS IS LK-FHS-FILE-STATUS.

I-O-CONTROL.

    APPLY CONTIGUOUS-BEST-TRY PREALLOCATION 100000
          EXTENSION 20000
          LOCK-HOLDING
          WINDOW 255
          ON TIPOSTCODE_REQ.

DATA DIVISION.

FILE SECTION.

FD  TIPOSTCODE_REQ.

* FROM COPYBOOK

01  PR:_POSTCODE_REQUEST_RECORD.
    05  PR:_DBKEY.
     07  PR:_BILLING_ID                        PIC  X(006).
    05  PR:_ALT_DBKEY.
     07  PR:_CUSTOMER_ID                       PIC  S9(009).
    05  PR:_ADDRESS_1                          PIC  X(030).
    05  PR:_ADDRESS_2                          PIC  X(030).
    05  PR:_ADDRESS_3                          PIC  X(030).
    05  PR:_ADDRESS_4                          PIC  X(030).
    05  PR:_SOURCE_INDICATOR                   PIC  X.
    05  PR:_POSTCODE                           PIC  X(006).
    05  PR:_DATE_CREATED                       PIC  S9(008).
    05  PR:_TIME_CREATED                       PIC  S9(008).
    05  PR:_DATE_TAPE_PRODUCED                 PIC  S9(008).
    05  PR:_TIME_TAPE_PRODUCED                 PIC  S9(008).
    05  PR:_RECORD_STATUS                      PIC  X.
    05  PR:_TAPE_SERIAL_NUMBER                 PIC  S9(006) USAGE IS DISPLAY.
    05  PR:_RECORD_TYPE                        PIC  X.
    05  PR:_FILLER                             PIC  X(010).

WORKING-STORAGE.
          05  WS-FHS-FILE-STATUS         PIC X(002).
              88 READ-AT-END                  VALUE "10", "46".
              88 READ-INVALID-KEY             VALUE "14", "23".
              88 START-INVALID-KEY            VALUE "23".
              88 DELETE-INVALID-KEY           VALUE "23".
              88 WRITE-INVALID-KEY            VALUE "21", "22", "24", "34".
              88 WRITE-DUPLICATE          VALUE "22".
              88 REWRITE-INVALID-KEY          VALUE "22", "23".
      
     *   For read, write and rewrite, use read-ok, write-ok and rewrite-ok
     *   respectively. For all other operations, use io-ok.
      
              88 READ-OK                      VALUE "00", "02".
              88 WRITE-OK                     VALUE "00", "02".
              88 REWRITE-OK                   VALUE "00", "02", "21".
              88 IO-OK                        VALUE "00".
              88 OPTIONAL-NOT-PRESENT         VALUE "05".
              88 RECORD-SOFTLOCKED            VALUE "90".
              88 RECORD-HARDLOCKED            VALUE "92".
              88 RECORD-LOCKED                VALUE "90", "92".

***  This is the processing routine (currently). It doesn't "work" !

PROCESS_FILE.
* Start Alternate Key

    START TIPOSTCODE_REQ
    KEY IS NOT LESS THAN PR_ALT_DBKEY
    ALLOWING UPDATERS.
    PERFORM DFDA_CALL_FHS.

    IF NOT IO-OK 
	PERFORM XC_RMS_ERROR              
    END-IF

* Read record
    READ TIPOSTCODE_REQ ALLOWING UPDATERS
    KEY IS PR_ALT_DBKEY.

    MOVE "N" TO WS_POSTCODE_REQ_FLAG 
    IF READ_OK
	PERFORM UNTIL WS_POSTCODE_REQ_FOUND OR READ-AT-END


            IF (this is the record I want)
              PROCESS...
	    ELSE
* Read next record
                READ TIPOSTCODE_REQ NEXT RECORD ALLOWING UPDATERS.

		IF NOT READ-AT-END
		   IF NOT IO-OK
			PERFORM XC_RMS_ERROR              
		   END-IF
		END-IF
	    END-IF
        END-PERFORM
    ELSE
	IF NOT READ-INVALID_KEY THEN 
	    PERFORM XC_RMS_ERROR              
	END-IF
    END-IF.

T.RTitleUserPersonal
Name
DateLines
3216.1another approachPACKED::BLATTFri Mar 14 1997 13:4013
I don't really have an answer for the code you posted, but rather
a suggestion for an alternate approach.  

Status code 02 means there's another duplicate in the series.
It seems like that could be exploited in the program logic.

If there are 3 duplicate key values, for example, the first
and second read will give you an 02 meaning "there's another one".
Reading the last one will return an 00.

-Wendy


3216.2EPS::VANDENHEUVELHeinMon Mar 17 1997 01:2724
    
    Sorry, not much time just now. Still, some hints:
    
    	- Please define 'does not work'. It is not at all clear from
    	  a quick reading of the topic what the code was expected to
    	  do and how it behaved differently in reality.
    	  Was there a run time error? 
    	  Or a hard loop against the first key selected perhaps?
    
    	> START TIPOSTCODE_REQ KEY IS NOT LESS THAN PR_ALT_DBKEY...
    	> PERFORM DFDA_CALL_FHS.
	> READ TIPOSTCODE_REQ ALLOWING UPDATERS KEY IS PR_ALT_DBKEY.
    	
    	If the procedure called does not perform a READ NEXT then
    	the START is entirely wasted. It establishes a current 
    	record, ready to be read, but the READ provides its own key
    	and Thus go for its own current record. They may want to
    	try to reply the KEY clause with a NEXT RECORD?
    	
    	hth,
    		Hein.
    

    
3216.3read alternate key with duplicates follow upCCAD14::MCCULLOCHTue Mar 18 1997 00:1176
Hi All,

Thanks for your replies so far.

To explain what the customer is hoping to do:
They have an application which stores the different possible addresses for a
customer.  ie. each customer has a mailing address,
a directory address, a contact address etc.

The primary key is the Billing Id, but the program has only got access to
the "Customer Id" ( PIC S9(9) ) which has duplicates.

So, the program wants to find the address record for a particular customer id
which has a "Source indicator" of 'S' and then possibly update it (later)
if it exists or create one if it doesn't.


I have got hold of a cut down version of the program and the data file.
I have changed the program to do as Hein suggests in .2

ie.
  START TIPOSTCODE_REQ KEY IS NOT LESS THAN PR_ALT_DBKEY...
  (Check status)
  READ TIPOSTCODE_REQ NEXT RECORD ALLOWING UPDATERS.
  (Check status)
    

Here are a list of valid customer id's which have records in the file (I know
because I can see them using Powerhouse).

    customer id
      131162
      131275

The problem is:

a) If I START with customer id = 131162, the system returns 131275 as the first
record when the first READ NEXT has executed.  (What happened to 131162 ? - it
is "NOT LESS THAN" the alternate key provided).

b) If I START with customer id = 131160 (which doesn't exist) then the
system again returns 131275 as the first record, skipping over the first record
131162 which satisfies the key condition.

Conceptually, I have difficult with the term "Next Record" after a
START, since READ NEXT RECORD after a START would seem to indicate that it
would not read Current Record (!?!) which START had found, and is what I want!
Anyway, if (.2) is correct and certainly the User Manual seems to suggest that
this is the way to do it,

Either,

1. I have overlooked something obvious.

2. There is a problem with the (old) version (V4.4) of VAX COBOL which means
that it should work but doesn't.  I have not currently got access to a
current version.

3. There is possibly a mismatch between the program's view of the file and the
actual file.  I have done an ANALYZE/RMS/FDL on the file with no obvious
problems reported.  The key offsets and size seem to match the copybook view of
the file.

BTW. If I specify 
  START TIPOSTCODE_REQ KEY IS EQUAL TO PR_ALT_DBKEY...
                           ^^^^^^^^^^^
then the program doesn't find ANY of the valid records at all !
All I get is Error 23 on the START.


Any suggestions or further comment heartily welcomed.

Thanks for your interest,

Malcolm McCulloch

3216.4More ideasPACKED::BRAFFITTTue Mar 18 1997 03:4718
>I have got hold of a cut down version of the program and the data file.
>I have changed the program to do as Hein suggests in .2
>
>ie.
>  START TIPOSTCODE_REQ KEY IS NOT LESS THAN PR_ALT_DBKEY...
>  (Check status)
>  READ TIPOSTCODE_REQ NEXT RECORD ALLOWING UPDATERS.
>  (Check status)
    
    If you put together a self-contained .COB which generates the data file
    and then tries to read it, we could try that .COB on our systems with a
    supported version of VAX COBOL (V5.4) to see if you are encountering
    a bug related to one of the many bugs fixes made since VAX COBOL V4.4.
    
    Also, VAX COBOL now has a feature /CHECK=DUPLICATES to do some
    additional validation that the way DUPLICATES is set for an input data
    file ISAM keys matches the use of DUPLICATES in the declaration of the
    file in the program.
3216.5WENDYL::BLATTTue Mar 18 1997 12:3613
>All I get is Error 23 on the START.

which says pretty clearly that the record is not in the file, which I 
think makes all the subsequent behavior expected.

>Here are a list of valid customer id's which have records in the file (I know
>because I can see them using Powerhouse).

I'm not familiar with what Powerhouse is or how it checks, but maybe the 
record is somehow corrupted or marked for deletion.

Can you regenerate the file and retry?

3216.6Bitten by overpunch?WIBBIN::NOYCEPulling weeds, pickin' stonesTue Mar 18 1997 12:4515
If you move 131162 to a PIC S9(9) field, I think it will contain

	00013116B

The "B" represents both the sign "+" and the digit "2".
Is this the form of the data in your file?  If the customer record you're
looking for is actually

	000131162

then it is less than the key you provide, and you won't find it.
(Notice that you tell COBOL the key is the group item, so it uses
character-string compare rules, not numeric compare rules ... I think.)

What happens if you declare the key to be PIC 9(9) instead of S9(9) ?
3216.7Full problem test case neededPACKED::MASLANKATue Mar 18 1997 14:3918
Re .0

The COBOL code in the base note looks reasonable. What you
have shown is not wrong in the sense that it is legal COBOL.
It should do something meaningful for the user although it 
certainly appears not to require the START step. FWIW COBOL 
programmers have been using that kind of logic ever since 
Indexed files with alternate keys became available under the 
ANSI-74 COBOL standard. 

However, as Don suggests in .4, your user may be utilizing a 
bug in VAX COBOL V4.4. If this is the case, it may be very 
difficult to decypher what was originally intended. Upgrades
sometimes run into those kinds of problems. 

I would also feel more comfortable to see a complete COBOL 
program with a symptom report that it is doing "X" under VAX 
COBOL V5.4, and it is expected to be doing "Y".
3216.8Solved!CCAD14::MCCULLOCHTue Mar 18 1997 22:0625
Hi All,

Thanks to all for their helpful replies.

But especially to the unnamed .6 who hit the nail on the head !

The copybook definition of the alternate key was PIC S9(9).
The RMS file (through the Powerhouse definition) was expecting an unsigned 9
byte key - ie character-string comparison.

Being a simple C and Pascal programmer of many years standing, and having all
of 2 month's COBOL experience, I had no idea of the effects of using a 
Signed value.  In other languages, the only difference is top-bit set !

So, after changing the PIC S9(9) to a PIC 9(9), the program "worked" perfectly!

Anyway, the customer is pleased, I am pleased and I think I have learnt a
valuable lesson:

  "Beware using PIC Signed entities in interfaces to External objects"

Thanks to all very much,

Malcolm McCulloch