]>
git.saurik.com Git - apple/security.git/blob - libsecurity_utilities/lib/sqlite++.cpp
2 * Copyright (c) 2008 Apple Computer, 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
)
102 : mMutex(Mutex::recursive
)
105 check(::sqlite3_open_v2(path
, &mDb
, flags
, NULL
));
106 check(::sqlite3_extended_result_codes(mDb
, true));
109 sqlite3_close(mDb
); // allocated even if open fails(!)
114 Database::~Database()
119 void Database::close()
122 check(::sqlite3_close(mDb
));
126 int Database::execute(const char *text
, bool strict
/* = true */)
128 StLock
<Mutex
> _(mMutex
);
130 int rc
= ::sqlite3_exec(mDb
, text
, NULL
, NULL
, NULL
);
137 void Database::busyDelay(int ms
)
139 StLock
<Mutex
> _(mMutex
);
141 check(::sqlite3_busy_timeout(mDb
, ms
));
145 void Database::check(int err
)
152 bool Database::empty()
154 return value("select count(*) from sqlite_master;", 0) == 0;
158 int Database::errcode()
160 StLock
<Mutex
> _(mMutex
);
162 return sqlite3_errcode(mDb
);
167 const char *Database::errmsg()
169 StLock
<Mutex
> _(mMutex
);
171 return sqlite3_errmsg(mDb
);
176 bool Database::inTransaction()
178 StLock
<Mutex
> _(mMutex
);
180 return !::sqlite3_get_autocommit(mDb
);
185 int64
Database::lastInsert()
187 StLock
<Mutex
> _(mMutex
);
189 return ::sqlite3_last_insert_rowid(mDb
);
192 int Database::changes()
194 StLock
<Mutex
> _(mMutex
);
196 return ::sqlite3_changes(mDb
);
199 void Database::interrupt()
201 StLock
<Mutex
> _(mMutex
);
203 ::sqlite3_interrupt(mDb
);
207 // Transaction managers
209 Transaction::Transaction(Database
&db
, Type type
, const char *name
)
210 : database(db
), mName(name
? name
: "")
213 case deferred
: xactCommand("BEGIN DEFERRED"); break;
214 case immediate
: xactCommand("BEGIN IMMEDIATE"); break;
215 case exclusive
: xactCommand("BEGIN EXCLUSIVE"); break;
219 Transaction::~Transaction()
221 if (database
.inTransaction())
225 void Transaction::commit()
227 xactCommand("COMMIT");
230 void Transaction::abort()
232 xactCommand("ROLLBACK");
235 void Transaction::xactCommand(const string
&cmd
)
237 database
.execute(cmd
+ " TRANSACTION " + mName
+ ";");
244 Statement::Statement(Database
&db
, const char *text
)
245 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
250 Statement::Statement(Database
&db
)
251 : StLock
<Mutex
>(db
.mMutex
), database(db
), mStmt(NULL
)
254 void Statement::query(const char *text
)
258 check(::sqlite3_prepare_v2(database
.sql(), text
, -1, &mStmt
, &tail
));
260 throw std::logic_error("multiple statements");
263 void Statement::close()
265 // Sqlite3_finalize will return an error if the Statement (executed and) failed.
266 // So we eat any error code here, since we can't tell "genuine" errors apart from
267 // errors inherited from the Statement execution.
269 ::sqlite3_finalize(mStmt
);
273 Statement::~Statement()
279 void Statement::unbind()
281 check(::sqlite3_clear_bindings(mStmt
));
284 void Statement::reset()
286 check(::sqlite3_reset(mStmt
));
290 int Statement::step()
292 return ::sqlite3_step(mStmt
);
295 void Statement::execute()
297 switch (int rc
= this->step()) {
306 bool Statement::nextRow()
308 switch (int rc
= this->step()) {
323 Statement::Binding
Statement::bind(const char *name
) const
325 if (int ix
= ::sqlite3_bind_parameter_index(mStmt
, name
))
326 return Binding(*this, ix
);
328 throw std::logic_error("unknown parameter name");
331 void Statement::Binding::null()
333 statement
.check(::sqlite3_bind_null(statement
.sql(), index
));
336 void Statement::Binding::operator = (const Value
&value
)
338 statement
.check(::sqlite3_bind_value(statement
.sql(), index
, value
.sql()));
341 void Statement::Binding::operator = (int value
)
343 statement
.check(::sqlite3_bind_int(statement
.sql(), index
, value
));
346 void Statement::Binding::operator = (sqlite3_int64 value
)
348 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
351 void Statement::Binding::integer(sqlite3_int64 value
)
353 statement
.check(::sqlite3_bind_int64(statement
.sql(), index
, value
));
356 void Statement::Binding::operator = (double value
)
358 statement
.check(::sqlite3_bind_double(statement
.sql(), index
, value
));
361 void Statement::Binding::operator = (const char *value
)
366 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
367 ::strdup(value
), -1, ::free
));
370 void Statement::Binding::operator = (const std::string
&value
)
372 statement
.check(::sqlite3_bind_text(statement
.sql(), index
,
373 ::strdup(value
.c_str()), -1, ::free
));
376 void Statement::Binding::blob(const void *data
, size_t length
, bool shared
/* = false */)
381 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
, data
, length
, NULL
));
382 } else if (void *copy
= ::malloc(length
)) {
383 ::memcpy(copy
, data
, length
);
384 statement
.check(::sqlite3_bind_blob(statement
.sql(), index
,
385 copy
, length
, ::free
));
387 throw std::bad_alloc();
390 void Statement::Binding::operator = (CFDataRef data
)
393 this->blob(CFDataGetBytePtr(data
), CFDataGetLength(data
));
398 void Statement::Binding::operator = (CFStringRef value
)
401 *this = cfString(value
).c_str();
406 const char *Statement::Binding::name() const
408 return sqlite3_bind_parameter_name(statement
.sql(), index
);
413 // Row/column results
415 const char *Statement::Result::name() const
417 return sqlite3_column_name(statement
.sql(), index
);
420 CFDataRef
Statement::Result::data() const
422 switch (this->type()) {
426 return makeCFData(this->blob(), this->length());
428 throw Error(SQLITE_MISMATCH
, "Retrieving data() of non-Blob");