]>
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());
56 secnotice("security_exception", "sqlite: %d %s",error
, (char*)message
.c_str());
59 void Error::throwMe(int err
)
64 OSStatus
Error::osStatus() const
66 return unixError() + errSecErrnoBase
;
69 int Error::unixError() const
102 Database::Database(const char *path
, int flags
, bool lenient
/* = false */)
103 : mMutex(Mutex::recursive
)
106 int rc
= ::sqlite3_open_v2(path
, &mDb
, flags
, NULL
);
107 if (rc
!= SQLITE_OK
&& lenient
) { // silent open failure
108 sqlite3_close(mDb
); // ditch useless Db object
109 mDb
= NULL
; // indicate failure
113 check(::sqlite3_extended_result_codes(mDb
, true));
116 sqlite3_close(mDb
); // allocated even if open fails(!)
121 Database::~Database()
126 void Database::close()
129 check(::sqlite3_close(mDb
));
133 int Database::execute(const char *text
, bool strict
/* = true */)
135 StLock
<Mutex
> _(mMutex
);
137 int rc
= ::sqlite3_exec(mDb
, text
, NULL
, NULL
, NULL
);
144 void Database::busyDelay(int ms
)
146 StLock
<Mutex
> _(mMutex
);
148 check(::sqlite3_busy_timeout(mDb
, ms
));
152 void Database::check(int err
)
159 bool Database::empty()
161 return value("select count(*) from sqlite_master;", 0) == 0;
165 int Database::errcode()
167 StLock
<Mutex
> _(mMutex
);
169 return sqlite3_errcode(mDb
);
174 const char *Database::errmsg()
176 StLock
<Mutex
> _(mMutex
);
178 return sqlite3_errmsg(mDb
);
183 bool Database::inTransaction()
185 StLock
<Mutex
> _(mMutex
);
187 return !::sqlite3_get_autocommit(mDb
);
192 int64
Database::lastInsert()
194 StLock
<Mutex
> _(mMutex
);
196 return ::sqlite3_last_insert_rowid(mDb
);
199 int Database::changes()
201 StLock
<Mutex
> _(mMutex
);
203 return ::sqlite3_changes(mDb
);
206 void Database::interrupt()
208 StLock
<Mutex
> _(mMutex
);
210 ::sqlite3_interrupt(mDb
);
214 // Transaction managers
216 Transaction::Transaction(Database
&db
, Type type
, const char *name
)
217 : database(db
), mName(name
? name
: "")
220 case deferred
: xactCommand("BEGIN DEFERRED"); break;
221 case immediate
: xactCommand("BEGIN IMMEDIATE"); break;
222 case exclusive
: xactCommand("BEGIN EXCLUSIVE"); break;
226 Transaction::~Transaction()
228 if (database
.inTransaction()) {
229 // request rollback but ignore any errors
230 database
.execute("ROLLBACK TRANSACTION", false);
234 void Transaction::commit()
236 xactCommand("COMMIT");
239 void Transaction::abort()
241 xactCommand("ROLLBACK");
244 void Transaction::xactCommand(const string
&cmd
)
246 database
.execute(cmd
+ " TRANSACTION " + mName
+ ";");
253 Statement::Statement(Database
&db
, const char *text
)
254 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
259 Statement::Statement(Database
&db
)
260 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
263 void Statement::query(const char *text
)
267 check(::sqlite3_prepare_v2(database
.sql(), text
, -1, &mStmt
, &tail
));
269 throw std::logic_error("multiple statements");
272 void Statement::close()
274 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
275 // So we eat any error code here, since we can't tell "genuine" errors apart from
276 // errors inherited from the Statement execution.
278 ::sqlite3_finalize(mStmt
);
282 Statement::~Statement()
288 void Statement::unbind()
290 check(::sqlite3_clear_bindings(mStmt
));
293 void Statement::reset()
295 check(::sqlite3_reset(mStmt
));
299 int Statement::step()
301 return ::sqlite3_step(mStmt
);
304 void Statement::execute()
306 switch (int rc
= this->step()) {
315 bool Statement::nextRow()
317 switch (int rc
= this->step()) {
332 Statement::Binding
Statement::bind(const char *name
) const
334 if (int ix
= ::sqlite3_bind_parameter_index(mStmt
, name
))
335 return Binding(*this, ix
);
337 throw std::logic_error("unknown parameter name");
340 void Statement::Binding::null()
342 statement
.check(::sqlite3_bind_null(statement
.sql(), index
));
345 void Statement::Binding::operator = (const Value
&value
)
347 statement
.check(::sqlite3_bind_value(statement
.sql(), index
, value
.sql()));
350 void Statement::Binding::operator = (int value
)
352 statement
.check(::sqlite3_bind_int(statement
.sql(), index
, value
));
355 void Statement::Binding::operator = (sqlite3_int64 value
)
357 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
360 void Statement::Binding::integer(sqlite3_int64 value
)
362 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
365 void Statement::Binding::operator = (double value
)
367 statement
.check(::sqlite3_bind_double(statement
.sql(), index
, value
));
370 void Statement::Binding::operator = (const char *value
)
375 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
376 ::strdup(value
), -1, ::free
));
379 void Statement::Binding::operator = (const std::string
&value
)
381 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
382 ::strdup(value
.c_str()), -1, ::free
));
385 void Statement::Binding::blob(const void *data
, size_t length
, bool shared
/* = false */)
390 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
, data
, (int)length
, NULL
));
391 } else if (void *copy
= ::malloc(length
)) {
392 ::memcpy(copy
, data
, length
);
393 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
,
394 copy
, (int)length
, ::free
));
396 throw std::bad_alloc();
399 void Statement::Binding::operator = (CFDataRef data
)
402 this->blob(CFDataGetBytePtr(data
), CFDataGetLength(data
));
407 void Statement::Binding::operator = (CFStringRef value
)
410 *this = cfString(value
).c_str();
415 const char *Statement::Binding::name() const
417 return sqlite3_bind_parameter_name(statement
.sql(), index
);
422 // Row/column results
424 const char *Statement::Result::name() const
426 return sqlite3_column_name(statement
.sql(), index
);
429 CFDataRef
Statement::Result::data() const
431 switch (this->type()) {
435 return makeCFData(this->blob(), this->length());
437 throw Error(SQLITE_MISMATCH
, "Retrieving data() of non-Blob");