Technical Information Database TI898D.txt Determining Record Number In A dBASE Table Category :Database Programming Platform :All Product :Delphi All Description: dBASE tables employ a fairly static record numbering system. The record number for a given record reflects its physical position in the table file. These record number are not subject to change dependent on the filtering of data or index ordering. For instance, a record that is the first record stored in the .DBF file would be record number 1. It is possible that, through the ordering of an index, this record may be displayed as the last of 100 records. In such a case, its record would remain the same -- one -- and would not be changed to 100 to reflect its position in the index ordered data set. This is in contrast with Paradox tables, where there is a sequence number. The Paradox sequence number is like the dBASE record number except that it is much more fluid and the number for a given record will reflect its position relative to the data set. That is, a record may not always have the same sequence number given filtering of the data set to reduce the number of records or when an index is active that may change the displayed order of the record. In database applications created with Delphi and the Borland Database Engine (BDE), there is no provision built into the stock data components for extracting or determining the record for dBASE tables. Such an opera- tion is, however, possible by making a call from the application a BDE function. There are a number of BDE functions that will return information about the current dBASE record, such as the record number. Basically, any function that fills a BDE pRECProps structure would suffice. Such BDE functions include DbiGetRecord, DbiGetNextRecord, and DbiGetPriorRecord. Of course, only the first of these functions really applies to retrieving information about the current record. The other two move the record pointer when in- voked, similar in effect to the Next and Prior methods of the TTable or TQuery components. The pRECProps structure consists of the fields: iSeqNum: type LongInt; specifies the sequence number of the record (relative to the data set, including filtering and index ordering); applicable if the table type supports sequence numbers (Paradox only). iPhyRecNum: type LongInt; specifies the record number for the record; applicable only when the table type supports physical record numbers (dBASE only). bRecChanged: type Boolean; not currently used. bSeqNumChanged: type Boolean; not currently used. bDeleteFlag: type Boolean; indicates whether the record is deleted; applicable only for table types that support soft-deletes (dBASE only). One of these BDE functions may be invoked in a Delphi application to fill this structure, from which the physical record number may be retrieved. Below is an example of the DbiGetRecord function used for this purpose. function RecNo(ATable: TTable): LongInt; var R: RECProps; rslt: DbiResult; Error: array [0..255] of Char; begin ATable.UpdateCursorPos; rslt := DbiGetRecord(ATable.Handle, dbiNoLock, nil, R); if rslt = DBIERR_NONE then Result := R.iPhyRecNum else begin DbiGetErrorString(rslt, Error); ShowMessage(StrPas(Error)); Result := -1; end; end; As with invoking any BDE function in a Delphi application, the BDE wrapper units DbiTypes, and DbiErrs, DbiProcs must be included in the Uses section of the unit in which the BDE function will be invoked (the Uses section not shown here). To make this function more transportable, it does not reference the subject TTable component directly, but a reference to the TTable is passed as a parameter. If this function is used in a unit that does not reference the Delphi units DB and DBTables, they must be added so that references to the TTable component will be valid. The UpdateCursorPos method of the TTable is called to ensure that the record number current in the TTable component is synchronized with that of the underlying table. BDE functions do not in themselves cause an exception if they fail. Rather, they return a value of BDE type DbiResult that indicates the succ- ess or failure of the intended operation. This return value must then be retrieved and evaluated by the front-end application, and the appropriate action taken. A result other than DBIERR_NONE indicates an unsuccessful execution of the function. An extra step may be taken (as in the example above) to query the BDE to translate an error code into a readable mess- age with the BDE function DbiGetErrorString. In this example, the return value from the invoking of DbiGetRecord is stored in the variable rslt, and then compared against DBIERR_NONE to determine the success of the function call. If the call to DbiGetRecord succeeds, the physical record number from the iPhyRecNum field of the pRECProps structure is stored to the variable Result, which is the function's return value. To indicate when the function has failed (i.e., the involing of the DbiGetRecord function failed), a value of negative one is returned instead of the record number. This value is purely arbitrary, and any value of a compatible type may be used at the discretion of the programmer. Reference: 7/16/98 4:33:56 PM
Last Modified: 01-SEP-99