![]() | An Object-Oriented Database V. 0.1 Mail to: ODB for Win 95 / NT | ![]() |
The datatype collection is somewhat more complex than the other datatypes supported by ODB. A collection is similar to a set with the difference that a collection can contain several equal objects or values.
Collections are created by sending the create_collection message to the database object. On successful creation a handle to an empty collection is returned. This handle must ALWAYS be assigned a reference owned by the application since the collection otherwise will be unaccessible to the application. The application owned reference can be released when the collection is referenced from elswhere, e.g. through an attribute of some object.
A collection which may contain references to other objects is created and assigned a collection handle ch as:
ODB_SET ch; ch=My_DB.create_collection(_OBJECT_);Valid type identifiers are to the create_collection method are:
When a collection has been created elements may be inserted into the collection. ODB supports two way of doing this; by sending the collection_insert message to the database object or by sending the insert message directly to the collection object.
In the following example a collection of character strings are created and bound to the handle coll. Then two elements are inserted into the set by collection_insert and by insert.
ODB_SET coll; //Create a collection coll=My_DB.create_collection(_CHAR_); My_DB.collection_insert(coll,"Object"); coll->insert("Orientation");The difference with these two ways is that by sending the collection_insert message to the database objects all necessary checks are performed before insertion. When the insert message is sent to a collection the application must ensure that the collection is of the correct type and that the collection handle is initialized properly.
The return value from collection_insert is:
Elements may be deleted from a collection by either sending the delete_element message to the set object or by sending the delete_from_collection message to the database object. In the following example objects are deleted from the set coll.
ODB_SET coll; //Create collection coll=My_DB.create_collection(_INT_); //Insert into collection using both //insertion methods My_DB.collection_insert(coll,2); coll->insert(3); //remove from collection My_DB.delete_from_collection(coll,3); coll->delete(2);Using the delete_from_collection message to the database object is a safer way since all necessary checks are performed before deketion of any element. However, sending the delete message directly to the collection object is slightly faster but then the application must ensure that the handle is initialized etc.
Note especially that before using the delete message directly to the collection object to delete an ODB_CHAR the characterstring must be substituted with the characterstring stored in the string table. The same is true for inserting characterstrings directly into a collection The following example illustrates the correct procedure:
ODB_REF cstr, cstr2; ODB_SET coll; coll=My_DB.create_collection(_CHAR_); //Get a handle to the stored ODB string //Don't bother if you know it does not //exist, ODB takes all reqd actions cstr=My_DB.getstring("ODB"); //Insert it into the collection My_DB.collection_insert(coll,cstr); //The following will not delete //ODB from the collection coll.delete("ODB"); //The following will delete // "ODB" from the collection cstr2=My_DB.getstring("ODB"); coll.delete(cstr2);
Collections are deleted by either sending the delete_collection message to the database object or the delete_set message to the collection object.
There are a number of ODB specific datatypes and type identifiers that are used to interface ODB in the API.
There are a number of C++ datatypes and classes defined in the API these are:
C++ datatype | Type of data |
---|---|
ODB_INT | integer |
ODB_REAL | real |
ODB_OID | oid |
ODB_CHAR | charstring |
ODB_REF | object handle |
ODB_SET | collection handle |
ODB_QSTREAM | query stream handle |
ODB_SSTREAM | select stream handle |
ODB_SJSTREAM | semi-join stream handle |
ODB_DB | database object |
ODB_DB_HANDLE | odb database handle |
ODB_TYPE | odb type handle |
These types are used by the application using ODB to declare interface variables to ODB. The C++ classes the API provides are:
C++ Class | Ref. decl | Description |
---|---|---|
Database | ODB_DB | The ODB database class |
Type | ODB_TYPE(ref.) | The ODB type class |
Object | ODB_REF (ref.) | The ODB object class |
Outputbuffer | N/A | The ODB outputbuffer class |
There are a number of type identifiers defined in the API which are used to specify to ODB which type to consider. These are:
Type Id | C++ Type |
---|---|
_INT_ | ODB_INT |
_REAL_ | ODB_REAL |
_CHAR_ | ODB_CHAR |
_OBJECT_ | ODB_REF |
_OBJECT_COLLECTION_ | ODB_SET |
_INT_COLLECTION_ | ODB_SET |
_REAL_COLLECTION_ | ODB_SET |
_CHAR_COLLECTION_ | ODB_SET |
Note that the C++ datatype ODB_SET is used to denote all collection types. The type identifiers are used to denote the result type of properties when these are created and to denote which type of elements a collection can contain.
In addition to database creation, maintenance and querying there a methods to print objects, retrieve object and types etc. these are described here.
Each database object contains a stringtable where all strings used by the datbase are stored. Before some operatons involving strings can be executed the application must get a handle to the string maintained by the database otherwise equality tests etc. will not function properly. In most cases ODB does this for you.
A string handle to a prticular string is obtained by sending the getstring message to the database object. In the following example a handle is obtained to the string "ODB Rules".
ODB_CHAR str; str=My_DB.getstring("ODB Rules");The following example demonstrates the benefit if the string table:
ODB_CHAR s1, s2; s1=My_DB.getstring("ODB"); s2=My_DB.getstring("ODB"); if (s1==s2) cout << "\nODB Rules\n"; else cout << "\nYou cheated\n");The output will of course be: ODB Rules
All objects, types and databases may be printed by sending the display message to the object. To support any print-method the application may want to utilize all display methods of all ODB objects print in a buffer which is provided by the ODBAPI.
The display message can be sent to any OBD object with a display buffer as argument as:
displaybuffer buf; database odb; ODB_TYPE tp; //Create a type tp=odb.create_type("Person"); //print type to buffer tp->display(buf); //print buffer to stdout cout << buf.get_buffer(); //reset buffer before used buf.reset_buffer();
OBD provides a class named outputbuffer which all display methods use. A buffer, Disp_Buf is declared in the application as:
outputbuffer DispBuf;The buffer can be retrieved by sending the get_buffer message as:
Disp_Buf.getbuffer();The return value is a reference to a character buffer as:
ODB_CHAR BufPtr BufPtr=Disp_Buf.getbuffer();The reference to the buffer can then be used by the application to print the content of the buffer on a widget in a GUI or on a tex display using cout etc.as e.g.:
ODB_CHAR BufPtr BufPtr=Disp_Buf.getbuffer(); cout << BufPtr;When the buffer has been printed or to prevent it from overflowing it can be emptied by sending the reset_buffer message to the buffer object as:
DispBuf.reset_buffer();The buffer size is 1k and if there is not enough free space in it when used by some object, the display output from the object will be lost.
If a handle is required to a type for e.g. printing the gettypenamed message to the database object as:
ODB_TYPE tp; tp=My_DB.gettypenemrd("Person");In this example a handle is returned to the type named Person. If no such type exists the NULL handle is returned.
Object handles can retreived by using the query interface, see Section 5.0, or by sending the getobjectwithoid message to the database object as:
ODB_REF o; o=My_DB.getobjectwithoid("Usertypes",45);In this example the object with oid equal 45 is returned, if no such object exist a NULL handle is returned. Note especially that there is no guarantee that objects will get the same oid when reloaded from file, in fact it is very likely that it will get another oid.
If the application for some reason wants to traverse the type tree of the database the application then first sends the getallsubtypes message to the database object to get the first subtype. All subsequent subtypes are retreived one by one by sending the getnextsubtype message to the database object. The following exaple shows how all types in the database are printed on stdout:
ODB_CHAR tp; //type names ODB_TYPE tph; //type handle database My_DB; My_DB.load_database("Compdb.odb"); tp=My_DB.getallsubtypes(); while(tp!=NULL){ cout << tp << `\n'; tp=My_DB.getnextsubtype(); //Type handles to the subtypes //can be obtained as tph=My_DB.gettypenamed(tp); }
char *tp; //type names ODB_TYPE tph; //type handle database My_DB; My_DB.load_database("Compdb.odb"); tp=My_DB.getsubtypes("Person"); while(tp!=NULL){ cout << tp << `\n'; tp=My_DB.getsubtype("Person"); //Type handles to the subtypes //can be obtained as tph=My_DB.gettypenamed(tp); }In this example all direct subtypes of the type named Person are retreived.
The supertype name of a particular type can be retreived by using the getsupertype message to the database object.
In this example the supertypename of the type named Employee is retreived and then used to get a handle to the supertype to the type named Employee.
ODB_CHAR stpnm; ODB_TYPE stp; stpnm=My_DB.getsupertype("Employee"); stp=My_DB.gettypenamed(stpnm);
The names of all properties of a type can be retreived b y first sending the getfirstprop messageto the database object and then get the rest of the property names by sending the getnextprop message to the database object.
In this example all properties of the type named Employee are printed to stdout.
ODB_CHAR pn; //prop names database My_DB; My_DB.load_database("Compdb.odb"); pn=My_DB.getfirstprop("Employee"); while(pn!=NULL){ cout << pn << `\n'; pn=My_DB.getnextprop("Employee"); }
As described in Section 4.3 all properties are associated with a type where the type describes which objects the property can have as values.
The type of a property can be retreived by sending the getpropertytype message to the database object. The returned value is a type identifier see section 4.3. In the following example the type identifier is retreived from the name property of the Person type.
ODB_TYPE_TAG ttg; ttg=My_DB.getpropertytype("Person","Name");
Each property denotes a value or other object. To retreive the denoted value or object the application sends the getproperty_value message to the database object.
It is important to note that the return value is a code indicating the success of the operation. The value is retreived by sending the reference to the variable the result is intendet to be retreived into. In the next example the value of a set valued property is retreived into the variable coll:
ODB_SET coll; ODB_REF obj; //obj is assigned a person object //and person have a collection //valued property named Parents //defined to them. ok=My_DB.getproperty_value(obj,"Parents",&coll);The return value is:
This system is intended to support developers in managing moderately sized data in an easy manner. The data can be created and changed outside the application by using a graphical user interface and later loaded into the application easily without any recompilation or other cumbersome procedure.
The system supports the object-oriented data modelling paradigm for the data stored.
The data can easily be queried
through a high level stream based interface which the API provides.
This is the firs released version of the system and any bug reports or comments
are welcomned to me.
![]() | Mail to ODB for Win 95 / NT | ![]() |