ch21.bodyTEXTDmWrByymBIN Program Structures

Loop Structures

Loop Processing

There is no 'GO TO' statement in NATURAL so repetitive processing is performed by loops. Control will be returned to the statement generating the loop when the end of the logical block is reached.

Each loop initiating statement must be coded with an appropriate END statement:

READ READ WORK FIND HISTOGRAM REPEAT FOR

SORT

END-READ END-WORK END-FIND

END-HISTOGRAM

END-REPEAT END-FOR

END-SORT

Exit conditions should also be specified. ESCAPE is the most common statement used to terminate a loop while Program Function keys are often used to terminate loops in the on-line environment. The UNTIL or WHILE clause of the REPEAT is often used to terminate the loop.

READ WORK ONCE

FIND NUMBER GET
END-WORK    

These statements create single-pass loops, that is to say, they will only execute logic block
but once; only one record is accessed by a READ WORK ONCE or a GET statement
and a FIND NUMBER doesn't access data at all but provides a count of records
that meet the specified criteria and optionally, saves the list of ISNs .

SORT is a special case loop. Loops prior to the SORT are closed in order to release data to the sort process. Loops following the SORT are coded to process the output from the sort. See the SORT statement in the previous chapter.

Break Processing

A control break is simply the execution of a statement or block of statements based on a change in a control field. The AT BREAK statement in NATURAL is used to indicate the field to be tested and the statements to be executed when there is a change in that control field.

The test for control breaks are evaluated immediately after the record is read and before any detail processing takes place. Multiple AT BREAK statements may be coded. In order that the break processing is executed properly, the AT BREAKs must be coded in the reverse order of the sort of the data. If an AT END OF DATA statement is coded, it is considered the highest level break and will force all lower level breaks to be executed in order, that is, higher level breaks cause automatic execution of lower level breaks even if no change has taken place at the lower level.

NATURAL Standard System Functions are available within the AT BREAK block. Functions like AVERage, MINimum, MAXimum as well as SUM and TOTAL are available. These functions are also available within the AT END OF DATA condition.

The OLD function will provide values from the previous record, that is, the last record from the group on which totals are being reported. Remember, any database fields specified will return values from the record that caused the break.

COUNT is a function that may be specified for any field type. It counts the number of records within a break group and resets to zero before evaluating the next group of data.

Example of Break Processing

