Page History
...
Btree.Read reads a node of an indexed file (a ! or bang file) into a dimensioned array. It can be called in the Char event of a window to return an entry in the ! file (such as the next entry starting with a character of group of characters) without having to perform an index read, as a Btree.Extract call would. See the example below.
...
Caution: Both of these techniques could result in your program missing records or in your program processing the same record twice.
See also
Btree.Extract, Extract_SI_Keys, IXLOOKUP event, Update_Index, Collect.IXVals()
Example: Traversing the Index
Code Block |
---|
/* This program searches the CUSTOMER_NAME_XREF index using BTREE.READ and returns all records that have an indexed value between "CASH" and "THOMPSON". */ DECLARE SUBROUTINE BTREE.READ, FSMSG EQU TRUE$ TO 1 EQU FALSE$ TO 0 EQU NULL$ TO "" DIM I_RECORD(5) MAT I_RECORD = NULL$ I = NULL$ SEP = NULL$ FOUND = NULL$ I_FILEVAR = NULL$ FIELD = "CUSTOMER_NAME_XREF" VALUE = "CASH" MAX_VALUE = "THOMPSON" /* Get the sort information from the index.*/ SORT_METHOD = XLATE("!CUSTOMERS", FIELD, 1, "X") OPEN "!CUSTOMERS" TO INDEX_FILE ELSE FSMSG() return 1 END OPEN "CUSTOMERS" TO CUSTOMER_FILE ELSE FSMSG() RETURN 2 END LOCKED = FALSE$ LOOP LOCK INDEX_FILE, FIELD:"*ROOT" THEN LOCKED = TRUE$ END UNTIL LOCKED REPEAT BTREE.READ(INDEX_FILE,FIELD,VALUE,SORT_METHOD,MAT I_RECORD,I,SEP,FOUND) /* Find the starting position in the key list in element five of the index leaf record. */ IF I > 1 THEN POS = INDEX(I_RECORD(5), @VM, I-1) + 1 END ELSE POS = 1 END FLAG = NULL$ DONE = FALSE$ LOOP /* Get the next key to process */ REMOVE @ID FROM I_RECORD(5) AT POS SETTING FLAG READ @RECORD FROM CUSTOMER_FILE, @ID THEN GOSUB PROCESS_RECORD END IF FLAG = 3 THEN /* REMOVE sets FLAG to 3 when a value mark is found. Finding a value mark indicates the indexed value has changed. */ IF I_RECORD(4)<1,I> > MAX_VALUE THEN /* No more valid values to process. */ DONE = TRUE$ END END ELSE IF FLAG ELSE /* If flag = 0 then we have reached the end of the current leaf record and it is time to read the next record or stop. */ IF I_RECORD(2) THEN /* There is a pointer to another record. */ MATREAD I_RECORD FROM INDEX_FILE, I_RECORD(2) THEN /* Start at the beginning of the list of keys in the new record.*/ POS = 1 I = 1 END ELSE /* Recovery logic goes here if you're not locking the index. */ DONE = TRUE$ END END ELSE /* There are no more index records. */ DONE = TRUE$ END END END UNTIL DONE REPEAT UNLOCK INDEX_FILE, FIELD:"*ROOT" ELSE FSMSG() return 4 END return 0 PROCESS_RECORD: /* Logic to process records goes here. */ RETURN RETURN 0 |
Example: In the Char Event
Code Block |
---|
/* The following code, in the Char event of an edit control called CITY, returns the name of the city closest to the letter entered by the user, in the CITY control. The program assumes that the CITY column in the CUSTOMERStable has a BTree index.*/ declare subroutine btree.read , set_property dim node(5) column = 'CITY' entered_data = get_property( @window : '.CITY','TEXT') open '!CUSTOMERS' TO vBangCustomers Then ReadV SortOrder from vBangCustomers, column, 1 Then pos = 0 separator = '' found = 0 call btree.read(vBangCustomers, column, entered_data, sortOrder, mat Node, Pos, separator, found) returned_data = node(4)<0,pos> returned_keys = node(5)<0,pos> set_property( @window : '.CITY', 'TEXT', returned_data) end end RETURN 0 |
...