]>
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>
32 // From cssmapple.h - layering break
33 // Where should this go?
35 #define errSecErrnoBase 100000
36 #define errSecErrnoLimit 100255
44 // Our exception object
46 void Error::check(int err
)
52 Error::Error(Database
&db
)
53 : error(db
.errcode()), message(db
.errmsg())
55 SECURITY_EXCEPTION_THROW_SQLITE(this, error
, (char*)message
.c_str());
58 void Error::throwMe(int err
)
63 OSStatus
Error::osStatus() const
65 return unixError() + errSecErrnoBase
;
68 int Error::unixError() const
101 Database::Database(const char *path
, int flags
, bool lenient
/* = false */)
102 : mMutex(Mutex::recursive
)
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
112 check(::sqlite3_extended_result_codes(mDb
, true));
115 sqlite3_close(mDb
); // allocated even if open fails(!)
120 Database::~Database()
125 void Database::close()
128 check(::sqlite3_close(mDb
));
132 int Database::execute(const char *text
, bool strict
/* = true */)
134 StLock
<Mutex
> _(mMutex
);
136 int rc
= ::sqlite3_exec(mDb
, text
, NULL
, NULL
, NULL
);
143 void Database::busyDelay(int ms
)
145 StLock
<Mutex
> _(mMutex
);
147 check(::sqlite3_busy_timeout(mDb
, ms
));
151 void Database::check(int err
)
158 bool Database::empty()
160 return value("select count(*) from sqlite_master;", 0) == 0;
164 int Database::errcode()
166 StLock
<Mutex
> _(mMutex
);
168 return sqlite3_errcode(mDb
);
173 const char *Database::errmsg()
175 StLock
<Mutex
> _(mMutex
);
177 return sqlite3_errmsg(mDb
);
182 bool Database::inTransaction()
184 StLock
<Mutex
> _(mMutex
);
186 return !::sqlite3_get_autocommit(mDb
);
191 int64
Database::lastInsert()
193 StLock
<Mutex
> _(mMutex
);
195 return ::sqlite3_last_insert_rowid(mDb
);
198 int Database::changes()
200 StLock
<Mutex
> _(mMutex
);
202 return ::sqlite3_changes(mDb
);
205 void Database::interrupt()
207 StLock
<Mutex
> _(mMutex
);
209 ::sqlite3_interrupt(mDb
);
213 // Transaction managers
215 Transaction::Transaction(Database
&db
, Type type
, const char *name
)
216 : database(db
), mName(name
? name
: "")
219 case deferred
: xactCommand("BEGIN DEFERRED"); break;
220 case immediate
: xactCommand("BEGIN IMMEDIATE"); break;
221 case exclusive
: xactCommand("BEGIN EXCLUSIVE"); break;
225 Transaction::~Transaction()
227 if (database
.inTransaction()) {
228 // request rollback but ignore any errors
229 database
.execute("ROLLBACK TRANSACTION", false);
233 void Transaction::commit()
235 xactCommand("COMMIT");
238 void Transaction::abort()
240 xactCommand("ROLLBACK");
243 void Transaction::xactCommand(const string
&cmd
)
245 database
.execute(cmd
+ " TRANSACTION " + mName
+ ";");
252 Statement::Statement(Database
&db
, const char *text
)
253 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
258 Statement::Statement(Database
&db
)
259 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
262 void Statement::query(const char *text
)
266 check(::sqlite3_prepare_v2(database
.sql(), text
, -1, &mStmt
, &tail
));
268 throw std::logic_error("multiple statements");
271 void Statement::close()
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.
277 ::sqlite3_finalize(mStmt
);
281 Statement::~Statement()
287 void Statement::unbind()
289 check(::sqlite3_clear_bindings(mStmt
));
292 void Statement::reset()
294 check(::sqlite3_reset(mStmt
));
298 int Statement::step()
300 return ::sqlite3_step(mStmt
);
303 void Statement::execute()
305 switch (int rc
= this->step()) {
314 bool Statement::nextRow()
316 switch (int rc
= this->step()) {
331 Statement::Binding
Statement::bind(const char *name
) const
333 if (int ix
= ::sqlite3_bind_parameter_index(mStmt
, name
))
334 return Binding(*this, ix
);
336 throw std::logic_error("unknown parameter name");
339 void Statement::Binding::null()
341 statement
.check(::sqlite3_bind_null(statement
.sql(), index
));
344 void Statement::Binding::operator = (const Value
&value
)
346 statement
.check(::sqlite3_bind_value(statement
.sql(), index
, value
.sql()));
349 void Statement::Binding::operator = (int value
)
351 statement
.check(::sqlite3_bind_int(statement
.sql(), index
, value
));
354 void Statement::Binding::operator = (sqlite3_int64 value
)
356 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
359 void Statement::Binding::integer(sqlite3_int64 value
)
361 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
364 void Statement::Binding::operator = (double value
)
366 statement
.check(::sqlite3_bind_double(statement
.sql(), index
, value
));
369 void Statement::Binding::operator = (const char *value
)
374 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
375 ::strdup(value
), -1, ::free
));
378 void Statement::Binding::operator = (const std::string
&value
)
380 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
381 ::strdup(value
.c_str()), -1, ::free
));
384 void Statement::Binding::blob(const void *data
, size_t length
, bool shared
/* = false */)
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
));
395 throw std::bad_alloc();
398 void Statement::Binding::operator = (CFDataRef data
)
401 this->blob(CFDataGetBytePtr(data
), CFDataGetLength(data
));
406 void Statement::Binding::operator = (CFStringRef value
)
409 *this = cfString(value
).c_str();
414 const char *Statement::Binding::name() const
416 return sqlite3_bind_parameter_name(statement
.sql(), index
);
421 // Row/column results
423 const char *Statement::Result::name() const
425 return sqlite3_column_name(statement
.sql(), index
);
428 CFDataRef
Statement::Result::data() const
430 switch (this->type()) {
434 return makeCFData(this->blob(), this->length());
436 throw Error(SQLITE_MISMATCH
, "Retrieving data() of non-Blob");