]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/sqlite++.cpp
2 * Copyright (c) 2008,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 // sqlite++ - C++ interface to SQLite3
28 #include <security_utilities/cfutilities.h>
29 #include <security_utilities/debugging_internal.h>
33 // From cssmapple.h - layering break
34 // Where should this go?
36 #define errSecErrnoBase 100000
37 #define errSecErrnoLimit 100255
45 // Our exception object
47 void Error::check(int err
)
53 Error::Error(Database
&db
)
54 : error(db
.errcode()), message(db
.errmsg())
56 SECURITY_EXCEPTION_THROW_SQLITE(this, error
, (char*)message
.c_str());
57 secnotice("security_exception", "sqlite: %d %s",error
, (char*)message
.c_str());
60 void Error::throwMe(int err
)
65 OSStatus
Error::osStatus() const
67 return unixError() + errSecErrnoBase
;
70 int Error::unixError() const
103 Database::Database(const char *path
, int flags
, bool lenient
/* = false */)
104 : mMutex(Mutex::recursive
)
107 int rc
= ::sqlite3_open_v2(path
, &mDb
, flags
, NULL
);
108 if (rc
!= SQLITE_OK
&& lenient
) { // silent open failure
109 sqlite3_close(mDb
); // ditch useless Db object
110 mDb
= NULL
; // indicate failure
114 check(::sqlite3_extended_result_codes(mDb
, true));
117 sqlite3_close(mDb
); // allocated even if open fails(!)
122 Database::~Database()
127 void Database::close()
130 check(::sqlite3_close(mDb
));
134 int Database::execute(const char *text
, bool strict
/* = true */)
136 StLock
<Mutex
> _(mMutex
);
138 int rc
= ::sqlite3_exec(mDb
, text
, NULL
, NULL
, NULL
);
145 void Database::busyDelay(int ms
)
147 StLock
<Mutex
> _(mMutex
);
149 check(::sqlite3_busy_timeout(mDb
, ms
));
153 void Database::check(int err
)
160 bool Database::empty()
162 return value("select count(*) from sqlite_master;", 0) == 0;
166 int Database::errcode()
168 StLock
<Mutex
> _(mMutex
);
170 return sqlite3_errcode(mDb
);
175 const char *Database::errmsg()
177 StLock
<Mutex
> _(mMutex
);
179 return sqlite3_errmsg(mDb
);
184 bool Database::inTransaction()
186 StLock
<Mutex
> _(mMutex
);
188 return !::sqlite3_get_autocommit(mDb
);
193 int64
Database::lastInsert()
195 StLock
<Mutex
> _(mMutex
);
197 return ::sqlite3_last_insert_rowid(mDb
);
200 int Database::changes()
202 StLock
<Mutex
> _(mMutex
);
204 return ::sqlite3_changes(mDb
);
207 void Database::interrupt()
209 StLock
<Mutex
> _(mMutex
);
211 ::sqlite3_interrupt(mDb
);
215 // Transaction managers
217 Transaction::Transaction(Database
&db
, Type type
, const char *name
)
218 : database(db
), mName(name
? name
: "")
221 case deferred
: xactCommand("BEGIN DEFERRED"); break;
222 case immediate
: xactCommand("BEGIN IMMEDIATE"); break;
223 case exclusive
: xactCommand("BEGIN EXCLUSIVE"); break;
227 Transaction::~Transaction()
229 if (database
.inTransaction()) {
230 // request rollback but ignore any errors
231 database
.execute("ROLLBACK TRANSACTION", false);
235 void Transaction::commit()
237 xactCommand("COMMIT");
240 void Transaction::abort()
242 xactCommand("ROLLBACK");
245 void Transaction::xactCommand(const string
&cmd
)
247 database
.execute(cmd
+ " TRANSACTION " + mName
+ ";");
254 Statement::Statement(Database
&db
, const char *text
)
255 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
260 Statement::Statement(Database
&db
)
261 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
264 void Statement::query(const char *text
)
268 check(::sqlite3_prepare_v2(database
.sql(), text
, -1, &mStmt
, &tail
));
270 throw std::logic_error("multiple statements");
273 void Statement::close()
275 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
276 // So we eat any error code here, since we can't tell "genuine" errors apart from
277 // errors inherited from the Statement execution.
279 ::sqlite3_finalize(mStmt
);
283 Statement::~Statement()
289 void Statement::unbind()
291 check(::sqlite3_clear_bindings(mStmt
));
294 void Statement::reset()
296 check(::sqlite3_reset(mStmt
));
300 int Statement::step()
302 return ::sqlite3_step(mStmt
);
305 void Statement::execute()
307 switch (int rc
= this->step()) {
316 bool Statement::nextRow()
318 switch (int rc
= this->step()) {
333 Statement::Binding
Statement::bind(const char *name
) const
335 if (int ix
= ::sqlite3_bind_parameter_index(mStmt
, name
))
336 return Binding(*this, ix
);
338 throw std::logic_error("unknown parameter name");
341 void Statement::Binding::null()
343 statement
.check(::sqlite3_bind_null(statement
.sql(), index
));
346 void Statement::Binding::operator = (const Value
&value
)
348 statement
.check(::sqlite3_bind_value(statement
.sql(), index
, value
.sql()));
351 void Statement::Binding::operator = (int value
)
353 statement
.check(::sqlite3_bind_int(statement
.sql(), index
, value
));
356 void Statement::Binding::operator = (sqlite3_int64 value
)
358 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
361 void Statement::Binding::integer(sqlite3_int64 value
)
363 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
366 void Statement::Binding::operator = (double value
)
368 statement
.check(::sqlite3_bind_double(statement
.sql(), index
, value
));
371 void Statement::Binding::operator = (const char *value
)
376 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
377 ::strdup(value
), -1, ::free
));
380 void Statement::Binding::operator = (const std::string
&value
)
382 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
383 ::strdup(value
.c_str()), -1, ::free
));
386 void Statement::Binding::blob(const void *data
, size_t length
, bool shared
/* = false */)
391 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
, data
, (int)length
, NULL
));
392 } else if (void *copy
= ::malloc(length
)) {
393 ::memcpy(copy
, data
, length
);
394 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
,
395 copy
, (int)length
, ::free
));
397 throw std::bad_alloc();
400 void Statement::Binding::operator = (CFDataRef data
)
403 this->blob(CFDataGetBytePtr(data
), CFDataGetLength(data
));
408 void Statement::Binding::operator = (CFStringRef value
)
411 *this = cfString(value
).c_str();
416 const char *Statement::Binding::name() const
418 return sqlite3_bind_parameter_name(statement
.sql(), index
);
423 // Row/column results
425 const char *Statement::Result::name() const
427 return sqlite3_column_name(statement
.sql(), index
);
430 CFDataRef
Statement::Result::data() const
432 switch (this->type()) {
436 return makeCFData(this->blob(), this->length());
438 throw Error(SQLITE_MISMATCH
, "Retrieving data() of non-Blob");