• Antelope Release 5.5 Mac OS X 10.8.5 2015-04-21

 

NAME

Datascope_Handle - handle object to manipulate Datascope db

SYNOPSIS

#include "dbpp.h"
using namespace SEISPP;
class Datascope_Handle : public Database_Handle

SUPPORT


Contributed code: NO BRTT support.
THIS PIECE OF SOFTWARE WAS CONTRIBUTED BY THE ANTELOPE USER COMMUNITY. BRTT DISCLAIMS ALL OWNERSHIP, LIABILITY, AND SUPPORT FOR THIS PIECE OF SOFTWARE.

FOR HELP WITH THIS PIECE OF SOFTWARE, PLEASE CONTACT THE CONTRIBUTING AUTHOR.

DESCRIPTION

The Datascope_Handle object is an instantiation of an abstract object called Database_Handle that is intended as a generic interface to any relational database system. The Datascope_Handle is an implementation for Dan Quinlan's Datascope DBMS maintained commercially by BRTT and used mainly in seismology.

A Database_Handle must be understood to mean four fundamental things the user must keep in mind:

OBJECT DEFINITIONS

This is the exact definition of the abstract base class:

class Database_Handle
{
public:
        virtual double get_double(string)=0;
        virtual int get_int(string)=0;
        virtual string get_string(string)=0;
        virtual string get_filename()=0;
        virtual void put(string,double)=0;
        virtual void put(string,float)=0;
        virtual void put(string,int)=0;
        virtual void put(string,string)=0;
        virtual void put(string,char *)=0;
        virtual void put(string,const char *)=0;
        virtual int number_tuples()=0;
        virtual int number_attributes()=0;
        virtual void rewind()=0;  // set row pointer to top
        virtual void operator ++()=0;
        virtual void sort(list<string>keys)=0;
        virtual void subset(string)=0;
        virtual void join(string t1, string t2,
                list<string> keys1,list<string>keys2)=0;
        virtual void group(list<string>group_keys)=0;
};

Note this object has no data but only function members. The series of get functions extract a concrete type from the table at the current row position tagged by the attribute name passed as the one argument for each member function. The put functions do the opposite. At the current row position they place the contents of the second argument into the field (attribute) defined by the name given in the first argument.

number_attribute and number_tuples define the number of columns and rows respectively in the virtual table to which the handle relates. The rewind function sets the row pointer to 0. The ++ operator increments the row position pointer in the virtual table.

sort, subset, join, and group implement the standard database operations that have those names. In these operators the list<string> STL containers should contain key attributes that are used to define the operation. i.e. sort keys for a sort, join keys for joins, and group keys for grouping (group by clause in SQL). In the join function the two string arguments (t1 and t2) define the tables to be joined. In the subset function the string is the subset clause that could be implementation dependent.

The Datascope_Handle defines all of the above virtual functions plus a few others. The full definition is:

class Datascope_Handle : public Database_Handle
{
public:
        Datascope_Handle(string dbname,bool readonly);
        Datascope_Handle(string dbname, string pfname,
                        string tag,bool readonly);
        Datascope_Handle(Dbptr db, Pf *pf, string tag);
        Datascope_Handle(Datascope_Handle& dh);
        ~Datascope_Handle();
        double get_double(string);
        int get_int(string);
        string get_string(string);
        string get_filename();
        void put(string, double);
        void put(string, float);
        void put(string,int);
        void put(string,string);
        void put(string,char *);
        void put(string, const char *);
        int append();
        int current_record(){return(db.record);};
        void set_record(int rec){db.record=rec;};
        void lookup(string tablename);
        void next_record(){++db.record;};
        int number_tuples();
        int number_attributes();
        void rewind(){db.record=0;};
        void sort(list<string>keys);
        void join(string t1, string t2,
                list<string> keys1,list<string>keys2);
        void natural_join(string t1, string t2);
        void natural_join(string t2);
        void subset(string sstr);
        void group(list<string>group_keys);
        Datascope_Handle& operator=(const Datascope_Handle&);
        void operator ++();
        void close();
        Dbptr db;
private:
        bool close_on_destruction;
	bool is_bundle;  // true when db is result of dbgroup
};

The following function definitions are appended from the Database_Handle definition:

The natural_join functions are added to use the Datascope feature of natural joins that do not require a key. This function is overloaded. The natural_join(string t1, string t2) joins tables t1 and t2. The form with only t2 joins t2 to the current view. join implements the generic join operator defined in the abstract base class.

This class adds two position operators. set_record sets the record pointer to the specified integer value and current_record returns the current row index position.

The next_record is a function alternative to the ++ operator.

The lookup is a simplified form of dblookup. It sets the view to be the single table with the name passed as the string argument.

The close function is potentially confusing. It does not instantly close the database, but sets the private variable close_on_destruction true. Normally this variable is false to prevent closing the database when a copy of the handle goes out of scope. This implies this function should be called when the program is about to exit or immediately before the handle is, by design, going to go out of scope. Most programs will not need to call this function at all and can simply let the database close when the program exits. This function is really needed only in applications that will open and close one or more databases several times in one run.

CONSTRUCTORS

There are currently three basic constructors that implement a form of resource acquisition. That is, they build the handle, but may do more and will throw an exception if the resource cannot be acquired.

The Datascope_Handle(string dbname,bool readonly) constructor calls dbopen on the database with name dbname. If readonly is true it is opened readonly. Otherwise it is opened as r+. Be aware this is a VERY simple constructor and the Dbptr will be just what dbopen sets it to. Any manipulations without some additional calls to set the Dbptr to a specific table or view will cause your program to abort. The most common application of this would be to call this constructor and immediately call the lookup function to work on a single table.

These two constructors are actually very similar:

Datascope_Handle(Dbptr db, Pf *pf, string tag);
Datascope_Handle(string dbname, string pfname,
                   string tag,bool readonly);

Both are useful for any program that is table driven by a single database view. The first one defines the basic algorithm: dbprocess is called on the Dbptr db using the &Tbl list of processing steps defined with the name tag in the parameter file handle pf. The second form is an all in one solution with the same basic algorithm: open database dbname, open pffile pfname, extract the process list from the parameter file using the Tbl data tagged with tag, and then release pf. The readonly argument is as described above and is relatively self explanatory.

The copy constructor, Datascope_Handle(Datascope_Handle& dh), is also defined. This is important to get a new handle to be manipulated to produce a different view while retaining the original, parent handle. For example, to keep a copy of a view sorted in two different orders one would want to call the copy constructor on the handle before the sort. Then the original would be unaltered but the copy would contain the sorted view.

DESTRUCTOR

The concept of the destructor for this object is unusual and must be understood. Because it is often necessary to have several open tables or database views within the same program destroying the handle is problematic. This is handled in a very simple way. The close_on_destruction boolean variable is normally false. This means that when a handle goes out of scope normally (close_on_destruction is false) nothing happens. The database is closed ONLY when close_on_destruction is set true. The only way to make that happen is by an explicit call to close(). Hence, as noted above, close should only be called when you mean it. It is not usually necessary to call it at all, but let the system handle all the housekeeping on exit.

OPERATORS

The ++ operator is implemented and acts as described in the generic handle description above.

The = operator is defined and simply copies the Dbptr.

EXCEPTIONS

Most functions in this object can and will throw a seispp_dberror exception in the event of a problem. Use the seispp_dberror log_error function to dump the elog and internal message passed through the throw mechanism. (Note this can be redundant and quite verbose. This assumes that exceptions are rare events.)

LIBRARY

-lseispp

SEE ALSO

seispp_error.3,
http://geology.indiana.edu/pavlis/software/seispp/html/index.html

BUGS AND CAVEATS

The base class will undoubtedly evolve if and when I ever try to adapt this to a dbms other than Datascope. For now the inheritance from an abstract base class is kind of baggage, but it is forward-looking baggage.

AUTHOR

Gary L. Pavlis
Indiana University
pavlis@indiana.edu

Antelope User Group Contributed Software
Printer icon