Access a table indirectly

The application will access the appropriate rate table indirectly. This feature of tableBASE is called Open Indirect (see Open Indirect).

Open Indirect causes a table to be searched for a target secondary table name. This secondary table is the one that will be opened if the search of the primary table is successful. The primary or first table may not be read password protected. The first table has only two fields:

TARGET-TABLE-NAME (8 bytes)

INDIRECT-OPEN-CRITERION (up to 50 bytes)

The second field is the key of the first table. For example, each key field might represent a date when the target rate table in TARGET-TABLE-NAME is to go into effect. The Set Indirect (SI) command is used to provide the processing date that becomes the search argument for the primary table. A search of the primary table is successful if the search argument is equal to a row-key, or is greater than one row-key, and less than the next row-key, of the primary table. After a successful Indirect Open operation, the target table name is placed in the TABLE field of the COMMAND-AREA, and the error code is 0. The FOUND code is N, whether the search was successful or not.

Abend processing will be suppressed in this example, so all calls to tableBASE must be followed by a test of the error code.

In COBOL
 DATA DIVISION.
 01  INPUT-RECORD.
   05  .....
   05  INPUT-PROCESSING-DATE            PIC X(8).
   05  INPUT-CODE .....
   
 01  STATUS-SWITCHES.
   05  ST-ABEND                         PIC X.
   05  FILLER                           PIC X(7) VALUE SPACES.
   
 01  RATE-ROW.
   05  RATE-CODE.....
   05  RATE-VALUE....
   
 01  RATE-COMMAND-AREA.
   05  RATE-COMMAND                     PIC XX    VALUE SPACES.
   05  RATE-TABLE                       PIC X(8)  VALUE SPACES.
   05  RATE-FOUND                       PIC X     VALUE SPACES.
   05  RATE-INDIRECT-IND                PIC X     VALUE LOW-VALUES.
   05  RATE-RESERVED                    PIC X     VALUE LOW-VALUES.
   05  RATE-ABEND-OVERRIDE              PIC X     VALUE SPACES.
   05  RATE-ERROR-CODE                  PIC S9(4) COMP VALUE +0.
   05  RATE-COUNT                       PIC S9(9) COMP VALUE +0.
   05  RATE-LOCK                        PIC X(8)  VALUE SPACES.
   05  RATE-LENGTHS.
       10  RATE-ROW-OVERRIDE-LENGTH     PIC S9(9) COMP VALUE +0.
       10  RATE-ROW-ACTUAL-LENGTH       PIC S9(9) COMP VALUE +0.
       10  RATE-FG-KEY-LENGTH           PIC S9(4) COMP VALUE +0.
   05  RATE-FUNCTION-ID                 PIC S9(4) COMP VALUE +0.
   05  RATE-FUNCTION-AREA.
       10  RATE-DATE                    PIC X(8).
       10  FILLER                       PIC X(20).
   05  RATE-RETURNED-ABS-GEN-NO         PIC S9(4) COMP VALUE +0.
   05  RATE-ERROR-SUBCODE               PIC S9(4) COMP VALUE +0.
   
***
*    THE FOLLOWING IS A COPY OF CONTENTS OF PRIMARY RATETBL.
*    IT IS PRESENTED HERE ONLY TO COMPLETE THE UNDERSTANDING
*    OF TABLEBASE WHEN PROCESSING THE PRIMARY RATETBL.
***

 01  RATETBL-PRIMARY-ROW.
   05  RATETBL-SECONDARY                PIC X(8)  VALUE 'RATE2000'.
   05  RATETBL-KEY                      PIC X(8)  VALUE '20000101'.
   
 PROCEDURE DIVISION.
 HOUSE-KEEPING.
 
***  TURN OFF TABLEBASE ABEND FUNCTION.
     MOVE 'N' TO ST-ABEND
     MOVE 'CS' TO RATE-COMMAND
     CALL 'TBLBASE' USING TB-PARM
                          RATE-COMMAND-AREA
                          STATUS-SWITCHES
						  
***  GET TODAY'S DATE AND MOVE IT TO INPUT-PROCESSING-DATE
***  SET UP VALUE TO BE USED FOR INDIRECT TABLE OPEN

     MOVE 'SI' TO RATE-COMMAND
     CALL 'TBLBASE' USING TB-PARM
                          RATE-COMMAND-AREA
                          INPUT-PROCESSING-DATE
     IF RATE-ERROR-CODE GREATER THAN ZERO
       GO TO TABLEBASE-ERROR-RTN
     END-IF
***  OPEN INDIRECT TABLE.

     MOVE 'I' TO RATE-INDIRECT-IND
     MOVE 'RATETBL' TO RATE-TABLE.
     MOVE 'OR' TO RATE-COMMAND
***
*    THE PRIMARY RATE IS SEARCHED USING TODAY'S DATE AS A KEY.
*    SINCE IT IS GREATER THAN 20000101, THE ONLY ENTRY IN THE
*    PRIMARY TABLE IS FOUND AND THE NAME 'RATE2000' IS PLACED
*    IN THE RATE-COMMAND-AREA BY TABLEBASE AND IS OPENED READY FOR
*    FURTHER PROCESSING.
***

     CALL 'TBLBASE' USING TB-PARM
                          RATE-COMMAND-AREA
     IF RATE-ERROR-CODE GREATER THAN ZERO
        GO TO TABLEBASE-ERROR-RTN
     ENDIF
 GET-RECORD.
 
