]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/sqlite++.cpp
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / sqlite++.cpp
1 /*
2 * Copyright (c) 2008,2011-2012,2014 Apple 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, bool lenient /* = false */)
102 : mMutex(Mutex::recursive)
103 {
104 try {
105 int rc = ::sqlite3_open_v2(path, &mDb, flags, NULL);
106 if (rc != SQLITE_OK && lenient) { // silent open failure
107 sqlite3_close(mDb); // ditch useless Db object
108 mDb = NULL; // indicate failure
109 return;
110 }
111 check(rc);
112 check(::sqlite3_extended_result_codes(mDb, true));
113 mOpenFlags = flags;
114 } catch (...) {
115 sqlite3_close(mDb); // allocated even if open fails(!)
116 throw;
117 }
118 }
119
120 Database::~Database()
121 {
122 this->close();
123 }
124
125 void Database::close()
126 {
127 if (mDb)
128 check(::sqlite3_close(mDb));
129 }
130
131
132 int Database::execute(const char *text, bool strict /* = true */)
133 {
134 StLock<Mutex> _(mMutex);
135
136 int rc = ::sqlite3_exec(mDb, text, NULL, NULL, NULL);
137 if (strict)
138 check(rc);
139 return rc;
140 }
141
142
143 void Database::busyDelay(int ms)
144 {
145 StLock<Mutex> _(mMutex);
146
147 check(::sqlite3_busy_timeout(mDb, ms));
148 }
149
150
151 void Database::check(int err)
152 {
153 if (err)
154 throw Error(*this);
155 }
156
157
158 bool Database::empty()
159 {
160 return value("select count(*) from sqlite_master;", 0) == 0;
161 }
162
163
164 int Database::errcode()
165 {
166 StLock<Mutex> _(mMutex);
167
168 return sqlite3_errcode(mDb);
169 }
170
171
172
173 const char *Database::errmsg()
174 {
175 StLock<Mutex> _(mMutex);
176
177 return sqlite3_errmsg(mDb);
178 }
179
180
181
182 bool Database::inTransaction()
183 {
184 StLock<Mutex> _(mMutex);
185
186 return !::sqlite3_get_autocommit(mDb);
187 }
188
189
190
191 int64 Database::lastInsert()
192 {
193 StLock<Mutex> _(mMutex);
194
195 return ::sqlite3_last_insert_rowid(mDb);
196 }
197
198 int Database::changes()
199 {
200 StLock<Mutex> _(mMutex);
201
202 return ::sqlite3_changes(mDb);
203 }
204
205 void Database::interrupt()
206 {
207 StLock<Mutex> _(mMutex);
208
209 ::sqlite3_interrupt(mDb);
210 }
211
212 //
213 // Transaction managers
214 //
215 Transaction::Transaction(Database &db, Type type, const char *name)
216 : database(db), mName(name ? name : "")
217 {
218 switch (type) {
219 case deferred: xactCommand("BEGIN DEFERRED"); break;
220 case immediate: xactCommand("BEGIN IMMEDIATE"); break;
221 case exclusive: xactCommand("BEGIN EXCLUSIVE"); break;
222 }
223 }
224
225 Transaction::~Transaction()
226 {
227 if (database.inTransaction()) {
228 // request rollback but ignore any errors
229 database.execute("ROLLBACK TRANSACTION", false);
230 }
231 }
232
233 void Transaction::commit()
234 {
235 xactCommand("COMMIT");
236 }
237
238 void Transaction::abort()
239 {
240 xactCommand("ROLLBACK");
241 }
242
243 void Transaction::xactCommand(const string &cmd)
244 {
245 database.execute(cmd + " TRANSACTION " + mName + ";");
246 }
247
248
249 //
250 // Statement objects
251 //
252 Statement::Statement(Database &db, const char *text)
253 : StLock<Mutex>(db.mMutex), database(db), mStmt(NULL)
254 {
255 this->query(text);
256 }
257
258 Statement::Statement(Database &db)
259 : StLock<Mutex>(db.mMutex), database(db), mStmt(NULL)
260 { }
261
262 void Statement::query(const char *text)
263 {
264 this->close();
265 const char *tail;
266 check(::sqlite3_prepare_v2(database.sql(), text, -1, &mStmt, &tail));
267 if (*tail)
268 throw std::logic_error("multiple statements");
269 }
270
271 void Statement::close()
272 {
273 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
274 // So we eat any error code here, since we can't tell "genuine" errors apart from
275 // errors inherited from the Statement execution.
276 if (mStmt)
277 ::sqlite3_finalize(mStmt);
278 mStmt = NULL;
279 }
280
281 Statement::~Statement()
282 {
283 this->close();
284 }
285
286
287 void Statement::unbind()
288 {
289 check(::sqlite3_clear_bindings(mStmt));
290 }
291
292 void Statement::reset()
293 {
294 check(::sqlite3_reset(mStmt));
295 }
296
297
298 int Statement::step()
299 {
300 return ::sqlite3_step(mStmt);
301 }
302
303 void Statement::execute()
304 {
305 switch (int rc = this->step()) {
306 case SQLITE_DONE:
307 case SQLITE_OK:
308 break;
309 default:
310 check(rc);
311 }
312 }
313
314 bool Statement::nextRow()
315 {
316 switch (int rc = this->step()) {
317 case SQLITE_ROW:
318 return true;
319 case SQLITE_DONE:
320 return false;
321 default:
322 check(rc);
323 return false;
324 }
325 }
326
327
328 //
329 // Binding gluons.
330 //
331 Statement::Binding Statement::bind(const char *name) const
332 {
333 if (int ix = ::sqlite3_bind_parameter_index(mStmt, name))
334 return Binding(*this, ix);
335 else
336 throw std::logic_error("unknown parameter name");
337 }
338
339 void Statement::Binding::null()
340 {
341 statement.check(::sqlite3_bind_null(statement.sql(), index));
342 }
343
344 void Statement::Binding::operator = (const Value &value)
345 {
346 statement.check(::sqlite3_bind_value(statement.sql(), index, value.sql()));
347 }
348
349 void Statement::Binding::operator = (int value)
350 {
351 statement.check(::sqlite3_bind_int(statement.sql(), index, value));
352 }
353
354 void Statement::Binding::operator = (sqlite3_int64 value)
355 {
356 statement.check(::sqlite3_bind_int64(statement.sql(), index, value));
357 }
358
359 void Statement::Binding::integer(sqlite3_int64 value)
360 {
361 statement.check(::sqlite3_bind_int64(statement.sql(), index, value));
362 }
363
364 void Statement::Binding::operator = (double value)
365 {
366 statement.check(::sqlite3_bind_double(statement.sql(), index, value));
367 }
368
369 void Statement::Binding::operator = (const char *value)
370 {
371 if (value == NULL)
372 this->null();
373 else
374 statement.check(::sqlite3_bind_text(statement.sql(), index,
375 ::strdup(value), -1, ::free));
376 }
377
378 void Statement::Binding::operator = (const std::string &value)
379 {
380 statement.check(::sqlite3_bind_text(statement.sql(), index,
381 ::strdup(value.c_str()), -1, ::free));
382 }
383
384 void Statement::Binding::blob(const void *data, size_t length, bool shared /* = false */)
385 {
386 if (data == NULL)
387 this->null();
388 else if (shared) {
389 statement.check(::sqlite3_bind_blob(statement.sql(), index, data, (int)length, NULL));
390 } else if (void *copy = ::malloc(length)) {
391 ::memcpy(copy, data, length);
392 statement.check(::sqlite3_bind_blob(statement.sql(), index,
393 copy, (int)length, ::free));
394 } else
395 throw std::bad_alloc();
396 }
397
398 void Statement::Binding::operator = (CFDataRef data)
399 {
400 if (data)
401 this->blob(CFDataGetBytePtr(data), CFDataGetLength(data));
402 else
403 this->null();
404 }
405
406 void Statement::Binding::operator = (CFStringRef value)
407 {
408 if (value)
409 *this = cfString(value).c_str();
410 else
411 this->null();
412 }
413
414 const char *Statement::Binding::name() const
415 {
416 return sqlite3_bind_parameter_name(statement.sql(), index);
417 }
418
419
420 //
421 // Row/column results
422 //
423 const char *Statement::Result::name() const
424 {
425 return sqlite3_column_name(statement.sql(), index);
426 }
427
428 CFDataRef Statement::Result::data() const
429 {
430 switch (this->type()) {
431 case SQLITE_NULL:
432 return NULL;
433 case SQLITE_BLOB:
434 return makeCFData(this->blob(), this->length());
435 default:
436 throw Error(SQLITE_MISMATCH, "Retrieving data() of non-Blob");
437 }
438 }
439
440
441 } // SQLite3
442 } // Security