]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_utilities/lib/sqlite++.h
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_utilities / lib / sqlite++.h
diff --git a/libsecurity_utilities/lib/sqlite++.h b/libsecurity_utilities/lib/sqlite++.h
new file mode 100644 (file)
index 0000000..1db59aa
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2008 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+//
+// sqlite++ - C++ interface to SQLite3
+//
+#ifndef _H_SQLITEPP
+#define _H_SQLITEPP
+
+#include <sqlite3.h>
+#include <security_utilities/errors.h>
+#include <security_utilities/threading.h>
+#include <CoreFoundation/CFData.h>
+
+
+namespace Security {
+namespace SQLite3 {
+
+class Database;
+class Statement;
+
+typedef sqlite3_int64 int64;
+typedef sqlite3_uint64 uint64;
+
+
+//
+// An sqlite3 error
+//
+class Error : public CommonError {
+public:
+       Error(Database &db);
+       Error(int err) : error(err) { }
+       Error(int err, const char *msg) : error(err), message(msg) { }
+       ~Error() throw () { }
+       const int error;
+       const std::string message;
+       
+       const char *what() const throw () { return message.c_str(); }
+    OSStatus osStatus() const;
+       int unixError() const;
+       
+       static void check(int err);
+       static void throwMe(int err) __attribute__((noreturn));
+};
+
+
+//
+// An sqlite3 database "connection"
+//
+class Database {
+       friend class Statement;
+public:
+       Database(const char *path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+       virtual ~Database();
+       
+       void close();
+       
+       // open flags
+       int openFlags() const { return mOpenFlags; }
+       
+       // last error condition encountered
+       int errcode();
+       const char *errmsg();
+       
+       bool inTransaction();
+       int64 lastInsert();
+       int changes();
+       
+       void interrupt();
+       
+       int execute(const char *text, bool strict = true);
+       int execute(const std::string &text, bool strict = true)
+               { return execute(text.c_str(), strict); }
+       
+       bool empty();
+       
+       template <class RType> RType value(const char *text, RType defaultResult = RType());
+       template <class RType> RType value(const std::string &text, RType defaultResult = RType())
+               { return value(text.c_str(), defaultResult); }
+       
+       double julianNow()
+               { return this->value<double>("SELECT JULIANDAY('now');"); }
+       
+       void busyDelay(int ms);
+
+       void check(int err);
+       
+       sqlite3 *sql() const { return mDb; }
+
+private:
+       sqlite3 *mDb;
+       Mutex mMutex;
+       int mOpenFlags;
+};
+
+
+//
+// An sqlite column value.
+// These are definitely not first-class API objects; in particular,
+// there doesn't seem to be API to actually *make* one - you can only
+// get them out of sqlite.
+//
+class Value {
+public:
+       Value(sqlite3_value *v) : mValue(v) { }
+
+       operator int () const { return ::sqlite3_value_int(mValue); }
+       operator sqlite3_int64 () const { return ::sqlite3_value_int64(mValue); }
+       operator const char * () const { return (const char *)::sqlite3_value_text(mValue); }
+       operator double () const { return ::sqlite3_value_double(mValue); }
+       
+       int type() const { return ::sqlite3_value_type(mValue); }
+       int numericType() const { return ::sqlite3_value_numeric_type(mValue); }
+       
+       operator bool () const { return type() != SQLITE_NULL; }
+       bool operator ! () const { return type() == SQLITE_NULL; }
+       
+       sqlite3_value *sql() const { return mValue; }
+
+private:
+       sqlite3_value *mValue;
+};
+
+
+//
+// A Transaction proxy.
+//
+class Transaction {
+public:        
+       enum Type {
+               deferred,
+               immediate,
+               exclusive
+       };
+
+public:
+       Transaction(Database &db, Type type = deferred, const char *name = NULL);
+       virtual ~Transaction();
+       
+       void commit();
+       void abort();
+       void rollback() { this->abort(); }
+       
+       Database &database;
+
+protected:
+       void xactCommand(const std::string &s);
+
+private:
+       std::string mName;
+};
+
+
+//
+// A (prepared) statement.
+//
+class Statement : private StLock<Mutex> {
+       class Binding;
+       
+public:
+       Statement(Database &db, const char *text);      // ready to serve
+       Statement(Database &db);                                                // quiescent; call query(text) to activate it
+       virtual ~Statement();
+       
+       Database &database;
+
+       operator bool () const { return mStmt != NULL; } // active
+       
+       void query(const char *text);                                   // activate statement with query text
+       void query(const std::string &text)
+               { query(text.c_str()); }
+       void close();                                                                   // close up active statement
+
+       Binding bind(int ix) const { return Binding(*this, ix); }
+       Binding bind(const char *name) const;
+       unsigned int bindings() const { return ::sqlite3_bind_parameter_count(mStmt); }
+       void unbind();
+
+       int step();
+       void execute();
+       bool nextRow();
+       bool operator () () { return nextRow(); }
+
+       void reset();
+       
+       class Result;
+       Result operator [] (int ix) { return Result(*this, ix); }
+       unsigned int count() const { return ::sqlite3_column_count(mStmt); }
+       
+       void check(int err) const { database.check(err); }
+       sqlite3_stmt *sql() const { return mStmt; }
+
+private:
+       class Column {
+       public:
+               Column(const Statement &st, int ix) : statement(st), index(ix) { }
+               
+               const Statement &statement;
+               const int index;
+       };
+       
+       class Binding : public Column {
+       public:
+               Binding(const Statement &st, int ix) : Column(st, ix) { }
+               
+               const char *name() const;
+               
+               void null();
+               void operator = (int value);
+               void operator = (sqlite3_int64 value);
+               void operator = (double value);
+               void operator = (const char *value);
+               void operator = (const std::string &value);
+               void operator = (const Value &value);
+               void integer(sqlite3_int64 value);
+               void blob(const void *data, size_t length, bool shared = false);
+               void operator = (CFDataRef data);
+               void operator = (CFStringRef value);
+       };
+       
+public:
+       class Result : public Column {
+       public:
+               Result(const Statement &st, int ix) : Column(st, ix) { }
+               
+               const char *name() const;
+               
+               operator int () const { return ::sqlite3_column_int(statement.sql(), index); }
+               operator sqlite3_int64 () const { return ::sqlite3_column_int64(statement.sql(), index); }
+               operator double () const { return ::sqlite3_column_double(statement.sql(), index); }
+               const char *string() const { return (const char *)::sqlite3_column_text(statement.sql(), index); }
+               operator const char *() const { return this->string(); }
+               const void *blob() const { return ::sqlite3_column_blob(statement.sql(), index); }
+               int length() const { return ::sqlite3_column_bytes(statement.sql(), index); }
+               CFDataRef data() const;
+               
+               int type() const { return ::sqlite3_column_type(statement.sql(), index); }
+               const char *declType() const { return ::sqlite3_column_decltype(statement.sql(), index); }
+       
+               operator bool () const { return type() != SQLITE_NULL; }
+               bool operator ! () const { return type() == SQLITE_NULL; }
+       };
+
+private:
+       sqlite3_stmt *mStmt;
+};
+
+
+template <class RType>
+RType Database::value(const char *text, RType defaultResult)
+{
+       Statement stmt(*this, text);
+       if (stmt())
+               return RType(stmt[0]);
+       else
+               return defaultResult;
+}
+
+
+
+} // SQLite3
+}      // Security
+
+#endif //_H_SQLITEPP