*      (get input record)

 PROCESS-ROW.
     MOVE 'FK' TO RATE-COMMAND
     CALL 'TBLBASE' USING TB-PARM
                          RATE-COMMAND-AREA
                          RATE-ROW
                          INPUT-CODE
     IF RATE-ERROR-CODE GREATER THAN ZERO
        GO TO TABLEBASE-ERROR-RTN
*      (correct rate table for processing date will be used)
     END-IF
In C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dkh.h"

/*
 *  DK1TEX9C
 *
 *  Access a Table Indirectly.
 *
 *  The primary table contains the names of the secondary
 *  tables (to be open indirectly) and a key used to make
 *  the selection. A row of this primary table might be
 *  expressed with this C struct:
 *
 *  typedef struct
 *  {
 *     char tblname_secondary [8];
 *     char selection_criteria [20];
 *  } PrimaryRow;
 *
 *  The precise table that will be open indirectly is the
 *  one with the largest kyt equal to or less than the value
 *  specified in the selection_criteria field.
 */
 
/*
 * Assume these are user inputs.
 */
static char szTableName[6] = "AARON";
static char szStatus[6] = "NYYYN";
static char szIndirectOpenCriterion[11] = "2003-04-21";
static char szReadPassword[2] = " ";
static int nGen = 0;
static int nRowSize = 20;
static int nKeySize = 5;
static int nKeyLocation = 1;

int main(void)
{
    TbParmStruct tbParm;
    TbCommandAreaStruct tbCommArea;
    char sReadPassword[8];
    char sStatus[8];
    char sTableName[8];
    char sIndirectOpenCriterion[50];
    int nGeneration = nGen;
    char * pRowArea = NULL;

    /*
     * Initialize the parameters.
     */
    fixStringLength( szTableName, sTableName, 8 );
    InitTbParm( &tbParm );
    InitTbCommandArea( &tbCommArea, sTableName );
    
    /*
     * Initialize tableBASE with CS, ChangeStatus.
     */
    fixStringLength( szStatus, sStatus, 8 );
    memcpy( tbCommArea.tbCommand, "CS", 2 );
    TBLBASE( &tbParm, &tbCommArea, sStatus );
    if( tbCommArea.tbError != TB_SUCCESS )
    {
        printf( "CS\n");
        printf( "Found code: %c\n", tbCommArea.tbFound );
        printf( "Error code: %d\n", tbCommArea.tbError );
        printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
        return tbCommArea.tbError;
    }
    
    /*
     * Setup the indirect open with SI.
     */
    fixStringLength( szIndirectOpenCriterion,
       sIndirectOpenCriterion, 50 );
    memcpy( tbCommArea.tbCommand, "SI", 2 );
    TBLBASE( &tbParm, &tbCommArea, sIndirectOpenCriterion );
    if( tbCommArea.tbError == TB_SUCCESS )
    {
        /*
         * Open the indirect table (the tbCommArea.tbTable field
         * was set to the primary table previously).
         * If the key (selection criteria) is found (or the greatest key
         * less than the criteria is found), the corresponding table
         * will be open and the field tbCommArea.tbTable will be
         * updated with the actual name of the open table.
         */
        fixStringLength( szReadPassword, sReadPassword, 8 );
        memcpy( tbCommArea.tbCommand, "OR", 2 );
        tbCommArea.tbIndirectOpen = 'I';
        TBLBASE( &tbParm, &tbCommArea, sReadPassword, nGeneration);
        if( tbCommArea.tbError == TB_SUCCESS )
        {
            /*
             * Get the first row (GF).
             */
            pRowArea = (char *) malloc( nRowSize + 1 );
            if( pRowArea == NULL )
               return TB_ERROR;
            memset( pRowArea, ' ', nRowSize );
            
            fixStringLength( szReadPassword, sReadPassword, 8 );
            memcpy( tbCommArea.tbCommand, "GF", 2 );
            TBLBASE( &tbParm, &tbCommArea, pRowArea );
            if( tbCommArea.tbError != TB_SUCCESS )
            {
                printf( "GF\n");
                printf( "Found code: %c\n", tbCommArea.tbFound );
                printf( "Error code: %d\n", tbCommArea.tbError );
                printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
                free( pRowArea );
                return tbCommArea.tbError;
            }
            
            /*
             * Print the output.
             */
            pRowArea[nRowSize] = '\0';
            printf( "Row: %s\n", pRowArea );
            
            /*
             * Close the table (CL).
             */
            memcpy( tbCommArea.tbCommand, "CL", 2 );
            TBLBASE( &tbParm, &tbCommArea );
            if( tbCommArea.tbError != TB_SUCCESS )
            {
                printf( "CL\n");
                printf( "Found code: %c\n", tbCommArea.tbFound );
                printf( "Error code: %d\n", tbCommArea.tbError );
                printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
                return tbCommArea.tbError;
            }
        }
    }
    else
    {
        printf( "SI\n");
        printf( "Found code: %c\n", tbCommArea.tbFound );
        printf( "Error code: %d\n", tbCommArea.tbError );
        printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
        return tbCommArea.tbError;
    }
    
    if( pRowArea != NULL )
        free( pRowArea );
        
    return TB_SUCCESS;
}