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

# A Sample application

To give an idea of how ODB is used the following example code illustratesthe interface. This application file is included in the ftp package ODB.ZIP.

    #include < iostream.h>#include < fstream.h>#include < conio.h>#include < time.h>#include < math.h>#include < stdlib.h>#include < sys\timeb.h>#include "odb.h"outputbuffer obuf=outputbuffer();void browse_extent(ODB_TYPE tp,database db){//this function browses through all objects in the//extent of the specified type tpODB_QSTREAM q_stream;ODB_CHAR tpname;ODB_REF o;	if (tp==NULL) return;    	//quit if shitty reference	tpname=tp->getname();   	//this method is not described					//in the manual, it is found					//in odb.h	q_stream=db.open_stream(tpname);	if (q_stream==NULL) return; 	//should not happen					//(they all say that)	cout< < "Browsing the extent of type "< < tpname< < '\n';	obuf.reset_buffer();		//reset the buffer	//follows is the standard structure of iterating through streams	//at ****** Any Code ***** application specific code are enterd	//in below example the object bound to o is just printed to stdout	//-------------------------------------------------	//----------- Std stream iteration-----------------	//-------------------------------------------------	//--          o=db.get(q_stream);                --	//--          while (o!=NULL){                   --	//--            ****** Any Code *****            --	//--            o=db.get(q_stream);              --	//--          }                                  --	//-------------------------------------------------	//----------- End Std stream iteration-------------	//-------------------------------------------------	o=db.get(q_stream);	while (o!=NULL){		o->display(obuf);		cout< < obuf.get_buffer()< < '\n';		obuf.reset_buffer();		o=db.get(q_stream);		}	//-------------------------------------------------	//--                I M P O R T A N T            --	//-------------------------------------------------	//-- The application MUST deallocate the stream  --	//-- here, otherwise a memory leak would occur as--	//-- the stream can not be referenced again      --	//-- Alternatively, declare it as STATIC         --	//-------------------------------------------------	db.close_stream(q_stream);	}void display_schema(database db){//For each type in the loaded database schema//display its information by sending the display message to the//type object and then for each type display its proppertiesODB_CHAR tpname, propname;ODB_TYPE tphandle;	obuf.reset_buffer(); 	//empty any old crap in the buffer	tpname=db.getallsubtypes();		//get the first typename	while (tpname!=NULL){ 		//loop over all typenames		tphandle=db.gettypenamed(tpname); //given a type name the handle							//can be fetched		if (tphandle!=NULL) {			//display the type object and all its properties			tphandle->display(obuf);			cout< < "\n--------------------------------------\n";			cout< < obuf.get_buffer()< < '\n';			obuf.reset_buffer();			cout< < "\n------- Press any key for more -------\n" ;			getch();		//let the user control the flow		}; 				//end while	tpname=db.getnextsubtype();     //get next typename	} 				   //end while}					   //end functionvoid select_type(database db){//In this function the user is provided all usertypes//in the database and then promted to select one whose//extent are to be browsedODB_CHAR tpname;char usertpnm[20];ODB_TYPE utp;tpname=db.getallsubtypes();	while (tpname!=NULL){	cout< < tpname< < '\n';	tpname=db.getnextsubtype();	}	cout< < "Enter name of the type whose extent to browse\n";	cin>>usertpnm;	utp=db.gettypenamed(usertpnm);	if (utp==NULL) cout< < "\nThere no type named "< < usertpnm< < " in the database\n";	else browse_extent(utp,db);}void find_all_janitors(database My_DB){//In this function all janitors are retreived.//This is done by first finding the department//object with "Janitors" as value in to the//Name attributeODB_QSTREAM q_stream;ODB_SSTREAM s_stream;ODB_REF o,jo;char typenm[16]="Department";char propnm[8]="Name";char val[16]="Janitors";	//Open a stream over the department type with the condition that	//the Name attribute must have Janitors as value	q_stream=My_DB.open_stream(typenm,propnm,val);	//The stream may not be opened if so it is best to check before use.	if (q_stream==NULL) {		cout< < "\nError when opening stream bla bla bla...\n";		return;		};	//The stream was opened allright. In the remaining we only consider the	//first found department named Janitors, thus we do not assume the name	//to be a key to departments	o=My_DB.get(q_stream);	//If o==NULL yhen there were no such department in the database	if (o==NULL) {		cout< < "No department named "< < val< < " exist in the database\n";		return;		}	//No longer req'd	My_DB.close_stream(q_stream);	//reuse q_stream to open the stream to select all employees at	//the department bound to object reference o	q_stream=My_DB.open_stream("Employee","EmployedAt",o);  if (q_stream==NULL) {		cout< < "\nError when opening stream over employee\n";		return;		};	cout< < "\nThese are the Janitors\n-------------------------\n";	obuf.reset_buffer();			//reset the buffer	//Now, we can start browsing the janitors	jo=My_DB.get(q_stream);	while (jo!=NULL){		jo->display(obuf);		cout< < obuf.get_buffer()< < '\n';		obuf.reset_buffer();		jo=My_DB.get(q_stream);		};	//Now, Lets select those janitors who earn more than 10000.	//This is accomplished by opening a select stream over the	//query stream which selects all janitors.	//First, reset the stream	My_DB.reset_stream(q_stream);	//secondly, open a select stream over q_stream with the	//condition that the salary should be greater than 10000	s_stream=My_DB.select(q_stream,"Salary",">",(ODB_INT)10000);	cout< < "\n Theese are all the rich janitors\n";	obuf.reset_buffer();			//reset the buffer	//Now, we can start browsing the rich janitors	jo=My_DB.get(s_stream);	while (jo!=NULL){		jo->display(obuf);		cout< < obuf.get_buffer()< < '\n';		obuf.reset_buffer();		jo=My_DB.get(s_stream);		};	My_DB.close_stream(s_stream);} void demonstrate_index(database &My_DB){//In this fn a new type is created. The type is then//given an integer valued proerty which can be assigned//random values.//First create 5000 objects and find the ones with a particular//value for the attribute. Measure the time for this. Then create//an index and redo the search and measure time.struct timeb t1,t2;double elapsed_time;ODB_REF o;int i,v;ODB_QSTREAM q_stream;	My_DB.set_tablesize(3000); //3K table size	//Create a type named testtype	My_DB.create_type("Testtype");	//Create an integer valued property named Int_prop	My_DB.add_property("Testtype","Int_prop",_INT_);	//Create 5000 objects and assign random values to	//the attribute named Int_prop for each object.	cout< < "\nCreating 50000 objects ...";	i=0;	while (i++< 50000){		//Create an object and assign o to reference it		o=My_DB.create_instance("Testtype");		//generate a random number in [0..4000]		v=rand()%4000;		//set the property named Int_prop of the object o		//to v		o->setproperty_value("Int_prop",(ODB_INT)v);	};	cout< < "Done\n";	//Now, lets find all objects with Int_prop = 2345	//the probability that this number is less than 1	//Thus, it may be the case that no object exists	//with that property value. To make sure there is	//atleast one such object we simply assign an object	//that value for the property.	//To make sure we do this right we first find out the	//OID of the last object. Then we subtract a number less	//than 50000 from the OID. We now have an OID to one of	//the 50000 object we just generated. Retrieve it and	//set the value.	i=0;	My_DB.getproperty_value(o,"OID", &(ODB_INT)i);	i=i-rand()%45000;	o=My_DB.getobjectwithoid("Testtype",i);	o->setproperty_value("Int_prop",(ODB_INT)1234);	//Now that we know there is an object with 1234 as	//value for the Int_prop property we can start to	//search for it.	obuf.reset_buffer();	q_stream=My_DB.open_stream("Testtype","Int_prop","=",(ODB_INT)1234);	//All set for test search. Start timer and go for it	ftime(&t1);	o=My_DB.get(q_stream);	while (o!=NULL){		o->display(obuf);		cout< < obuf.get_buffer()< < '\n';		obuf.reset_buffer();		o=My_DB.get(q_stream);		};	//All objects found, stop timer and check time	ftime(&t2);	elapsed_time=(t2.time*1000+t2.millitm)-(t1.time*1000+t1.millitm);	cout< < "\The search took "< < elapsed_time< < "millisec without index";	//Now, build an index and redo the whole procedure.	cout< < "\nBuilding index ...";	My_DB.create_index("Testtype", "Int_prop");	cout< < "Done\n";	//reset the stream	My_DB.reset_stream(q_stream);	obuf.reset_buffer();	ftime(&t1);	o=My_DB.get(q_stream);	while (o!=NULL){		o->display(obuf);		cout< < obuf.get_buffer()< < '\n';		obuf.reset_buffer();		o=My_DB.get(q_stream);		};	ftime(&t2);	elapsed_time=(t2.time*1000+t2.millitm)-(t1.time*1000+t1.millitm);	cout< < "\The search took "< < elapsed_time< < "millisec with index";	//-------------------------------------------------	//--                I M P O R T A N T            --	//-------------------------------------------------	//-- Since the application now no longer need the--	//-- 50000objects etc we now deallocate them     --	//-- There are several ways of doing this.       --	//-- 1: Open a stream over all Testtype objects  --	//-- and deallocate them one by one.             --	//-- 2: Since the type named Testtype is not     --	//-- wanted anymore we simply delete the type    --	//-- and let ODB do the hard work of deallocating--	//-- everything, e.g. objects indexes ......     --	//--                                             --	//-- And also, we allocated a stream local to    --	//-- to this function. This function must be     --	//-- deallocated to prevent memory leak.         --	//-------------------------------------------------	My_DB.delete_type("Testtype");	My_DB.close_stream(q_stream);	//It is now ok to exit this function}int main (void){database My_DB("");int retval;	retval=My_DB.load_database("Compdb.odb");	if (retval< 0) cout< < "\n Failed to load company database ";	else {		cout< < "\n The company database is loaded";		My_DB.display(obuf);		cout< < "\n"< < obuf.get_buffer();		obuf.reset_buffer();		};	//display the schema of the loaded database	display_schema(My_DB);	//let the user select and browse a type extent	select_type(My_DB);	//demonstrate the search interface	find_all_janitors(My_DB);	//show the benefit of indexing when the database	//is large	demonstrate_index(My_DB);	cout< < "\nODB Demo is now finished\n";	return 1;};

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