Rebuilding Relational Indexes Using R/BASIC

Published ByDateVersionKnowledge LevelKeywords
Revelation Technologies18 SEP 19912.1XEXPERTINDEXES, INDEXING, RELATIONAL, RBASIC, R/BASIC, INDEX.REBUILD.SUB

Technical Bulletin #73 documents a method of rebuilding indexes from within an R/BASIC program. This method consists of creating a special "rebuild all" index transaction and placing it in the index transaction file either !INDEXING, or in Advanced Revelation 2.1 and higher, the !file itself.

The documentation in Technical Bulletin #73 covers only Btree indexes, and by extension, Cross Reference indexes. Relational indexes were not addressed. However, only minor changes are required to accommodate Relational indexes. Those changes are described below. Code for a modified version of the code in Technical Bulletin #73 appears in Figure 1.

Broadly speaking, there are three changes to the code:

  1. Add an argument by which the type of the index to be rebuilt (Btree or Relational) can be passed.
  2. Expand the error checking for the index so that it looks for Relational as well as Btree indexing.
  3. Put different information into the "rebuild all" index transaction depending on the type of the index to be rebuilt.

If you wish to use a single subroutine to handle all types of index rebuilds, you must pass into the routine the index type (Btree or Relational). You can do this by passing an extra argument to the subroutine for the type, which will allow you to determine where to do special processing to accommodate relational indexing.

This change affects the calling syntax for this program. The new syntax is:

CALL INDEX.REBUILD.SUB(FILE,INDEX,TYPE)

where type can be "B" (Btree) or "R" (Relational).

When you rebuild a Btree index, you can check to see if the field is indexed by looking for a flag in field 6 of the dictionary record. To check for relational indexing, check field 23 – if there is something there, the field is relationally indexed.

Field 23 is not a simple true/false flag. Instead, it is a specification for the target file, target field, and sort order of the index in this format:

target_file*target_field*sort

The "sort" specification is of the form BOT, AR, etc., as entered when the index was established. This entire specification is used when building the index token (see below).

Because you may need to look in different places in the dictionary record (depending on the type of index you are rebuilding) the program extracts the entire dictionary record rather than just field 6 before doing its error checking.

Field 3 of the "rebuild all" index token for a Btree index is simply the index name. For a relational index, however, this field should contain instead the entire index specification as found in field 23 of the dictionary record (see "Index Flags" above).

In the program, the third field of the token is made dependent on the index type. The value for the third field is assigned as part of the error checking for valid index types (see "Checking for Indexing", above).

The changes discussed above are all found in Figure 1. Other changes have been made as well, some of which do not directly address relational indexing. All changes are marked in bold in Figure 1. This is a summary of the changes since Technical Bulletin 73:

  1. Accepts an argument type (B or R) to indicate the type of index to be rebuilt.
  2. Incorporates an additional error value for STATUS( ) to indicate a bad index type (not B or R). Provides separate error codes for non-existent and non-indexed fields.
  3. Checks that arguments have been passed with a value (aborts if not). This guards against the possibility that the routine is called with an uninitialized variable as one of the arguments.
  4. Does error checking against the index type passed into the routine.
  5. Uses more sophisticated checking to make sure that the nominated field exists and that it is indexed according to the type requested.
  6. Skips the creation of the file_spec parameter for the rebuild token unless the token is being built for a Btree rebuild in versions previous to 2.1.
  7. Builds the third field of the "rebuild all" token according to the type of the index being rebuilt.

Figure 1

SUBROUTINE INDEX.REBUILD.SUB(FILE_NAME,INDEX,TYPE)

* desc: modified version of code in TB73. Handles relational
* indexes in addition to btree indexes.
*---------------------------------------------------------------------------
* index types are:
*
* B = Btree (includes Xref by specifying the .XREF suffix)
* R = Relational
*
* error return codes in STATUS()
*
* 0 = everything ok
* 1 = !INDEXING or !file_name (2.1+) not available
* 2 = "file_name" is not available
* 3 = "index" is not a field name in "file_name"
* 4 = "type" is not a valid indexing type (B or R)
* 5 = "index" is not an indexed field
*
*-------------------
* init

EQU TRUE$  TO 1
EQU FALSE$ TO 0

* error return codes for STATUS()
EQU OK$               TO 0
EQU NO_BANG_INDEXING$ TO 1
EQU BAD_FILE$         TO 2
EQU BAD_INDEX$        TO 3
EQU BAD_TYPE$         TO 4
EQU NOT_INDEXED$      TO 5

