1/* 2 * Copyright (c) 2008 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23// 24// sqlite++ - C++ interface to SQLite3 25// 26#ifndef _H_SQLITEPP 27#define _H_SQLITEPP 28 29#include <sqlite3.h> 30#include <security_utilities/errors.h> 31#include <security_utilities/threading.h> 32#include <CoreFoundation/CFData.h> 33 34 35namespace Security { 36namespace SQLite3 { 37 38class Database; 39class Statement; 40 41typedef sqlite3_int64 int64; 42typedef sqlite3_uint64 uint64; 43 44 45// 46// An sqlite3 error 47// 48class Error : public CommonError { 49public: 50 Error(Database &db); 51 Error(int err) : error(err) { } 52 Error(int err, const char *msg) : error(err), message(msg) { } 53 ~Error() throw () { } 54 const int error; 55 const std::string message; 56 57 const char *what() const throw () { return message.c_str(); } 58 OSStatus osStatus() const; 59 int unixError() const; 60 61 static void check(int err); 62 static void throwMe(int err) __attribute__((noreturn)); 63}; 64 65 66// 67// An sqlite3 database "connection" 68// 69class Database { 70 friend class Statement; 71public: 72 Database(const char *path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, bool lenient = false); 73 virtual ~Database(); 74 75 bool isOpen() const { return mDb != NULL; } 76 void close(); 77 78 // open flags 79 int openFlags() const { return mOpenFlags; } 80 81 // last error condition encountered 82 int errcode(); 83 const char *errmsg(); 84 85 bool inTransaction(); 86 int64 lastInsert(); 87 int changes(); 88 89 void interrupt(); 90 91 int execute(const char *text, bool strict = true); 92 int execute(const std::string &text, bool strict = true) 93 { return execute(text.c_str(), strict); } 94 95 bool empty(); 96 97 template <class RType> RType value(const char *text, RType defaultResult = RType()); 98 template <class RType> RType value(const std::string &text, RType defaultResult = RType()) 99 { return value(text.c_str(), defaultResult); } 100 101 double julianNow() 102 { return this->value<double>("SELECT JULIANDAY('now');"); } 103 104 void busyDelay(int ms); 105 106 void check(int err); 107 108 sqlite3 *sql() const { return mDb; } 109 110private: 111 sqlite3 *mDb; 112 Mutex mMutex; 113 int mOpenFlags; 114}; 115 116 117// 118// An sqlite column value. 119// These are definitely not first-class API objects; in particular, 120// there doesn't seem to be API to actually *make* one - you can only 121// get them out of sqlite. 122// 123class Value { 124public: 125 Value(sqlite3_value *v) : mValue(v) { } 126 127 operator int () const { return ::sqlite3_value_int(mValue); } 128 operator sqlite3_int64 () const { return ::sqlite3_value_int64(mValue); } 129 operator const char * () const { return (const char *)::sqlite3_value_text(mValue); } 130 operator double () const { return ::sqlite3_value_double(mValue); } 131 132 int type() const { return ::sqlite3_value_type(mValue); } 133 int numericType() const { return ::sqlite3_value_numeric_type(mValue); } 134 135 operator bool () const { return type() != SQLITE_NULL; } 136 bool operator ! () const { return type() == SQLITE_NULL; } 137 138 sqlite3_value *sql() const { return mValue; } 139 140private: 141 sqlite3_value *mValue; 142}; 143 144 145// 146// A Transaction proxy. 147// 148class Transaction { 149public: 150 enum Type { 151 deferred, 152 immediate, 153 exclusive 154 }; 155 156public: 157 Transaction(Database &db, Type type = deferred, const char *name = NULL); 158 virtual ~Transaction(); 159 160 void commit(); 161 void abort(); 162 void rollback() { this->abort(); } 163 164 Database &database; 165 166protected: 167 void xactCommand(const std::string &s); 168 169private: 170 std::string mName; 171}; 172 173 174// 175// A (prepared) statement. 176// 177class Statement : private StLock<Mutex> { 178 class Binding; 179 180public: 181 Statement(Database &db, const char *text); // ready to serve 182 Statement(Database &db); // quiescent; call query(text) to activate it 183 virtual ~Statement(); 184 185 Database &database; 186 187 operator bool () const { return mStmt != NULL; } // active 188 189 void query(const char *text); // activate statement with query text 190 void query(const std::string &text) 191 { query(text.c_str()); } 192 void close(); // close up active statement 193 194 Binding bind(int ix) const { return Binding(*this, ix); } 195 Binding bind(const char *name) const; 196 unsigned int bindings() const { return ::sqlite3_bind_parameter_count(mStmt); } 197 void unbind(); 198 199 int step(); 200 void execute(); 201 bool nextRow(); 202 bool operator () () { return nextRow(); } 203 204 void reset(); 205 206 class Result; 207 Result operator [] (int ix) { return Result(*this, ix); } 208 unsigned int count() const { return ::sqlite3_column_count(mStmt); } 209 210 void check(int err) const { database.check(err); } 211 sqlite3_stmt *sql() const { return mStmt; } 212 213private: 214 class Column { 215 public: 216 Column(const Statement &st, int ix) : statement(st), index(ix) { } 217 218 const Statement &statement; 219 const int index; 220 }; 221 222 class Binding : public Column { 223 public: 224 Binding(const Statement &st, int ix) : Column(st, ix) { } 225 226 const char *name() const; 227 228 void null(); 229 void operator = (int value); 230 void operator = (sqlite3_int64 value); 231 void operator = (double value); 232 void operator = (const char *value); 233 void operator = (const std::string &value); 234 void operator = (const Value &value); 235 void integer(sqlite3_int64 value); 236 void blob(const void *data, size_t length, bool shared = false); 237 void operator = (CFDataRef data); 238 void operator = (CFStringRef value); 239 }; 240 241public: 242 class Result : public Column { 243 public: 244 Result(const Statement &st, int ix) : Column(st, ix) { } 245 246 const char *name() const; 247 248 operator int () const { return ::sqlite3_column_int(statement.sql(), index); } 249 operator sqlite3_int64 () const { return ::sqlite3_column_int64(statement.sql(), index); } 250 operator double () const { return ::sqlite3_column_double(statement.sql(), index); } 251 const char *string() const { return (const char *)::sqlite3_column_text(statement.sql(), index); } 252 operator const char *() const { return this->string(); } 253 const void *blob() const { return ::sqlite3_column_blob(statement.sql(), index); } 254 int length() const { return ::sqlite3_column_bytes(statement.sql(), index); } 255 CFDataRef data() const; 256 257 int type() const { return ::sqlite3_column_type(statement.sql(), index); } 258 const char *declType() const { return ::sqlite3_column_decltype(statement.sql(), index); } 259 260 operator bool () const { return type() != SQLITE_NULL; } 261 bool operator ! () const { return type() == SQLITE_NULL; } 262 }; 263 264private: 265 sqlite3_stmt *mStmt; 266}; 267 268 269template <class RType> 270RType Database::value(const char *text, RType defaultResult) 271{ 272 Statement stmt(*this, text); 273 if (stmt()) 274 return RType(stmt[0]); 275 else 276 return defaultResult; 277} 278 279 280 281} // SQLite3 282} // Security 283 284#endif //_H_SQLITEPP 285