![]() | An Object-Oriented Database V. 0.1 Mail to: ODB for Win 95 / NT | ![]() |
The query interface is a stream based query interface. In a stream based query interface the application opens a stream from which objects can be retrieved one by one until no more objects are returned. Thus, no materialization of the entire set of object that may constitute the result of some query occurs. The basic operations on streams are:
Open streams may be reset which means that their state is changed to some initial state. In order to redo a query this is a useful feature that saves the application from having to open and combine some new streams to redo the same query.
Streams which will not be used any more may be closed. Closing a streams means it cannot be reused and any reference to any stream which is closed must not be reused.
There are three different types of streams:
Select streams are opened over another stream to select only those objects that satisfy a condition that is defined with the select stream.
Semi-join streams are opened over two other streams. The semi join stream returns those object from the left operand stream for which there exists an object in the right operand stream that satisfy some condition defined over the two streams.
Streams are opened by sending a message to the database object. The return value is either a reference to the new stream or NULL if the operation was successful or failed, respectively. In this section stream handles and open stream statements are explained.
There are three C++ types that may be used to declare stream handles. A handle, q_strm, to a query_stream is declared as:
ODB_QSTREAM q_strm;A declaration of a select stream, s_strm, handle is:
ODB_SSTREAM s_strm;And for a semi-join stream the handle, sj_strm, is declared as:
ODB_SJSTREAM sj_strm;
Query streams are opened over some type. This means that the stream accesses the objects that are instances of the type, the type extent, and the instances of its subtypes.
For example, in this figure, if a query stream is opened over the type named Person then all objects of type person and of the type named Employee will be considered as possible objects to output.
A query stream can be opened over a type named Employee as:
My_DB.open_stream("Employee");This stream will retrieve every object in the extent of type Employee and in the extent of all subtypes to the type named Employee, called the deep extent of type Employee.
A stream can be opened which only retrieves object that satisfy some condition defined with the stream. Assume we want to retrieve all persons aged 18, i.e. all objects in the deep extent of the type named Person that have the value 18 for its age property. This is done as:
My_DB.open_stream("Person","Age", "=",(ODB_INT)18);In this statement we used the =-operator to compare the values of the objects with the value defined with the stream. For integer and real there are additional comparison operators that can be used. These are:
For collections the equality operator is overloaded. If one operand is a collection and the other is a non collection type then the equality means the member operator. If on the other hand both operands are sets then the equality operator means that the same members should be found in both sets, i.e. A=B means that if an object, o, is member of set A then o must also be a member of the set B and vice verca.
To exemplify how streams are opened over character strings, collections and object reference valued properties consider this example:
A stream is to be opened over the Employee type where all Employees which have the name "Bob Smith" should be returned from the stream. This is written as:
My_DB.open_stream("Employee","Name","Bob Smith");Streams with restrictions over collections and object reference valued properties are opened analogously.
Select streams are opened over existing streams to add additional conditions on the objects that are sought. If for example, all Person objects with age greater than 18 and whose name is "John Doe" are interesting we write:
ODB_QSTREAM s1; ODB_SSTREAM s2; //Open s1 s1=My_DB.open_stream("Person","Age","> =",(ODB_INT)18);Now, s1 retrieves all objects of type Person with age greater than or equal to 18. The additional name condition can be added by opening a select_stream over this stream as:
s2=My_DB.select(s1,"Name","John Doe");Here, a stream is opened over the existing stream, s1, and a condition on the name attribute is defined and the result is bound to the stream variable s2. The objects are retrieved from s2 by the get-method.
The semi-join operation is a variant of the traditional join operator in the relational algebra. The semi-join stream is opened over two streams where attribute values from objects in one stream are compared with attribute values of the objects from the other stream. Only objects from one stream is in the result of the stream. The latter is the difference from a traditional join operator where the result is a tuple of values, (See any textbook that covers the relational algebra and relational databases).
To exemplify, assume we have two types, Pet and Person where both have a character string valued name-attribute. If we would like to retrieve those persons that has the same name as a pet has we write:
ODB_QSTREAM qst1,qst2; ODB_SJSTREAM sjs; //Open qst1 over persons and //qst2 over pets qst1=My_DB.open_stream("Person"); qst2=My_DB.open_stream("Pet"); //Open the semi join stream sjs=My_DB.semi_join(qst1,"Name",qst2,"Name");The objects returned will be from the stream qst1 that has the same name-value as any object of type pet.
Given an open stream, objects can be retrieved through that stream by sending the get message to the database object with the stream as additional argument with the message. The result is either an object or NULL depending on the success of the operation.
The following example opens a stream and retrieves all objects that satisfies the condition that their value for the age property must be greater then 65.
ODB_QSTREAM qst; ODB_REF obj; //Open the stream qst=My_DB.open_stream("Person","Age" ,"> =",65); if (qst==NULL) { //Do some error recovery //qst may be the NULL reference if //the open statement failed } else { //Get the first object and //then the rest of the objects obj=My_DB.get(qst); while(obj!=NULL){ //do something with obj obj=My_DB.get(qst); } } //end elseThis example shows the standard way of iterating through a stream. When all objects are retrieved (a NULL reference is returned) the stream can either be closed or reset to its initial state.
When an opened stream has reached its end or if we by some other reason do not want to retrieve any more objects from it the stream can be reset. When a stream is reset it is set to the same state as if it was just opened.
Streams that will be used again to query the data should be reset instead of closed and recreated. A stream is reset by sending the reset_stream message to the database object as:
My_DB.reset_stream(qst);Where qst is an object of type query, select or semi join stream.
Streams are closed when it is no longer to be reused again. For composite streams, closing the outer most stream will cause all streams it uses to be closed as well. In Figure4 this means that closing the stream s2 will also close the stream s1. In the same figure, closing s1 only will leave s2 in an undefined state. Streams are closed by sending the close_stream message to the database object as:
ODB_QSTREAM qst; // Open qst, and use it My_DB.close_stream(qst);After a stream has been closed th application must not try to use the reference unless the reference is assigned another stream.
![]() | Mail to ODB for Win 95 / NT | ![]() |