DEFINE DATA LOCAL USING JOB-LDA
* 1 JOB-SUMMARY VIEW OF EMPLOYEES
* 2 NAME
* 2 CITY
* 2 COUNTRY
* 2 SALARY(1)
* 2 JOB-TITLE
* 2 DEPT
END-DEFINE
FIND JOB-SUMMARY WITH COUNTRY = 'USA'
AND DEPT = 'COMP00' THRU 'COMP99'
END-ALL
SORT JOB-TITLE DEPT /* JOB-TITLE IS THE MAJOR SORT
USING NAME SALARY(1) /* DEPT IS THE MINOR SORT
DISPLAY DEPT NAME SALARY(1)
* Minor Break Processing
AT BREAK OF DEPT
WRITE T*DEPT COUNT(DEPT) /* COUNT OF NUMBER OF RECORDS
END-BREAK
* Major Break Processing
AT BREAK OF JOB-TITLE
WRITE T*DEPT COUNT(JOB-TITLE) /* COUNT OF POSITIONS
OLD(JOB-TITLE) /* VALUE FROM PREVIOUS RECORD
T*SALARY(1) SUM(SALARY(1)) // /* TOTAL OF SALARY FOR JOB GROUP
END-BREAK
* End of Data
AT END OF DATA
WRITE T*DEPT COUNT(JOB-TITLE) /* COUNT OF ALL PERSONNEL
T*SALARY(1) TOTAL(SALARY(1)) /* REPORT TOTAL
END-ENDDATA
END-SORT
END

The (control) break processing condition will be checked before any other processing in the loop, regardless of the physical position of the AT BREAK statement within the loop. This can cause problems if you have a REJECT statement at the top of the loop, because a rejected record can cause a break. Consider the use of BEFORE BREAK processing to avoid this problem.

Transaction Processing

Logical Transaction

A logical transaction is defined as any operation which leads to a change to the database. Only one database should be updated within a single logical transaction but many files on that database may be updated.

Hold Queue

The Hold Queue is a list of records (ISNs) internal to ADABAS which gives the user who placed the record on hold exclusive use of the record for updating or deleting. Users may still access the record but not for modification.

END TRANSACTION

This statement is issued by a program to signify the end of a logical transaction. Issuing this command has two major effects:

An END TRANSACTION statement should be issued after each change to the data base in the on-line environment. In batch, the END TRANSACTION would be more efficiently utilized by issuing the command after a predetermined number of records. As a record is read, the ISN is placed in hold status regardless of whether it is changed or not. To avoid possible Hold Queue problems, the END TRANSACTION should be issued every 25 records or a number that best suits the particular environment (see the following section on the Hold Queue).

The DATA clause of the END TRANSACTION statement may be used to store user data on the ADABAS System File to be retrieved later. The GET TRANSACTION DATA statement is used to read this stored data for restarting a program (see the section on the END TRANSACTION With DATA).

GET TRANSACTION DATA

This statement is issued to retrieve transaction data previously written to the System File by an END TRANSACTION statement. This data is tagged and retrieved by using the ETID of the person currently logged on to NATURAL. (The ETID is the "address" of the END TRANSACTION data. This has to be set to insure the correct "data" is retrieved. See NATURAL Security Profile.) The fields which define the layout of the transaction data may be A or N format. The sequence and format of the fields used must be identical to the sequence and format of the data created with the corresponding END TRANSACTION statement.

BACKOUT TRANSACTION

When issued, the BACKOUT TRANSACTION causes the current logical transaction to be abandoned. All changes applied by the current user will be undone back to the last successful END TRANSACTION. This command may be issued by a program and is also issued by ADABAS and NATURAL.

The following processes are performed when this command is issued:

Transaction processing examples:

END TRANSACTION without user data:

0000 END TRANSACTION

END TRANSACTION with user data:

0000 END TRANSACTION #W-ET-USER-DATA

Where #W-ET-USER-DATA is the user variable containing the transaction data to be used in a re-start situation.

GET TRANSACTION DATA:

0000 GET TRANSACTION DATA #W-ET-USER-DATA

Where #WT-ET-USER-DATA is the user variable containing the transaction data to be used for re-starting the transaction.

Transaction Processing in NATURAL

The NATURAL environment in this installation has been created so that all transaction processing is under 'program control'. This means that programmers are entirely responsible for defining logical transaction boundaries within the systems they write. If END TRANSACTION statements are not issued at appropriate points, then the record(s) will remain in hold status even after the program has completed execution.

Excessive use of the BACKOUT TRANSACTION command should be avoided as it causes ADABAS to do as much processing as it did applying the intended original update and this involves a large performance overhead.

If the NATURAL session should fail then the NATURAL software will automatically issue a BACKOUT TRANSACTION. If a NATURAL program abends then ADABAS will be unaware of the program failure. However, a logical transaction is only permitted to span a certain length of time. If this window of time is exceeded, then ADABAS will automatically issue a BACKOUT TRANSACTION. This condition may also be caused by a long terminal wait when a record or records are in hold status.

The Hold Queue

The effect of placing records on the hold queue is that any other program wishing to place the same record(s) in the hold queue will be unable to do so. If the second program has set GLOBALS (parameter) WH=OFF then the program being executed will abend with a NAT3145 error message otherwise the terminal will lock out until the record is released by the first program. The ON ERROR statement should be coded if retaining program control is required, i.e., instead of abending when the NAT3145 is encountered, trap the error and pass control to an error handling routine.

Always specifically code END TRANSACTION or BACKOUT TRANSACTION statements in NATURAL programs to release records from the hold queue so that logical transactions are clearly defined. At the end of an on-line or batch session which ends normally, NATURAL will issue an implicit BACKOUT TRANSACTION. Note also that a session which is ended by a TERMINATE statement is considered an abnormal end and therefore an implicit BACKOUT TRANSACTION is issued.

The size of the hold queue is set within ADABAS for each database according to the anticipated concurrent updating activity. For example:

DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'KEYNES'
AND FIRST-NAME EQ 'MILTON'
MOVE 0 TO SALARY(1)
UPDATE
END TRANSACTION
END-FIND
END

NATURAL, at compile time, checks any backward references (implicit or explicit) on UPDATE and DELETE statements to decide the type of ADABAS command to be issued. In this example, all records read by the FIND command will be placed on the hold queue as they are read one at a time. Each record therefore is held, read, updated and then released. No hold queue problems will result from the execution of this program.

DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'KEYNES'
AND FIRST-NAME EQ 'MILTON'
MOVE 0 TO SALARY(1)
UPDATE
END-FIND
END TRANSACTION
END

Problems may result from this program since the first record is held, read, updated and then the next record is held, read and updated, and so on. the records are only released when the program completes the loop processing of all records satisfying the FIND. If more records pass the WITH clause than the maximum entries available in the hold queue, then the program will lock itself out until a 'time out' condition occurs at which time all updates are backed out. Under ADABAS 5, the number of records any one user can hold is a parameter that can be set by the DBA.

* EXAMPLE 1
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'KEYNES'
WHERE FIRST-NAME EQ 'MILTON'
MOVE 0 TO SALARY(1)
UPDATE
END TRANSACTION
END-FIND
END
* EXAMPLE 2
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'KEYNES' IF FIRST-NAME EQ 'MILTON'
MOVE 0 TO SALARY(1)
UPDATE
END TRANSACTION
END-IF
END-FIND
END

Either of these programs may cause more records to be held than is necessary. Each record read is held. In the WHERE example, if the criteria is true the loop is entered and eventually the record (ISN) is released. In the IF example (Example 2), the ISN is placed in the hold queue and if it passes the IF test, is updated and then released from the hold queue. In both cases, records not processed under either condition remain in the hold queue until a record read meets the criteria, is updated and the END TRANSACTION issued releasing all currently held records.

Beware of situations in which records are not apparently processed as the result of a search-read statement evaluation but still are placed on the hold queue.

The ACCEPT and REJECT will work exactly the same way as the WHERE clause, i.e., records are held until one passes the criteria for an update and subsequent END TRANSACTION releasing held records. Avoid the use of these statements with a loop where database updating is to be performed.

* EXAMPLE 3
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'HAMILTON'
ACCEPT IF FIRST-NAME EQ 'MIKE'
MOVE 0 TO SALARY(1)
UPDATE
END TRANSACTION
END-IF
END-FIND
END
* EXAMPLE 4
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FIND EMPLOYEES-VIEW WITH NAME EQ 'HAMILTON'
IF FIRST-NAME EQ 'MIKE'
MOVE 0 TO SALARY(1)
UPDATE
END-IF
END TRANSACTION
END-FIND
END

This example should give no record holding problems since each record is held, read and then conditionally updated but always released from the hold queue whether it has been updated or not. The issuing of END TRANSACTION statements causes ADABAS to perform an appreciable amount of processing even if records to be released form the hold queue are not actually being updated.

* EXAMPLE 5
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 NAME
2 FIRST-NAME
2 SALARY(1)
END-DEFINE
FEMPL01. FIND EMPLOYEES-VIEW WITH NAME EQ 'HAMILTON'
IF FIRST-NAME EQ 'MIKE'
GEMPL01. GET EMPLOYEES-VIEW *ISN (FEMPL01.)
MOVE 0 TO SALARY(1)
UPDATE (GEMPL01.)
END TRANSACTION
END-IF
END-FIND
END

If the percentage of records read which are to be updated is low, then the above example should be followed. Once it is determined that a record is to be modified, then it is held, re-read, updated and then released.

The back reference on the update (using a label in Example 5 but line sequence numbers are also acceptable) indicates to NATURAL/ADABAS that only those records re-read MUST be held and this clearly will be done one record at a time.

Similarly, if a large number of records are to be updated, then issue an END TRANSACTION statement after a predetermined number of records have been placed in hold status by the program.

* EXAMPLE 6
*
DEFINE DATA LOCAL
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 PERSONNEL-ID
2 NAME
2 FIRST-NAME
2 SALARY(1)
1 #W-RECORD-COUNT(I2)
END-DEFINE
READ EMPLOYEES-VIEW BY PERSONNEL-ID
ADD 1 TO #W-RECORD-COUNT
MULTIPLY SALARY(1) BY 1.0675
UPDATE
IF #W-RECORD-COUNT EQ 25
END TRANSACTION
RESET #W-RECORD-COUNT
END-IF
END-READ
END TRANSACTION
END

In this example, each record in turn is held, read and then the salary is updated by 6.75%. Once twenty-five records have been processed, an END TRANSACTION statement is issued and the counter is reset to 0.

Note also the need for an END TRANSACTION after the loop process is completed since there may not have been an exact multiple of 25 records processed.

END TRANSACTION With Data

The END TRANSACTION statement enables a program to optionally supply data at the end of a logical transaction. The transaction data is held in the system and synchronized with the last completed transaction. The fields used as transaction data may be A or N format but must not exceed a total length of 2000 bytes.

This facility can be particularly useful for restart processing in the event of a system failure when work files are being used to update database files.

DEFINE DATA LOCAL
1 #W-RECORD(A80)
1 REDEFINE #W-RECORD
2 #W-PERSONNEL-ID (A8)
2 #W-NAME
2 #W-SALARY
1 EMPLOYEES-VIEW VIEW OF EMPLOYEES
2 PERSONNEL-ID
2 NAME
2 SALARY(1)
END-DEFINE
READ WORK FILE 1 RECORD #W-RECORD
FIND EMPLOYEES-VIEW WITH PERSONNEL-ID EQ #W-PERSONNEL-ID
MOVE #W-SALARY TO EMPLOYEES-VIEW.SALARY(1)
UPDATE
END TRANSACTION #W-PERSONNEL-ID
END-FIND
END-WORK
END

The above program records the most recent personnel identification number successfully updated. This may then be used if necessary to provide the value of a restart point, that is, read work file until the personnel identification number last processed is reached and then begin updating with the next record in sequence.

The transaction data is identified using the ETID of the user initiation the program an although this is not directly available for retrieval with the GET TRANSACTION statement, it does relate the processing to an individual user and not to a specific terminal.

It is possible to use [end] transaction data even if database updating is not being performed, but the method to be used is slightly different. In order to write transaction data to the system file it is necessary to issue an END TRANSACTION statement with data followed by an END TRANSACTION statement without any data.

0300 :
0310 END TRANSACTION #W-USER-DATA
0320 END TRANSACTION
0330 :

The above technique is useful if a check point is required at the end of a particular phase of processing.

GET TRANSACTION DATA

The GET TRANSACTION DATA statement is used to retrieve transaction data from the system file and is located using the ETID of the person currently signed-on to NATURAL. The fields which define the layout of the transaction data may be A or N format. The sequence and format of the fields used must be identical to the sequence and format of the data created with the corresponding END TRANSACTION statement. If no transaction data has been stored which matches the ETID of the current user then all fields in the GET TRANSACTION DATA statement will be filled with blanks regardless of their format definition. The program must always check for the presence of valid values before attempting to perform arithmetic on numeric fields else and abnormal program termination will occur.

DEFINE DATA LOCAL
1 #W-USER-DATA(N8)
1 REDEFINE #W-USER-DATA
2 #W-USER-DATA-ALPHA
END-DEFINE
GET TRANSACTION DATA #W-USER-DATA
IF #W-USER-DATA-ALPHA = ' '
WRITE 'NO TRANSACTION DATA AVAILABLE'
STOP
END-IF
:
:

The above program insures the presence of transaction data before continuing with any recovery processing.

2 key is not being modified (see READ LOGICAL later in this chapter).

If a specific sequence is desired, examine whether READ IN LOGICAL SEQUENCE BY descript Dreamweaver28A2STR d