]> git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/sqlite++.h
1db59aaa7e434efa3c48e6fb74915a8b7f31dc0a
[apple/security.git] / libsecurity_utilities / lib / sqlite++.h
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
35 namespace Security {
36 namespace SQLite3 {
37
38 class Database;
39 class Statement;
40
41 typedef sqlite3_int64 int64;
42 typedef sqlite3_uint64 uint64;
43
44
45 //
46 // An sqlite3 error
47 //
48 class Error : public CommonError {
49 public:
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 //
69 class Database {
70 friend class Statement;
71 public:
72 Database(const char *path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
73 virtual ~Database();
74
75 void close();
76
77 // open flags
78 int openFlags() const { return mOpenFlags; }
79
80 // last error condition encountered
81 int errcode();
82 const char *errmsg();
83
84 bool inTransaction();
85 int64 lastInsert();
86 int changes();
87
88 void interrupt();
89
90 int execute(const char *text, bool strict = true);
91 int execute(const std::string &text, bool strict = true)
92 { return execute(text.c_str(), strict); }
93
94 bool empty();
95
96 template <class RType> RType value(const char *text, RType defaultResult = RType());
97 template <class RType> RType value(const std::string &text, RType defaultResult = RType())
98 { return value(text.c_str(), defaultResult); }
99
100 double julianNow()
101 { return this->value<double>("SELECT JULIANDAY('now');"); }
102
103 void busyDelay(int ms);
104
105 void check(int err);
106
107 sqlite3 *sql() const { return mDb; }
108
109 private:
110 sqlite3 *mDb;
111 Mutex mMutex;
112 int mOpenFlags;
113 };
114
115
116 //
117 // An sqlite column value.
118 // These are definitely not first-class API objects; in particular,
119 // there doesn't seem to be API to actually *make* one - you can only
120 // get them out of sqlite.
121 //
122 class Value {
123 public:
124 Value(sqlite3_value *v) : mValue(v) { }
125
126 operator int () const { return ::sqlite3_value_int(mValue); }
127 operator sqlite3_int64 () const { return ::sqlite3_value_int64(mValue); }
128 operator const char * () const { return (const char *)::sqlite3_value_text(mValue); }
129 operator double () const { return ::sqlite3_value_double(mValue); }
130
131 int type() const { return ::sqlite3_value_type(mValue); }
132 int numericType() const { return ::sqlite3_value_numeric_type(mValue); }
133
134 operator bool () const { return type() != SQLITE_NULL; }
135 bool operator ! () const { return type() == SQLITE_NULL; }
136
137 sqlite3_value *sql() const { return mValue; }
138
139 private:
140 sqlite3_value *mValue;
141 };
142
143
144 //
145 // A Transaction proxy.
146 //
147 class Transaction {
148 public:
149 enum Type {
150 deferred,
151 immediate,
152 exclusive
153 };
154
155 public:
156 Transaction(Database &db, Type type = deferred, const char *name = NULL);
157 virtual ~Transaction();
158
159 void commit();
160 void abort();
161 void rollback() { this->abort(); }
162
163 Database &database;
164
165 protected:
166 void xactCommand(const std::string &s);
167
168 private:
169 std::string mName;
170 };
171
172
173 //
174 // A (prepared) statement.
175 //
176 class Statement : private StLock<Mutex> {
177 class Binding;
178
179 public:
180 Statement(Database &db, const char *text); // ready to serve
181 Statement(Database &db); // quiescent; call query(text) to activate it
182 virtual ~Statement();
183
184 Database &database;
185
186 operator bool () const { return mStmt != NULL; } // active
187
188 void query(const char *text); // activate statement with query text
189 void query(const std::string &text)
190 { query(text.c_str()); }
191 void close(); // close up active statement
192
193 Binding bind(int ix) const { return Binding(*this, ix); }
194 Binding bind(const char *name) const;
195 unsigned int bindings() const { return ::sqlite3_bind_parameter_count(mStmt); }
196 void unbind();
197
198 int step();
199 void execute();
200 bool nextRow();
201 bool operator () () { return nextRow(); }
202
203 void reset();
204
205 class Result;
206 Result operator [] (int ix) { return Result(*this, ix); }
207 unsigned int count() const { return ::sqlite3_column_count(mStmt); }
208
209 void check(int err) const { database.check(err); }
210 sqlite3_stmt *sql() const { return mStmt; }
211
212 private:
213 class Column {
214 public:
215 Column(const Statement &st, int ix) : statement(st), index(ix) { }
216
217 const Statement &statement;
218 const int index;
219 };
220
221 class Binding : public Column {
222 public:
223 Binding(const Statement &st, int ix) : Column(st, ix) { }
224
225 const char *name() const;
226
227 void null();
228 void operator = (int value);
229 void operator = (sqlite3_int64 value);
230 void operator = (double value);
231 void operator = (const char *value);
232 void operator = (const std::string &value);
233 void operator = (const Value &value);
234 void integer(sqlite3_int64 value);
235 void blob(const void *data, size_t length, bool shared = false);
236 void operator = (CFDataRef data);
237 void operator = (CFStringRef value);
238 };
239
240 public:
241 class Result : public Column {
242 public:
243 Result(const Statement &st, int ix) : Column(st, ix) { }
244
245 const char *name() const;
246
247 operator int () const { return ::sqlite3_column_int(statement.sql(), index); }
248 operator sqlite3_int64 () const { return ::sqlite3_column_int64(statement.sql(), index); }
249 operator double () const { return ::sqlite3_column_double(statement.sql(), index); }
250 const char *string() const { return (const char *)::sqlite3_column_text(statement.sql(), index); }
251 operator const char *() const { return this->string(); }
252 const void *blob() const { return ::sqlite3_column_blob(statement.sql(), index); }
253 int length() const { return ::sqlite3_column_bytes(statement.sql(), index); }
254 CFDataRef data() const;
255
256 int type() const { return ::sqlite3_column_type(statement.sql(), index); }
257 const char *declType() const { return ::sqlite3_column_decltype(statement.sql(), index); }
258
259 operator bool () const { return type() != SQLITE_NULL; }
260 bool operator ! () const { return type() == SQLITE_NULL; }
261 };
262
263 private:
264 sqlite3_stmt *mStmt;
265 };
266
267
268 template <class RType>
269 RType Database::value(const char *text, RType defaultResult)
270 {
271 Statement stmt(*this, text);
272 if (stmt())
273 return RType(stmt[0]);
274 else
275 return defaultResult;
276 }
277
278
279
280 } // SQLite3
281 } // Security
282
283 #endif //_H_SQLITEPP