sqlite.hpp

Go to the documentation of this file.
00001 #ifndef GLIM_SQLITE_HPP_
00002 #define GLIM_SQLITE_HPP_
00003 
00004 /**
00005  * A threaded interface to <a href="http://sqlite.org/">SQLite</a>.
00006  * This file is a header-only library,
00007  * whose sole dependencies should be standard STL and posix threading libraries.
00008  * You can extract this file out of the "glim" library to include it separately in your project.
00009  * @code
00010 Copyright 2006 Kozarezov Artem Aleksandrovich <artem@bizlink.ru>
00011 
00012 Licensed under the Apache License, Version 2.0 (the "License");
00013 you may not use this file except in compliance with the License.
00014 You may obtain a copy of the License at
00015 
00016     http://www.apache.org/licenses/LICENSE-2.0
00017 
00018 Unless required by applicable law or agreed to in writing, software
00019 distributed under the License is distributed on an "AS IS" BASIS,
00020 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021 See the License for the specific language governing permissions and
00022 limitations under the License.
00023  * @endcode
00024  * @file
00025  */
00026 
00027 #include <stdexcept>
00028 #include <sqlite3.h>
00029 #include <pthread.h>
00030 #include <string.h> // strerror
00031 #include <sys/types.h> // stat
00032 #include <sys/stat.h> // stat
00033 #include <unistd.h> // stat
00034 #include <errno.h> // stat
00035 #include <stdint.h>
00036 
00037 namespace glim {
00038 
00039 class SqliteSession;
00040 class SqliteQuery;
00041 
00042 /**
00043  * The database.
00044  * According to sqlite3_open <a href="http://sqlite.org/capi3ref.html#sqlite3_open">documentation</a>,
00045  * only the thread that opened the database can safely access it. This restriction was
00046  * relaxed, as described in the <a href="http://www.sqlite.org/faq.html#q8">FAQ</a>
00047  * (the "Is SQLite threadsafe?" question), so we can use the library from multiple
00048  * threads, but only if no more than one thread at a time accesses the database.
00049  * This restriction is, in fact, beneficial if the database is used from a single application:
00050  * by restricting access to a sigle thread at a time, we effectively avoid all deadlock issues.\n
00051  * This library goals are:\n
00052  * \li to ensure that SQLite is used in a thread-safe way,
00053  * \li to provide additional threaded quirks, such as delayed updates (not implemented).
00054  * 
00055  * The library is targeted at SQLite setup which is \b not \c -DTHREADSAFE,
00056  * since this is the default setup on UNIX architectures.\n
00057  * \n
00058  * This file is a header-only library,
00059  * whose sole dependencies should be standard STL and posix threading libraries.
00060  * You can extract this file out of the "glim" library to include it separately in your project.\n
00061  * \n
00062  * This library is targeted at UTF-8 API. There is no plans to support the UTF-16 API.\n
00063  * \n
00064  * See also:\n
00065  * \li http://www.sqlite.org/cvstrac/fileview?f=sqlite/src/server.c\n
00066  *     for another way of handling multithreading with SQLite.
00067  */
00068 class Sqlite {
00069   /// No copying allowed.
00070   Sqlite& operator = (const Sqlite& other) {return *this;}
00071   /// No copying allowed.
00072   Sqlite (const Sqlite& other) {}
00073   friend class SqliteSession;
00074   protected:
00075   /// Filename the database was opened with; we need it to reopen the database on fork()s.
00076   /// std::string is used to avoid memory allocation issues.
00077   std::string filename;
00078   ::sqlite3* handler;
00079   ::pthread_mutex_t mutex;
00080   public:
00081   /// Flags for the Sqlite constructor.
00082   enum Flags {
00083     /**
00084      * The file will be checked for existence.
00085      * std::runtime_error is thrown if the file is not accessible;
00086      * format of the error description is "$filename: $strerror".\n
00087      * Usage example: \code Sqlite db ("filename", Sqlite::existing); \endcode
00088      */
00089     existing = 1
00090   };
00091   /**
00092    * Opens the database.
00093    * @param filename Database filename (UTF-8).
00094    * @param flags Optional. Currently there is the #existing flag.
00095    * @throws std::runtime_error Thrown if we can't open the database.
00096    */
00097   Sqlite (std::string filename, int flags = 0) {
00098     if (flags & existing) {
00099       // Check if the file exists already.
00100       struct stat st; if (stat (filename.c_str(), &st))
00101         throw std::runtime_error(filename + ": " + strerror(errno));
00102     }
00103     ::pthread_mutex_init (&mutex, NULL);
00104     this->filename = filename;
00105     if (::sqlite3_open(filename.c_str(), &handler) != SQLITE_OK)
00106       throw std::runtime_error(std::string("sqlite3_open(") + filename + "): " + ::sqlite3_errmsg(handler));
00107   }
00108   /**
00109    * Closes the database.
00110    * @throws std::runtime_error Thrown if we can't close the database.
00111    */
00112   ~Sqlite () {
00113     ::pthread_mutex_destroy (&mutex);
00114     if (::sqlite3_close(handler) != SQLITE_OK)
00115       throw std::runtime_error(std::string ("sqlite3_close(): ") + ::sqlite3_errmsg(handler));
00116   }
00117 };
00118 
00119 /**
00120  * A single thread session with Sqlite.
00121  * Only a sigle thread at a time can have an SqliteSession,
00122  * all other threads will wait, in the SqliteSession constructor,
00123  * till the active session is either closed or destructed.
00124  */
00125 class SqliteSession {
00126   /// No copying allowed.
00127   SqliteSession& operator = (const SqliteSession& other) {return *this;}
00128   /// No copying allowed.
00129   SqliteSession(SqliteSession& other) {}
00130   protected:
00131   Sqlite* db;
00132   public:
00133   /**
00134    * Locks the database.
00135    * @throws std::runtime_error if a mutex error occurs.
00136    */
00137   SqliteSession (Sqlite* sqlite): db (sqlite) {
00138     int err = ::pthread_mutex_lock (&(db->mutex));
00139     if (err != 0) throw std::runtime_error(std::string ("error locking the mutex: ") + strerror(err));
00140   }
00141   /**
00142    * A shorter way to construct query from the session.
00143    * Usage example: \code ses.query(S("create table test (i integer)")).step() \endcode
00144    * @see SqliteQuery#qstep
00145    */
00146   template <typename T>
00147   SqliteQuery query (T t);
00148   /// Automatically unlocks the database.
00149   /// @see close
00150   ~SqliteSession () {close();}
00151   /**
00152    * Unlock the database.
00153    * It is safe to call this method multiple times.\n
00154    * You must not use the session after it was closed.\n
00155    * All resources allocated within this session must be released before the session is closed.
00156    * @throws std::runtime_error if a mutex error occurs.
00157    */
00158   void close () {
00159     if (db == NULL) return;
00160     int err = ::pthread_mutex_unlock (&(db->mutex));
00161     db = NULL;
00162     if (err != 0) throw std::runtime_error(std::string ("error unlocking the mutex: ") + strerror(err));
00163   }
00164   /// True if the \c close method has been already called on this SqliteSession.
00165   bool isClosed () const {
00166     return db == NULL;
00167   }
00168   /**
00169    * This class can be used in place of the SQLite handler.
00170    * Make sure you've released any resources thus manually acquired before this SqliteSession is closed.
00171    * Usage example:
00172    * @code
00173    * glim::Sqlite db (":memory:");
00174    * glim::SqliteSession ses (&db);
00175    * sqlite3_exec (ses, "PRAGMA page_size = 4096;", NULL, NULL, NULL);
00176    * @endcode
00177    */
00178   operator ::sqlite3* () const {return db->handler;}
00179 };
00180 
00181 /**
00182  * Wraps the sqlite3_stmt; will prepare it, bind values, query and finalize.
00183  */
00184 class SqliteQuery {
00185   protected:
00186   ::sqlite3_stmt* statement;
00187   SqliteSession* session;
00188   int bindCounter;
00189   /// -1 if statement isn't DONE.
00190   int mChanges;
00191   void prepare (SqliteSession* session, char const* query, int queryLength) {
00192     ::sqlite3* handler = *session;
00193     if (::sqlite3_prepare (handler, query, queryLength, &statement, NULL) != SQLITE_OK)
00194       throw std::runtime_error(std::string(query, queryLength) + ": " + ::sqlite3_errmsg(handler));
00195   }
00196   public:
00197   /**
00198    * Prepares the query.
00199    * @throws std::runtime_error if sqlite3_prepare fails; format of the error message is "$query: $errmsg".
00200    */
00201   SqliteQuery (SqliteSession* session, char const* query, int queryLength)
00202     : statement (NULL), session (session), bindCounter (0), mChanges (-1) {
00203     prepare (session, query, queryLength);
00204   }
00205   /**
00206    * Prepares the query.
00207    * @throws std::runtime_error if sqlite3_prepare fails; format of the error message is "$query: $errmsg".
00208    */
00209   SqliteQuery (SqliteSession* session, std::pair<char const*, int> query)
00210     : statement (NULL), session (session), bindCounter (0), mChanges (-1) {
00211     prepare (session, query.first, query.second);
00212   }
00213   /**
00214    * Prepares the query.
00215    * @throws std::runtime_error if sqlite3_prepare fails; format of the error message is "$query: $errmsg".
00216    */
00217   SqliteQuery (SqliteSession* session, std::string query)
00218     : statement (NULL), session (session), bindCounter (0), mChanges (-1) {
00219     prepare (session, query.c_str(), query.length());
00220   }
00221   /**
00222    * Release resources.
00223    * @see http://sqlite.org/capi3ref.html#sqlite3_finalize
00224    */
00225   ~SqliteQuery () {
00226     if (statement) ::sqlite3_finalize (statement);
00227   }
00228   
00229   /// Call this (followed by the #step) if you need the query to be re-executed.
00230   /// @see http://sqlite.org/capi3ref.html#sqlite3_reset
00231   SqliteQuery& reset () {
00232     bindCounter = 0;
00233     mChanges = -1;
00234     ::sqlite3_reset (statement);
00235     return *this;
00236   }
00237   
00238   /// Synonym for #step.
00239   bool next () {return step();}
00240   /**
00241    * Invokes sqlite3_step.
00242    * @return \c true if there was a row fetched successfully, \c false if there is no more rows.
00243    * @see http://sqlite.org/capi3ref.html#sqlite3_step
00244    */
00245   bool step () {
00246     if (mChanges >= 0) {mChanges = 0; return false;}
00247     int ret = ::sqlite3_step (statement);
00248     if (ret == SQLITE_ROW) return true;
00249     if (ret == SQLITE_DONE) {
00250       mChanges = ::sqlite3_changes (*session);
00251       return false;
00252     }
00253     throw std::runtime_error (std::string(::sqlite3_errmsg(*session)));
00254   }
00255   /**
00256    * Perform #step and throw an exception if #step has returned \c false.
00257    * Usage example:
00258    * \code (ses.query(S("select count(*) from test where idx = ?")) << 12345).qstep().intAt(1) \endcode
00259    */
00260   SqliteQuery& qstep () {
00261     if (!step())
00262       throw std::runtime_error (std::string("qstep: no rows returned / affected"));
00263     return *this;
00264   }
00265   /**
00266    * Invokes a DML query and returns the number of rows affected.
00267    * Example: \code
00268    * int affected = (ses.query(S("update test set count = count + ? where id = ?")) << 1 << 9).ustep();
00269    * \endcode
00270    * @see http://sqlite.org/capi3ref.html#sqlite3_step
00271    */
00272   int ustep () {
00273     int ret = ::sqlite3_step (statement);
00274     if (ret == SQLITE_DONE) {
00275       mChanges = ::sqlite3_changes (*session);
00276       return mChanges;
00277     }
00278     if (ret == SQLITE_ROW) return 0;
00279     throw std::runtime_error (std::string(::sqlite3_errmsg(*session)));
00280   }
00281   
00282   /**
00283    * The number of rows changed by the query. 
00284    * Providing the query was a DML (Data Modification Language),
00285    * returns the number of rows updated.\n
00286    * If the query wasn't a DML, returned value is undefined.\n
00287    * -1 is returned if the query wasn't executed, or after #reset.\n
00288    * Example: \code
00289    * SqliteQuery query (&ses, S("update test set count = count + ? where id = ?"));
00290    * query.bind (1, 1);
00291    * query.bind (2, 9);
00292    * query.step ();
00293    * int affected = query.changes ();
00294    * \endcode
00295    * @see #ustep
00296    */
00297   int changes () {return mChanges;}
00298   
00299   /**
00300    * The integer value of the given column.
00301    * @param column 1-based.
00302    * @see http://sqlite.org/capi3ref.html#sqlite3_column_text
00303    */
00304   int intAt (int column) {
00305     return ::sqlite3_column_int (statement, --column);
00306   }
00307   
00308   /**
00309    * The integer value of the given column.
00310    * @param column 1-based.
00311    * @see http://sqlite.org/capi3ref.html#sqlite3_column_text
00312    */
00313   int64_t int64at (int column) {
00314     return (int64_t) ::sqlite3_column_int64 (statement, --column);
00315   }
00316   
00317   /**
00318    * The floating point number from the given column.
00319    * @param column 1-based.
00320    * @see http://sqlite.org/capi3ref.html#sqlite3_column_text
00321    */
00322   double doubleAt (int column) {
00323     return ::sqlite3_column_double (statement, --column);
00324   }
00325   
00326   /**
00327    * Return the column as UTF-8 characters, which can be used until the next #step.
00328    * @param column 1-based.
00329    * @see http://sqlite.org/capi3ref.html#sqlite3_column_text
00330    */
00331   std::pair<char const*, int> charsAt (int column) {
00332     return std::pair<char const*, int> ((char const*) ::sqlite3_column_text (statement, column-1),
00333                                         ::sqlite3_column_bytes (statement, column-1));
00334   }
00335   
00336   /**
00337    * Return the column as C++ string (UTF-8).
00338    * @param column 1-based.
00339    */
00340   std::string stringAt (int column) {
00341     return std::string ((char const*) ::sqlite3_column_text (statement, column-1),
00342                         ::sqlite3_column_bytes (statement, column-1));
00343   }
00344   
00345   /**
00346    * The type of the column.
00347    * SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB or SQLITE_NULL.
00348    * @param column 1-based.
00349    * @see http://sqlite.org/capi3ref.html#sqlite3_column_text
00350    */
00351   int typeAt (int column) {
00352     return ::sqlite3_column_type (statement, --column);
00353   }
00354   
00355   /**
00356    * Binds a value using one of the bind methods.
00357    */
00358   template<typename T>
00359   SqliteQuery& operator << (T value) {
00360     return bind (++bindCounter, value);
00361   }
00362   /**
00363    * Binds a value using the named parameter and one of the bind methods.
00364    * @throws std::runtime_error if the name could not be found.
00365    * @see http://sqlite.org/capi3ref.html#sqlite3_bind_parameter_index
00366    */
00367   template<typename T>
00368   SqliteQuery& bind (char const* name, T value) {
00369     int index = ::sqlite3_bind_parameter_index (statement, name);
00370     if (index == 0)
00371       throw std::runtime_error (std::string ("No such parameter in the query: ") + name);
00372     return bind (index, value);
00373   }
00374   
00375   /**
00376    * Bind a string to the query.
00377    * @param transient must be true, if lifetime of the string might be shorter than that of the query.
00378    */
00379   SqliteQuery& bind (int index, const char* text, int length, bool transient = false) {
00380     if (::sqlite3_bind_text (statement, index, text, length,
00381                              transient ? SQLITE_TRANSIENT : SQLITE_STATIC) != SQLITE_OK)
00382       throw std::runtime_error (std::string (::sqlite3_errmsg (*session)));
00383     return *this;
00384   }
00385   /**
00386    * Bind a string to the query.
00387    * @param transient must be true, if lifetime of the string might be shorter than that of the query.
00388    */
00389   SqliteQuery& bind (int index, std::pair<const char*, int> text, bool transient = false) {
00390     if (::sqlite3_bind_text (statement, index, text.first, text.second,
00391                              transient ? SQLITE_TRANSIENT : SQLITE_STATIC) != SQLITE_OK)
00392       throw std::runtime_error (std::string (::sqlite3_errmsg (*session)));
00393     return *this;
00394   }
00395   /**
00396    * Bind a string to the query.
00397    * @param transient must be true, if lifetime of the string might be shorter than that of the query.
00398    */
00399   SqliteQuery& bind (int index, std::string text, bool transient = true) {
00400     if (::sqlite3_bind_text (statement, index, text.c_str(), text.length(),
00401                              transient ? SQLITE_TRANSIENT : SQLITE_STATIC) != SQLITE_OK)
00402       throw std::runtime_error (std::string (::sqlite3_errmsg (*session)));
00403     return *this;
00404   }
00405   /**
00406    * Bind an integer to the query.
00407    */
00408   SqliteQuery& bind (int index, int value) {
00409     if (::sqlite3_bind_int (statement, index, value) != SQLITE_OK)
00410       throw std::runtime_error (std::string (::sqlite3_errmsg (*session)));
00411     return *this;
00412   }
00413   /**
00414    * Bind an 64-bit integer to the query.
00415    */
00416   SqliteQuery& bind (int index, long long int value) {
00417     if (::sqlite3_bind_int (statement, index, value) != SQLITE_OK)
00418       throw std::runtime_error (std::string (::sqlite3_errmsg (*session)));
00419     return *this;
00420   }
00421 };
00422 
00423 /**
00424  * Version of SqliteQuery suitable for using SQLite in parallel with other processes.
00425  * Will automatically handle the SQLITE_SCHEMA error
00426  * and will automatically repeat attempts after SQLITE_BUSY,
00427  * but it requires that the query string supplied
00428  * is constant and available during the SqliteParQuery lifetime.
00429  * Error messages, contained in exceptions, may differ from SqliteQuery by containing the query
00430  * (for example, the #step method will throw "$query: $errmsg" instead of just "$errmsg").
00431  */
00432 class SqliteParQuery: public SqliteQuery {
00433   protected:
00434   char const* query;
00435   int queryLength;
00436   int repeat;
00437   int wait;
00438   public:
00439   /**
00440    * Prepares the query.
00441    * @param repeat the number of times we try to repeat the query when SQLITE_BUSY is returned.
00442    * @param wait how long, in milliseconds (1/1000 of a second) we are to wait before repeating.
00443    * @throws std::runtime_error if sqlite3_prepare fails; format of the error message is "$query: $errmsg".
00444    */
00445   SqliteParQuery (SqliteSession* session, char const* query, int queryLength, int repeat = 90, int wait = 20)
00446     : SqliteQuery (session, query, queryLength) {
00447     this->query = query;
00448     this->queryLength = queryLength;
00449     this->repeat = repeat;
00450     this->wait = wait;
00451   }
00452   /**
00453    * Prepares the query.
00454    * @param query the SQL query together with its length.
00455    * @param repeat the number of times we try to repeat the query when SQLITE_BUSY is returned.
00456    * @param wait how long, in milliseconds (1/1000 of a second) we are to wait before repeating.
00457    * @throws std::runtime_error if sqlite3_prepare fails; format of the error message is "$query: $errmsg".
00458    */
00459   SqliteParQuery (SqliteSession* session, std::pair<char const*, int> query, int repeat = 90, int wait = 20)
00460     : SqliteQuery (session, query) {
00461     this->query = query.first;
00462     this->queryLength = query.second;
00463     this->repeat = repeat;
00464     this->wait = wait;
00465   }
00466   
00467   bool next () {return step();}
00468   bool step () {
00469     if (mChanges >= 0) {mChanges = 0; return false;}
00470     repeat:
00471     int ret = ::sqlite3_step (statement);
00472     if (ret == SQLITE_ROW) return true;
00473     if (ret == SQLITE_DONE) {
00474       mChanges = ::sqlite3_changes (*session);
00475       return false;
00476     }
00477     if (ret == SQLITE_SCHEMA) {
00478       ::sqlite3_stmt* old = statement;
00479       prepare (session, query, queryLength);
00480       ::sqlite3_transfer_bindings(old, statement);
00481       ::sqlite3_finalize (old);
00482       goto repeat;
00483     }
00484     if (ret == SQLITE_BUSY) for (int repeat = this->repeat; ret == SQLITE_BUSY;) {
00485       //struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = wait * 1000000; // nan is 10^-9 of sec.
00486       //while (::nanosleep (&ts, &ts) == EINTR);
00487       ::sqlite3_sleep (wait);
00488       ret = ::sqlite3_step (statement);
00489     }
00490     throw std::runtime_error (std::string(query, queryLength) + ::sqlite3_errmsg(*session));
00491   }
00492 };
00493 
00494 template <typename T>
00495 SqliteQuery SqliteSession::query (T t) {
00496   return SqliteQuery (this, t);
00497 }
00498 
00499 }; // namespace glim
00500 
00501 #endif // GLIM_SQLITE_HPP_

Generated on Fri Nov 24 20:57:37 2006 for libglim by  doxygen 1.4.6