Accessing data by key
Reading data by key is a good mean in order to position the property on a certain instance, which can be identified by key. Keys are returned to the caller and passed to the functions in an internal Key object. Usually, keys are passed in ESDF format (component values separated by '|', ';' or tab), but might be passed also in other formats (XML, OIF) as described in "Using keys".
The structure of a key depends on the sort order for the collection. When no sort order has been selected (unordered collection), instances are located by identifying key. When an unordered collections is not unique, it cannot be accessed by key.
Accessing data by key requires, that the application can provide a key for selecting an instance in a property handle. Therefore, several functions for accessing keys are provided. When a key became available, different functions can be used in order to select an instance for the key.
Since keys may consist of several key components, keyed access supports key levels. A key level is the component number in the key, up to which key matching is requested.
When accessing a collection by position, instances are provided in order of the selected index (access key). ODABA supports defining any number of persistent or transient indices (orders) for extents and local collections in the data model. Typically, those index definitions are referred to as access key for a collection.
In order to select an access key that differs from the default order for the collection (main order), changeAccessKey() can be called with an appropriate key name.
Property persons(obh,"Persons",PI_Read);
persons.changeAccessKey("ik_Name"); // schema order
The feature of defining ad-hoc orders is planned, but has not yet been implemented.
There are several property handle functions and properties provided in order to access and compare keys. Most key access functions (except metadata functions) require a selected instance in the property handle.
Key values can be extracted from the instance selected in the property handle by calling key() with the name of the key definition. Keys might also be extracted by its role.
Thus, the key value for the currently selected order key can be extracted calling accessKey(). In order to extract the primary key value, which might differ from the access key value, one may call primaryKey(). In order to get the proper primary key value for the selected instance in a weak-typed collection, currentKey() might be called (getter functions).
In order to "rename" an object instance, the corresponding setter functions might be called (e.g. accessKey(sNewKey)). This corresponds to changing the attribute values key components are referring to.
void ListKeyValues ( Property &person ) {
person.top();
while ( person.next(true) ) {
printf("primary key: %s - ", person.primaryKey());
printf("access key: %s\n", person.accessKey());
}
}
In order to select in instance from a collection by means of a key value, the proper access key has to be set for the property. Instances can be located or selected by passing a key value. In order to locate an instance by key value, locateKey() might be called. In order to read an instance by key, get() or tryGet() can be used.
Get functions always perform an exact key search, i.e. an instance with the key as passed to the function is searched. The functions fail, when no such instance exist. locateKey() allows looking for the key passed to the function and locates an instance with this or the next higher key value. In order to locate the key value exactly as being passed to the function, an exact option can be passed to the function.
nextKey() and previousKey() allow iterating through a collection returning the key values. Since those function trow an exception when reaching the end, the count or relative count should be used in order to avoid exceptions. When not passing a key level or an offset key, those functions work similar to next() and previous(), which could be used instead.
... fragment ( Property &person ) {
if ( person.locateKey("Miller|Mary",true) ) // exactly locates the key
person.get();
}
... fragment ( property &person ) {
int count = person.relativeCount();
person.top();
while ( count-- )
printf(nextKey());
}
Keys consisting of more than one component can be browsed by component levels. In order to force key function to return or locate the instance with the next key value on a certain component level, you may call nextKey(), previousKey() or locateKey() by passing a component level (see previous topic).
You may also fix a number of key components in order to select instances starting with a specific key value, only. Fixed key components are equivalent to a filter but are faster than filtering data.
In order to fix key components, you may call fixKeyComponents().
... fragment ( Property &person ) {
changeAccessKey("sk_name");
person.fixKeyComponents("Miller",1);
while ( person.next(true) ) (( selects all persons with name 'Miller'
printf("%s\n",person.value("first_name").toString());
}