]> git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/sqlite++.cpp
Security-55179.1.tar.gz
[apple/security.git] / libsecurity_utilities / lib / sqlite++.cpp
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 #include "sqlite++.h"
27 #include <stdexcept>
28 #include <security_utilities/cfutilities.h>
29
30
31 //@@@
32 // From cssmapple.h - layering break
33 // Where should this go?
34 //@@@
35 #define errSecErrnoBase 100000
36 #define errSecErrnoLimit 100255
37
38
39 namespace Security {
40 namespace SQLite3 {
41
42
43 //
44 // Our exception object
45 //
46 void Error::check(int err)
47 {
48 if (err != SQLITE_OK)
49 throw Error(err);
50 }
51
52 Error::Error(Database &db)
53 : error(db.errcode()), message(db.errmsg())
54 {
55 SECURITY_EXCEPTION_THROW_SQLITE(this, error, (char*)message.c_str());
56 }
57
58 void Error::throwMe(int err)
59 {
60 throw Error(err);
61 }
62
63 OSStatus Error::osStatus() const
64 {
65 return unixError() + errSecErrnoBase;
66 }
67
68 int Error::unixError() const
69 {
70 switch (error) {
71 case SQLITE_PERM:
72 case SQLITE_READONLY:
73 case SQLITE_AUTH:
74 return EACCES;
75 case SQLITE_BUSY:
76 return EAGAIN;
77 case SQLITE_NOMEM:
78 return ENOMEM;
79 case SQLITE_IOERR:
80 return EIO;
81 case SQLITE_FULL:
82 return ENOSPC;
83 case SQLITE_TOOBIG:
84 return EFBIG;
85 case SQLITE_MISMATCH:
86 case SQLITE_MISUSE:
87 return EINVAL;
88 case SQLITE_NOLFS:
89 return ENOTSUP;
90 case SQLITE_RANGE:
91 return EDOM;
92 default:
93 return -1;
94 }
95 }
96
97
98 //
99 // Database objects
100 //
101 Database::Database(const char *path, int flags)
102 : mMutex(Mutex::recursive)
103 {
104 try {
105 check(::sqlite3_open_v2(path, &mDb, flags, NULL));
106 check(::sqlite3_extended_result_codes(mDb, true));
107 mOpenFlags = flags;
108 } catch (...) {
109 sqlite3_close(mDb); // allocated even if open fails(!)
110 throw;
111 }
112 }
113
114 Database::~Database()
115 {
116 this->close();
117 }
118
119 void Database::close()
120 {
121 if (mDb)
122 check(::sqlite3_close(mDb));
123 }
124
125
126 int Database::execute(const char *text, bool strict /* = true */)
127 {
128 StLock<Mutex> _(mMutex);
129
130 int rc = ::sqlite3_exec(mDb, text, NULL, NULL, NULL);
131 if (strict)
132 check(rc);
133 return rc;
134 }
135
136
137 void Database::busyDelay(int ms)
138 {
139 StLock<Mutex> _(mMutex);
140
141 check(::sqlite3_busy_timeout(mDb, ms));
142 }
143
144
145 void Database::check(int err)
146 {
147 if (err)
148 throw Error(*this);
149 }
150
151
152 bool Database::empty()
153 {
154 return value("select count(*) from sqlite_master;", 0) == 0;
155 }
156
157
158 int Database::errcode()
159 {
160 StLock<Mutex> _(mMutex);
161
162 return sqlite3_errcode(mDb);
163 }
164
165
166
167 const char *Database::errmsg()
168 {
169 StLock<Mutex> _(mMutex);
170
171 return sqlite3_errmsg(mDb);
172 }
173
174
175
176 bool Database::inTransaction()
177 {
178 StLock<Mutex> _(mMutex);
179
180 return !::sqlite3_get_autocommit(mDb);
181 }
182
183
184
185 int64 Database::lastInsert()
186 {
187 StLock<Mutex> _(mMutex);
188
189 return ::sqlite3_last_insert_rowid(mDb);
190 }
191
192 int Database::changes()
193 {
194 StLock<Mutex> _(mMutex);
195
196 return ::sqlite3_changes(mDb);
197 }
198
199 void Database::interrupt()
200 {
201 StLock<Mutex> _(mMutex);
202
203 ::sqlite3_interrupt(mDb);
204 }
205
206 //
207 // Transaction managers
208 //
209 Transaction::Transaction(Database &db, Type type, const char *name)
210 : database(db), mName(name ? name : "")
211 {
212 switch (type) {
213 case deferred: xactCommand("BEGIN DEFERRED"); break;
214 case immediate: xactCommand("BEGIN IMMEDIATE"); break;
215 case exclusive: xactCommand("BEGIN EXCLUSIVE"); break;
216 }
217 }
218
219 Transaction::~Transaction()
220 {
221 if (database.inTransaction())
222 abort();
223 }
224
225 void Transaction::commit()
226 {
227 xactCommand("COMMIT");
228 }
229
230 void Transaction::abort()
231 {
232 xactCommand("ROLLBACK");
233 }
234
235 void Transaction::xactCommand(const string &cmd)
236 {
237 database.execute(cmd + " TRANSACTION " + mName + ";");
238 }
239
240
241 //
242 // Statement objects
243 //
244 Statement::Statement(Database &db, const char *text)
245 : StLock<Mutex>(db.mMutex), database(db), mStmt(NULL)
246 {
247 this->query(text);
248 }
249
250 Statement::Statement(Database &db)
251 : StLock<Mutex>(db.mMutex), database(db), mStmt(NULL)
252 { }
253
254 void Statement::query(const char *text)
255 {
256 this->close();
257 const char *tail;
258 check(::sqlite3_prepare_v2(database.sql(), text, -1, &mStmt, &tail));
259 if (*tail)
260 throw std::logic_error("multiple statements");
261 }
262
263 void Statement::close()
264 {
265 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
266 // So we eat any error code here, since we can't tell "genuine" errors apart from
267 // errors inherited from the Statement execution.
268 if (mStmt)
269 ::sqlite3_finalize(mStmt);
270 mStmt = NULL;
271 }
272
273 Statement::~Statement()
274 {
275 this->close();
276 }
277
278
279 void Statement::unbind()
280 {
281 check(::sqlite3_clear_bindings(mStmt));
282 }
283
284 void Statement::reset()
285 {
286 check(::sqlite3_reset(mStmt));
287 }
288
289
290 int Statement::step()
291 {
292 return ::sqlite3_step(mStmt);
293 }
294
295 void Statement::execute()
296 {
297 switch (int rc = this->step()) {
298 case SQLITE_DONE:
299 case SQLITE_OK:
300 break;
301 default:
302 check(rc);
303 }
304 }
305
306 bool Statement::nextRow()
307 {
308 switch (int rc = this->step()) {
309 case SQLITE_ROW:
310 return true;
311 case SQLITE_DONE:
312 return false;
313 default:
314 check(rc);
315 return false;
316 }
317 }
318
319
320 //
321 // Binding gluons.
322 //
323 Statement::Binding Statement::bind(const char *name) const
324 {
325 if (int ix = ::sqlite3_bind_parameter_index(mStmt, name))
326 return Binding(*this, ix);
327 else
328 throw std::logic_error("unknown parameter name");
329 }
330
331 void Statement::Binding::null()
332 {
333 statement.check(::sqlite3_bind_null(statement.sql(), index));
334 }
335
336 void Statement::Binding::operator = (const Value &value)
337 {
338 statement.check(::sqlite3_bind_value(statement.sql(), index, value.sql()));
339 }
340
341 void Statement::Binding::operator = (int value)
342 {
343 statement.check(::sqlite3_bind_int(statement.sql(), index, value));
344 }
345
346 void Statement::Binding::operator = (sqlite3_int64 value)
347 {
348 statement.check(::sqlite3_bind_int64(statement.sql(), index, value));
349 }
350
351 void Statement::Binding::integer(sqlite3_int64 value)
352 {
353 statement.check(::sqlite3_bind_int64(statement.sql(), index, value));
354 }
355
356 void Statement::Binding::operator = (double value)
357 {
358 statement.check(::sqlite3_bind_double(statement.sql(), index, value));
359 }
360
361 void Statement::Binding::operator = (const char *value)
362 {
363 if (value == NULL)
364 this->null();
365 else
366 statement.check(::sqlite3_bind_text(statement.sql(), index,
367 ::strdup(value), -1, ::free));
368 }
369
370 void Statement::Binding::operator = (const std::string &value)
371 {
372 statement.check(::sqlite3_bind_text(statement.sql(), index,
373 ::strdup(value.c_str()), -1, ::free));
374 }
375
376 void Statement::Binding::blob(const void *data, size_t length, bool shared /* = false */)
377 {
378 if (data == NULL)
379 this->null();
380 else if (shared) {
381 statement.check(::sqlite3_bind_blob(statement.sql(), index, data, length, NULL));
382 } else if (void *copy = ::malloc(length)) {
383 ::memcpy(copy, data, length);
384 statement.check(::sqlite3_bind_blob(statement.sql(), index,
385 copy, length, ::free));
386 } else
387 throw std::bad_alloc();
388 }
389
390 void Statement::Binding::operator = (CFDataRef data)
391 {
392 if (data)
393 this->blob(CFDataGetBytePtr(data), CFDataGetLength(data));
394 else
395 this->null();
396 }
397
398 void Statement::Binding::operator = (CFStringRef value)
399 {
400 if (value)
401 *this = cfString(value).c_str();
402 else
403 this->null();
404 }
405
406 const char *Statement::Binding::name() const
407 {
408 return sqlite3_bind_parameter_name(statement.sql(), index);
409 }
410
411
412 //
413 // Row/column results
414 //
415 const char *Statement::Result::name() const
416 {
417 return sqlite3_column_name(statement.sql(), index);
418 }
419
420 CFDataRef Statement::Result::data() const
421 {
422 switch (this->type()) {
423 case SQLITE_NULL:
424 return NULL;
425 case SQLITE_BLOB:
426 return makeCFData(this->blob(), this->length());
427 default:
428 throw Error(SQLITE_MISMATCH, "Retrieving data() of non-Blob");
429 }
430 }
431
432
433 } // SQLite3
434 } // Security