DECLARE SUBROUTINE DELAY
DECLARE FUNCTION GETCONFIGURE, UNASSIGNED

IF UNASSIGNED(FILE_NAME) THEN
  STATUS() = BAD_FILE$
  RETURN
END

IF UNASSIGNED(INDEX) THEN
  STATUS() = BAD_INDEX$
  RETURN
END

IF UNASSIGNED(TYPE) THEN
  STATUS() = BAD_TYPE$
  RETURN
END

STATUS() = OK$ ; * assume ok
*-------------------
OPEN FILE_NAME TO T$FILE ELSE
  STATUS() = BAD_FILE$
  RETURN
END

* check type
TYPE = TYPE[1,1]
CONVERT @LOWER.CASE TO @UPPER.CASE IN TYPE
IF INDEX('BR',TYPE,1) ELSE
  STATUS() = BAD_TYPE$
  RETURN
END

* check for valid field name and index type
DICT_REC = XLATE("DICT.":FILE_NAME, INDEX, '', "X")
BEGIN CASE
  CASE DICT_REC = ''
    * no such field
    STATUS() = BAD_INDEX$
  CASE TYPE = 'B'
    BTREE_FLAG = DICT_REC<6>
    IF BTREE_FLAG THEN
      * for Btree indexes, field name is used in token
      INDEX_TOKEN = INDEX
    END ELSE
      STATUS() = NOT_INDEXED$
    END
  CASE TYPE = 'R'
    RELIX_FLAG = DICT_REC<23>
    IF RELIX_FLAG THEN
      * for Relational indexes, full index spec in put into token
      INDEX_TOKEN = RELIX_FLAG
    END ELSE
      STATUS() = NOT_INDEXED$
    END
  CASE 1
    * undefined error
    STATUS() = BAD_TYPE$
END CASE

IF STATUS() THEN RETURN
*-------------------
* get version number
TWO_ONE = FALSE$
CONFIG = NULL$
IF GETCONFIGURE( CONFIG ) THEN
  VERSION = CONFIG< SYSTEM.LEVEL$>
  IF VERSION >= 2.1 THEN
    TWO_ONE = TRUE$
  END
END

IF TWO_ONE THEN
  BANG_FILE_NAME = '!':FILE_NAME
END ELSE
  BANG_FILE_NAME = '!INDEXING'
END

OPEN BANG_FILE_NAME TO BANG_INDEXING_FILE ELSE
  STATUS() = NO_BANG_INDEXING$
  RETURN
END
*-------------------
* build token

FILE_SPEC = ''
IF TYPE EQ 'B' AND VERSION < "2.1" THEN
  * build index name/volume string out of information in FILES and VOLUMES
  VOLUME_NAME  = XLATE("FILES", FILE_NAME, 1, "X")
  ACCOUNT_NAME = XLATE("FILES", FILE_NAME, 3, "X")
  VOLUME_LABEL = XLATE("VOLUMES", VOLUME_NAME, 1, "X")
  FILE_SPEC    = FILE_NAME:"*":ACCOUNT_NAME:"*":VOLUME_LABEL
END

TOKEN = ''
TOKEN<1> = FILE_SPEC
TOKEN<2> = 1 ; * no of 'transactions' to accomplish for this file
TOKEN<3> = INDEX_TOKEN ; * field name -or- relational specification
TOKEN<4> = "%%ALL.IDS%%" ; * actual rebuild/clear token
TOKEN<5> = "" ; * trailing fms are important
TOKEN<6> = ""
TOKEN<7> = ""

* if on 2.1+, the 1st 2 fields of the token are no longer used
IF TWO_ONE THEN
  TOKEN = DELETE( TOKEN, 1, 0, 0)
  TOKEN = DELETE( TOKEN, 1, 0, 0)
END
*-------------------
* place token as last transaction in 0 record in !INDEXING or !file_name
LOCKED_FLAG = FALSE$
LOOP
  LOCK BANG_INDEXING_FILE, "0" THEN LOCKED_FLAG = TRUE$
UNTIL LOCKED_FLAG
  DELAY(2)
REPEAT

* place rebuild token at the end of the 0 record
READ ZERO_REC FROM BANG_INDEXING_FILE, "0" THEN
  IF ZERO_REC[-1,1] NE @FM THEN ZERO_REC := @FM
END ELSE
  ZERO_REC = '0' : @FM
END

ZERO_REC := TOKEN
WRITE ZERO_REC ON BANG_INDEXING_FILE, "0"
UNLOCK BANG_INDEXING_FILE, "0"
RETURN
  • tips/revmedia/r91.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1