]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/sqlite++.cpp
4a5e05e857b488b9de2f340e29d2eb20c6c7b7f4
   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");