| ODB for Win95/NT An Object-Oriented Database V. 0.1 Mail to: ODB for Win 95 / NT |

# 6.0 Collections

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.

## 6.1 Creating collections

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:

- _INT_
- _REAL_
- _CHARSTRING_
- _OBJECT_

Thus, it is not possible to declare a collection to contain other collections.

## 6.2 Adding elements to a collection

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:

- > 0 upon succesful insert
- == -1 for improper handle
- ==-2 if the collection was of another type than the element to insert

## 6.3 Delete element from collection

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);

## 6.4 Delete collection

Collections are deleted by either sending the delete_collection message to the database object or the delete_set message to the collection object.

# 7.0 Datatypes

There are a number of ODB specific datatypes and type identifiers that are used to interface ODB in the API.

## 7.1 C++ Datatypes

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

## 7.2 Type identifiers

There are a number of type identifiers defined in the API which are used to specify to ODB which type to consider. These are:

- _INT_
- _REAL_
- _CHAR_
- _OBJECT_
- _OBJECT_COLLECTION_
- _INT_COLLECTION_
- _REAL_COLLECTION_
- _CHAR_COLLECTION_

These identifiers are used to identify objects of C++ datatypes as :

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

Table1. Type and Id mapping

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.

# 8.0 More interface methods

In addition to database creation, maintenance and querying there a methods to print objects, retrieve object and types etc. these are described here.

## 8.1 The string table

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

## 8.2 Printing ODB objects

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();

### 8.2.1 Display 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.

## 8.3 Getting a type handle

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.

## 8.4 Getting an object handle

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.

## 8.5 Traversing all subtypes of a type

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);

    }

## 8.6 Traversing direct subtypes of a type

A direct subtype of a type, t, is a type whose supertype is the type t. The direct subtypes are traversed by first sending the getsubtypes message to the database object and then sending the getsubtype message to get the other subtype names, one by one as:

    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.

## 8.7 Getting the supertype to a type

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);

## 8.8 Getting all properties of a type

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");

    }

## 8.9 Getting the type of a property

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");

## 8.10 Getting the value of an object property

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:

- > 0 if the operation succeeded
- ==-1 if the object reference was NULL
- ==-2 if the property did not exist
- ==-3 if the expected result type did not match the resulttype of the property.

# Conclusion

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.

| ODB for Win95 / NT An Object-Oriented Database V. 0.1 Mail to ODB for Win 95 / NT |