]>
git.saurik.com Git - apple/security.git/blob - Security/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())
231 void Transaction::commit()
233 xactCommand("COMMIT");
236 void Transaction::abort()
238 xactCommand("ROLLBACK");
241 void Transaction::xactCommand(const string
&cmd
)
243 database
.execute(cmd
+ " TRANSACTION " + mName
+ ";");
250 Statement::Statement(Database
&db
, const char *text
)
251 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
256 Statement::Statement(Database
&db
)
257 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
260 void Statement::query(const char *text
)
264 check(::sqlite3_prepare_v2(database
.sql(), text
, -1, &mStmt
, &tail
));
266 throw std::logic_error("multiple statements");
269 void Statement::close()
271 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
272 // So we eat any error code here, since we can't tell "genuine" errors apart from
273 // errors inherited from the Statement execution.
275 ::sqlite3_finalize(mStmt
);
279 Statement::~Statement()
285 void Statement::unbind()
287 check(::sqlite3_clear_bindings(mStmt
));
290 void Statement::reset()
292 check(::sqlite3_reset(mStmt
));
296 int Statement::step()
298 return ::sqlite3_step(mStmt
);
301 void Statement::execute()
303 switch (int rc
= this->step()) {
312 bool Statement::nextRow()
314 switch (int rc
= this->step()) {
329 Statement::Binding
Statement::bind(const char *name
) const
331 if (int ix
= ::sqlite3_bind_parameter_index(mStmt
, name
))
332 return Binding(*this, ix
);
334 throw std::logic_error("unknown parameter name");
337 void Statement::Binding::null()
339 statement
.check(::sqlite3_bind_null(statement
.sql(), index
));
342 void Statement::Binding::operator = (const Value
&value
)
344 statement
.check(::sqlite3_bind_value(statement
.sql(), index
, value
.sql()));
347 void Statement::Binding::operator = (int value
)
349 statement
.check(::sqlite3_bind_int(statement
.sql(), index
, value
));
352 void Statement::Binding::operator = (sqlite3_int64 value
)
354 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
357 void Statement::Binding::integer(sqlite3_int64 value
)
359 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
362 void Statement::Binding::operator = (double value
)
364 statement
.check(::sqlite3_bind_double(statement
.sql(), index
, value
));
367 void Statement::Binding::operator = (const char *value
)
372 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
373 ::strdup(value
), -1, ::free
));
376 void Statement::Binding::operator = (const std::string
&value
)
378 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
379 ::strdup(value
.c_str()), -1, ::free
));
382 void Statement::Binding::blob(const void *data
, size_t length
, bool shared
/* = false */)
387 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
, data
, (int)length
, NULL
));
388 } else if (void *copy
= ::malloc(length
)) {
389 ::memcpy(copy
, data
, length
);
390 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
,
391 copy
, (int)length
, ::free
));
393 throw std::bad_alloc();
396 void Statement::Binding::operator = (CFDataRef data
)
399 this->blob(CFDataGetBytePtr(data
), CFDataGetLength(data
));
404 void Statement::Binding::operator = (CFStringRef value
)
407 *this = cfString(value
).c_str();
412 const char *Statement::Binding::name() const
414 return sqlite3_bind_parameter_name(statement
.sql(), index
);
419 // Row/column results
421 const char *Statement::Result::name() const
423 return sqlite3_column_name(statement
.sql(), index
);
426 CFDataRef
Statement::Result::data() const
428 switch (this->type()) {
432 return makeCFData(this->blob(), this->length());
434 throw Error(SQLITE_MISMATCH
, "Retrieving data() of non-Blob");