Hydra 0.20
hydra.src/hydra/DB.h
00001 
00002 /*
00003  * Copyright (c) 2009 Aleksander B. Demko
00004  * This source code is distributed under the MIT license.
00005  * See the accompanying file LICENSE.MIT.txt for details.
00006  */
00007 
00008 #ifndef __INCLUDED_HYDRA_DB_H__
00009 #define __INCLUDED_HYDRA_DB_H__
00010 
00011 #include <hydra/TR1.h>
00012 
00013 #include <QString>
00014 
00015 #include <hydra/Record.h>
00016 
00017 struct sqlite3;   // forward
00018 typedef struct sqlite3 sqlite3;   // forward
00019 struct sqlite3_stmt;  // forward
00020 typedef struct sqlite3_stmt sqlite3_stmt; // forward
00021 
00022 namespace hydra
00023 {
00024   class DB;
00025   class Cursor;
00026 };
00027 
00028 /**
00029  * This represents a sqlite database table.
00030  *
00031  * This in the future, this can be abtracted away as an interface to allow
00032  * many possible backends (the old BerkleyDB one, postgresql, etc)
00033  *
00034  * Internally, this backend uses std::string and 8-bit UTF strings
00035  * for size-conservation.
00036  *
00037  * @author Aleksander Demko
00038  */ 
00039 class hydra::DB
00040 {
00041   public:
00042     /**
00043      * Creates a DB (disk backed map). It will use the given sqllite db
00044      * file and prepend the given prefix/namespace to the tables.
00045      * Using different tablescope's allows you to have multiple DBs
00046      * in the same sqlite file.
00047      *
00048      * @param filename the sqlite filename on disk
00049      * @param tablescope the prefix/table name to use. Cannot be empty.
00050      * @author Aleksander Demko
00051      */ 
00052     DB(const QString &filename, const QString & tablescope);
00053     /**
00054      * Creates a DB (disk backed map). It will use the given sqllite db
00055      * file and prepend the given prefix/namespace to the tables.
00056      *
00057      * This constructor allows you to reuse anoter DB instance's sqlite connection.
00058      *
00059      * @param linked_db the DB from whome this DB will share a single sqlite connection.
00060      * @param tablescope the prefix/table name to use. Cannot be empty.
00061      * @author Aleksander Demko
00062      */ 
00063     DB(DB &linked_db, const QString &tablescope);
00064     /// destructor
00065     virtual ~DB();
00066 
00067     /// is this key even in the db?
00068     bool contains(const std::string &key) { return contains(key.c_str()); }
00069     /// is this key even in the db?
00070     bool contains(const QString &key) { return contains(key.toUtf8().constData()); }
00071     /// is this key even in the db?
00072     bool contains(const char *key);
00073 
00074     /// removes the key from the db, returns true if anything was done
00075     bool erase(const std::string &key) { return erase(key.c_str()); }
00076     /// removes the key from the db, returns true if anything was done
00077     bool erase(const QString &key) { return erase(key.toUtf8().constData()); }
00078     /// removes the key from the db, returns true if anything was done
00079     bool erase(const char *key);
00080 
00081     /// saves to the db, returns true on success, will replace if exists
00082     bool insert(const std::string &key, const std::string &value) { return insert(key.c_str(), value); }
00083     /// saves to the db, returns true on success, will replace if exists
00084     bool insert(const QString &key, const std::string &value) { return insert(key.toUtf8().constData(), value); }
00085     /// saves to the db, returns true on success, will replace if exists
00086     bool insert(const char *key, const std::string &value);
00087 
00088     /// returns false on not-found or failed to load
00089     bool get(const std::string &key, std::string &value) { return get(key.c_str(), value); }
00090     /// returns false on not-found or failed to load
00091     bool get(const QString &key, std::string &value) { return get(key.toUtf8().constData(), value); }
00092     /// returns false on not-found or failed to load
00093     bool get(const char *key, std::string &value);
00094 
00095     /// saves to the db, returns true on success, will replace if exists
00096     bool insert(const std::string &key, const hydra::Record &value) { return insert(key.c_str(), value); }
00097     /// saves to the db, returns true on success, will replace if exists
00098     bool insert(const QString &key, const hydra::Record &value) { return insert(key.toUtf8().constData(), value); }
00099     /// saves to the db, returns true on success, will replace if exists
00100     bool insert(const char *key, const hydra::Record &value);
00101 
00102     /// returns false on not-found or failed to load
00103     bool get(const std::string &key, hydra::Record &value) { return get(key.c_str(), value); }
00104     /// returns false on not-found or failed to load
00105     bool get(const QString &key, hydra::Record &value) { return get(key.toUtf8().constData(), value); }
00106     /// returns false on not-found or failed to load
00107     bool get(const char *key, hydra::Record &value);
00108 
00109   private:
00110     void initDB(void);
00111     void initPrepared(void);
00112 
00113   private:
00114     class Connection
00115     {
00116       public:
00117         QString fileName;
00118         sqlite3 *handle;
00119       public:
00120         Connection(void) : handle(0) { }
00121         ~Connection();
00122     };
00123     class Statement
00124     {
00125       public:
00126         sqlite3_stmt *handle;
00127       public:
00128         Statement(void) : handle(0) { }
00129         ~Statement();
00130     };
00131     class ResetOnExit
00132     {
00133       public:
00134         ResetOnExit(sqlite3_stmt *handle) : dm_handle(handle) { }
00135         ~ResetOnExit();
00136       private:
00137         sqlite3_stmt *dm_handle;
00138     };
00139 
00140   private:
00141     friend class hydra::Cursor;
00142 
00143     std::shared_ptr<Connection> dm_connection;
00144     QString dm_table;
00145 
00146     // these are for performance cacheing
00147     Statement dm_put_statement, dm_has_statement, dm_get_statement, dm_erase_statement;
00148 
00149     // hot buffer used by the record-based put function
00150     QByteArray dm_put_hotbuf, dm_get_hotbuf;
00151 };
00152 
00153 /**
00154  * A iterator though a DB.
00155  *
00156  * @author Aleksander Demko
00157  */
00158 class hydra::Cursor
00159 {
00160   public:
00161     /**
00162      * Constructor.
00163      * This will iterate though all the entries in the DB.
00164      *
00165      * The cursor will initially be inValid. You must use next()
00166      * to move to the first valid row (if any).
00167      *
00168      * @author Aleksander Demko
00169      */
00170     Cursor(hydra::DB &db);
00171     /**
00172      * Constructor.
00173      * This will iterate though all the entries in the DB whos key has
00174      * the given prefix
00175      *
00176      * The cursor will initially be inValid. You must use next()
00177      * to move to the first valid row (if any).
00178      *
00179      * @author Aleksander Demko
00180      */
00181     Cursor(hydra::DB &db, const QString &prefix);
00182 
00183     /**
00184      * Is the cursot at a valid row?
00185      *
00186      * @author Aleksander Demko
00187      */ 
00188     bool isValid(void) const { return dm_isvalid; }
00189 
00190     /**
00191      * Move the cursor to the next row, returns true if this was successul
00192      * and the cursor is at the next row and is valid.
00193      *
00194      * @author Aleksander Demko
00195      */ 
00196     bool next(void);
00197 
00198     /**
00199      * Returns the key value at the current row. The current row must be valid.
00200      *
00201      * @author Aleksander Demko
00202      */ 
00203     const char * getKey(void);
00204 
00205     /**
00206      * Loads the current value. The current row must be valid.
00207      *
00208      * @author Aleksander Demko
00209      */ 
00210     void get(std::string &value);
00211 
00212     /**
00213      * Loads the current value. The current row must be valid.
00214      *
00215      * @author Aleksander Demko
00216      */ 
00217     void get(QString &value);
00218 
00219     /**
00220      * Loads the current value. The current row must be valid.
00221      *
00222      * Returns false if the record failed to deserialize (ie. it threw an exception)
00223      *
00224      * @author Aleksander Demko
00225      */ 
00226     bool get(hydra::Record &value);
00227 
00228     //Erase(void);
00229 
00230   private:
00231     bool dm_isvalid;
00232 
00233     std::shared_ptr<DB::Connection> dm_connection;
00234 
00235     DB::Statement dm_select_statement;
00236 
00237     QByteArray dm_put_hotbuf, dm_get_hotbuf, dm_prefix_string;
00238 };
00239 
00240 #endif
00241 
 All Classes Namespaces Functions Variables