|
Purpose |
Reads a record from the database | |||||||||||||||||||||||||
|
Old name |
#define fetch rec_fetch | |||||||||||||||||||||||||
|
Syntax (CCOWN) |
int rec_fetch(int flags, short *datarec, int index, int role,ADDITIONAL) | |||||||||||||||||||||||||
|
Syntax (DP4DBAPI) |
BOOLEAN dp4_rec_fetch(DCONN * dconn,short * datarec, int flags,int index,int index_role, int match_keys); | |||||||||||||||||||||||||
|
Parameters |
DCONN * dconn |
Handle to database connection | ||||||||||||||||||||||||
|
|
int flags |
This parameter determines the search method used. This parameter is formed from a combination of at least one direction flag, and zero or more other flags, as explained in the following tables: Direction Flags
In calls to rec_fetch() itself you will generally only pass one direction flag, though the combinations of EQUAL|NEXT and EQUAL|PREV are meaningful: they return a matching record if there is one, or the nearest record in the appropriate direction otherwise. When you call a block or buffered fetch function two other combinations are also meaningful: FIRST|NEXT and LAST|PREV. It should be noted that searching forwards through an index is slightly faster than search backwards, though both are efficient. All the five basic direction flags apart from the EQUAL flag can be modified with the BUT and DEPTH flags, as explained in the next section. FIRST,LAST and EQUAL fetches are called terminal fetches: presented with the same intiial record and other parameters the database manager will always return the same record. NEXT and PREV searches are different ("no terminal"), because the record returned by a call to a fetch function may be different according to what records have been fetched previously. The record to be found depends on the find list, which stores an extra hidden key component for every record on the database, known as its sequence number or row identifier. When doing a NEXT or PREV search the row identifier of the record previously fetched to that table/memory address combination is used as the extra key component. When accessing records using the primary index, NEXT and PREV searches are effectively also terminal, because the database manager ignores the find list since there can be only one record with a given key. But for a secondary index the find list is not ignored unless NO_FINDLIST is specified. Where a secondary index is non-unique a fetch using a PREV or NEXT value on a record area that has been modified since it was last used for a fetch() will have indeterminate results: If you set the key fields for a record when using a secondary index, you should always perform one of the three "terminal" fetches before embarking on a sequence of NEXT or PREV fetches to read further data. Even if the secondary index is unique you may still encounter unexpected results if you do a NEXT or PREV search with a changed key: the database manager treats such a secondary index like any other secondary index, and uses the find list information - a fetch NEXT or PREV with a changed key might or might not find a matching record depending on the relative values of the row identifier of the matching record and the row identifier in the find list. Direction Modifier flagsThere are two main direction modifier flags: DEPTH and BUT. The DEPTH flag instructs the database manager to respect the match_keys (or depth) parameter: any records returned will have a key matching at least as many leading keys as were specified in the match_keys parameter, so that NEXT,PREV,FIRST, and LAST searches are all relevant to the subset of records determined by the contents of the datarec parameter and the match_keys parameter. In the CCOWN implementation of fetch functions you must specify the DEPTH flag explicitly if you want to pass a non zero match keys parameter. Conversely, in the DP4DBAPI implementation, since you have to pass match_keys anyway, the DEPTH flag is added automatically if you specify a non zero value for match_keys. The BUT modifier instructs the database manager to match the number of keys specified in the index properties. For a secondary index this is always all the keys. For the primary index it is the number of keys in the prime parent if there is one, or all the keys otherwise. Since the number of keys the BUT value matches might change if the database structure is changed, most DP4 programmers prefer to specify an explicit match_keys parameter rather than relying on this flag. For historical reasons, the DP4 C include files define all the various possible combinations of direction and modifier flags explicitly, so you can use FIRST_DEPTH, NEXT_BUT and so on, as well as FIRST|DEPTH NEXT|BUT. The two forms are identical in effect in every case. In theory you can also specify NO_FINDLIST as a direction modifier. This causes the stored find list position to be ignored and for an "impossible" sequence number to be used, so that a NEXT or PREV record would always find a record with a different key from the one initially passed in. This might be useful if you were implenenting some kind of "select distinct" functionality, but is rarely if ever used in practice. Other flagsThe following values may also be added to the parameter flags:
|
||||||||||||||||||||||||
|
|
short* datarec |
Pointer to the L field of a database record to be fetched. LIBMAKE is used to declare suitable variables to be used as record areas for fetch() functions to work with. | ||||||||||||||||||||||||
|
|
int index |
Index number of the index used. You can use the #index toggle of LIBMAKE to generate suitable constants for both the index and role parameters | ||||||||||||||||||||||||
|
|
int role |
Role number of the index used | ||||||||||||||||||||||||
|
|
int match_keys |
Number of keys to match when doing a FIRST,LAST,NEXT or PREV fetch(). For the CCOWN API this parameter is optional, and you must pass DEPTH as one of the flags for it to be respected. In DP4DBAPI you must pass this parameter, and should pass 0 if you do not want to limit the search to matching keys at all. | ||||||||||||||||||||||||
|
Description |
rec_fetch() is the most general function for fetching database records one at a time, as it allows you to specify a search index unlike rec_fetch_main() which always uses the primary index. If you want to process several records table sequentially, for example in report programs, then you should use buffered fetch functionality to read the database. | |||||||||||||||||||||||||
|
Return values |
Returns whether the read was successful or not | |||||||||||||||||||||||||
|
See also |
||||||||||||||||||||||||||
|
Example |
This is the same as:
and
| |||||||||||||||||||||||||
As explained above, when searching on a secondary index, the database manager uses an extra key component, to remember where in a sequence of identical keys the search has got to. You may sometimes need to do some kind of recursive search on a secondary index, to enumerate a complete bill of materials for instance.
You may wonder how the find list can keep track of the search position in this case. In order for the searches to proceed as expected you must do one of two things: