Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/property/db_property.hh

Go to the documentation of this file.
00001 /* $Id: db_property.hh,v 1.12 2003/07/24 23:08:35 reed Exp $ */
00002 
00003 /*
00004     @file db_property.hh
00005     
00006     Defines interface for property with database backend. 
00007 
00008     Copyright (C) 2001, 2002 Reed Hedges
00009 
00010     This library is free software; you can redistribute it and/or
00011     modify it under the terms of the GNU Lesser General Public
00012     License as published by the Free Software Foundation; either
00013     version 2 of the License, or (at your option) any later version.
00014 
00015     This library is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018     Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public
00021     License along with this library; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00023 
00024 */
00025 #ifndef _DB_PROPERTY_HH_
00026 #define _DB_PROPERTY_HH_
00027 
00028 #include <string>
00029 #include "property.hh"
00030 
00031 
00032 
00033 /** @class DBProperty db_property.hh vos/metaobjects/property/db_property.hh
00034  *
00035  *  General database-backend interface. By itself this doesn't do anything; 
00036     use a subclass like PGDBProperty (For Postgres databases).  This class
00037     is intended to be subclassed in order to implement VOS/database
00038     bridges with various SQL-based database systems. Subclasses will
00039     have to implement the actual updateToDB() and updateFromDB(), and
00040     methods, and the open() method to connect to the database.
00041     See database-specific classes for full usage details but the basic idea 
00042     is that the constructor should open a connection to the database,
00043     and create the associated table and columns if they don't exist,
00044     or just fetch the existing values if they do.
00045     write() and replace() immediately update the database with new data,
00046     but read() only returns cached data. updateFromDB()
00047     will get values from the database and replace cached data, and send
00048     property-update messages to all property listeners and remote objects.
00049     Some mechanism should be set up to call this function when necesary
00050     If the database backend has no such functionality, then
00051     the the subclass should extend read() to do an update before a read,
00052     and also periodically call updateFromDB() in case it changes.
00053 
00054     Use init() to set up the queries used to read and write to the database.
00055 
00056 
00057     Subclasses of DBProperty should open the database connection (in init), and
00058     actually do the communication with the database.
00059 */
00060 class DBProperty : public virtual LocalProperty 
00061 {
00062 
00063 protected:
00064 
00065     /* Query strings for getting stuff from the database. */
00066     string select_data_query;
00067     string select_type_query;
00068     string select_all_query;
00069 
00070     /* Query strings for setting stuff in the database. */
00071     string update_data_query;
00072     string update_type_query; // this is really not needed, because type is only updated on replace, and we should use update_all for that. but for now...
00073     string update_all_query;
00074 
00075     /* If this isn't empty (""), then this contains the constant datatype. */
00076     string force_type;
00077 
00078 public:
00079 
00080 
00081     /** Database Access Error exception */
00082     class DBAccessError : public runtime_error {
00083         public: DBAccessError(const string& w) : runtime_error(w){};
00084     };
00085 
00086 
00087     /** basic constructor */
00088     DBProperty(MetaObject *superobject) : LocalProperty(superobject), Property(superobject), MetaObject(superobject)  {
00089         // lala
00090     }
00091 
00092 
00093     /** called by factory to create a new instance */
00094     static MetaObject* new_DBProperty(MetaObject* superobject, const string& type) {
00095         return new DBProperty(superobject);
00096     }
00097     
00098     /** Register MetaObject extender for DBProperty. You must also call Property::registerExtenders() for stuff to work!.
00099     */
00100     static void registerExtenders()  {
00101         LocalSite::addLocalObjectExtension(typeid(DBProperty).name(), &DBProperty::new_DBProperty);
00102     }
00103 
00104     /** Set up query strings, for getting or changing just data, with constant
00105         data type.
00106         @param select_query Query for getting just data. Must return scalar.
00107         @param update_query Query for setting the data. %d is replaced with the new data.
00108         @param type Data type to always use.
00109     */
00110 
00111     virtual void init(const string& select_query, const string& update_query, const string& type);
00112 
00113     /** Set up query strings, for getting or changing both data value and data type.
00114         In the update queries, %d will
00115         be replaced by property data, and %t will be replaced by the datatype.
00116         These query strings should be in the format applicable to the 
00117         implementation subclass you are using.
00118         @param select_all_q Query for getting data and type. (in that order)
00119         @param select_data_q    Query for getting just data. 
00120         @param select_type_q    Query for getting type.
00121         @param update_all_q Query for changing data and type. %d will be replaced by property data, and %t with type 
00122         @param update_data_q    Query for changing data. %d will be replaced by data.
00123         @param update_type_q    Query for changing type. Eventually will be removed, in favor of the update_all query @deprecated.
00124     */
00125     virtual void init(const string& select_all_q, const string& select_data_q, const string& select_type_q, const string& update_all_q, const string& update_data_q, const string& update_type_q) ;
00126 
00127     /** Use given values to construct standard (I think) SQL query strings. 
00128         @warning may be broken; untested by author; use at own risk.....  but then send a patch, please :) 
00129         @param table    Name of the table we are interested in.
00130         @param name_col Column in the table used as primary key when looking up data. 
00131         @param val_col  Column containing property value.
00132         @param type_col Column containing property data type.
00133         @param name_val Value to use to identify this property in the database, as primary key.
00134     */
00135     void init_components(const string& table, const string& name_col, const string& val_col, const string& type_col, const string& name_val) ;
00136 
00137     /** change property data, starting at given byte (updated in DB) */
00138     virtual void write(int start, const string& newdata) throw(DBAccessError) {
00139         LocalProperty::write(start, newdata);
00140         updateToDB();
00141     }
00142 
00143     /** change all the property data, and datatype (updated in DB) */
00144     virtual void replace(const string& newdata, const string& newtype = "?") throw(DBAccessError) {
00145         LocalProperty::replace(newdata, newtype);
00146         updateToDB();
00147     }
00148         
00149 
00150     /** open database. this method must be overridden in implementation subclasses. */
00151     virtual void open(string dbinfo = "") {
00152         cout << "** OPEN: " << dbinfo << "\n";
00153     }
00154 
00155     /** perform a query on the database (in the implementation's language; e.g. SQL) This method must be overridden in implementation subclasses.  This method
00156     may throw range_error if there is an error in the query-string substiution.
00157     TODO: how shall non-scalars be returned?
00158     */
00159 
00160     virtual string queryDB(const string& query) throw(DBAccessError) {
00161         cout << "** QUERY: " << query << "\n";
00162         return "**UNIMPLEMENTED**";
00163     }
00164 
00165     /** fetch stuff from database and do a replace. */
00166     virtual void updateFromDB() throw(DBAccessError) ;
00167             
00168     /** write current data and type to DB. */
00169     virtual void updateToDB() throw(DBAccessError) ;
00170 
00171 
00172 
00173 private:
00174     /* Do replacement of substring key with value on s.  Note: only replaces the first key in s.
00175         throws range_error exception if key is not found in s.
00176     */
00177     static string sreplace( const string& s, const string& key, const string& value) throw (range_error);
00178 
00179 };
00180 
00181 
00182 #endif

Generated on Tue Aug 12 03:55:45 2003 for Interreality Project - VOS by doxygen 1.3.2