Mercurial > mercurial > hgweb_searcher2.cgi
comparison src/wxsqlite3.cpp @ 0:c174ac668e9f
First commit ! (ver2.8)
| author | pyon@macmini |
|---|---|
| date | Tue, 05 Apr 2011 18:44:57 +0900 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:c174ac668e9f |
|---|---|
| 1 /////////////////////////////////////////////////////////////////////////////// | |
| 2 // Name: wxsqlite3.cpp | |
| 3 // Purpose: Implementation of wxSQLite3 classes | |
| 4 // Author: Ulrich Telle | |
| 5 // Modified by: | |
| 6 // Created: 2005-07-06 | |
| 7 // Copyright: (c) Ulrich Telle | |
| 8 // Licence: wxWindows licence | |
| 9 /////////////////////////////////////////////////////////////////////////////// | |
| 10 | |
| 11 /// \file wxsqlite3.cpp Implementation of the wxSQLite3 class | |
| 12 | |
| 13 #if defined(__GNUG__) && !defined(__APPLE__) | |
| 14 #pragma implementation "wxsqlite3.h" | |
| 15 #endif | |
| 16 | |
| 17 // For compilers that support precompilation, includes "wx/wx.h". | |
| 18 #include "wx/wxprec.h" | |
| 19 | |
| 20 #ifdef __BORLANDC__ | |
| 21 #pragma hdrstop | |
| 22 #endif | |
| 23 | |
| 24 #ifndef WX_PRECOMP | |
| 25 #include "wx/wx.h" | |
| 26 #endif | |
| 27 | |
| 28 #include "wx/regex.h" | |
| 29 | |
| 30 #include "wx/wxsqlite3.h" | |
| 31 #include "wx/wxsqlite3opt.h" | |
| 32 | |
| 33 // Suppress some Visual C++ warnings regarding the default constructor | |
| 34 // for a C struct used only in SQLite modules | |
| 35 #ifdef __VISUALC__ | |
| 36 #pragma warning (disable:4510) | |
| 37 #pragma warning (disable:4610) | |
| 38 #endif | |
| 39 | |
| 40 #if WXSQLITE3_HAVE_CODEC | |
| 41 #define SQLITE_HAS_CODEC 1 | |
| 42 #else | |
| 43 #define SQLITE_HAS_CODEC 0 | |
| 44 #endif | |
| 45 | |
| 46 #include "sqlite3.h" | |
| 47 | |
| 48 // Dynamic loading of the SQLite library | |
| 49 | |
| 50 #if wxUSE_DYNAMIC_SQLITE3_LOAD | |
| 51 | |
| 52 #include "wx/dynlib.h" | |
| 53 | |
| 54 #define DYNFUNC(rcode, rtype, fname, farg, farguse) \ | |
| 55 typedef rtype (*p##fname) farg ; \ | |
| 56 static p##fname s_##fname = NULL; | |
| 57 #include "wx/wxsqlite3dyn.h" | |
| 58 #undef DYNFUNC | |
| 59 | |
| 60 static wxDynamicLibrary s_dll; | |
| 61 | |
| 62 static void InitSQLite3DLL() | |
| 63 { | |
| 64 if (s_dll.IsLoaded()) | |
| 65 { | |
| 66 return; | |
| 67 } | |
| 68 | |
| 69 #ifdef __WIN32__ | |
| 70 if (! s_dll.Load(wxT("sqlite3"))) | |
| 71 #else | |
| 72 if (! s_dll.Load(wxT("libsqlite3"))) | |
| 73 #endif | |
| 74 { | |
| 75 throw wxSQLite3Exception(-1, wxT("error loading dynamic library")); | |
| 76 } | |
| 77 | |
| 78 #define DYNFUNC(rcode, rtype, fname, farg, farguse) \ | |
| 79 s_##fname = (p##fname) s_dll.GetSymbol(wxT(#fname));\ | |
| 80 if (! s_##fname)\ | |
| 81 {\ | |
| 82 s_dll.Unload();\ | |
| 83 throw wxSQLite3Exception(-1, wxT("error getting symbol <") wxT(#fname) wxT(">"));\ | |
| 84 } | |
| 85 #include "wx/wxsqlite3dyn.h" | |
| 86 #undef DYNFUNC | |
| 87 | |
| 88 }; | |
| 89 | |
| 90 #define DYNFUNC(rcode, rtype, fname, farg, farguse) \ | |
| 91 rtype fname farg \ | |
| 92 {\ | |
| 93 InitSQLite3DLL();\ | |
| 94 rcode s_##fname farguse;\ | |
| 95 }; | |
| 96 #include "wx/wxsqlite3dyn.h" | |
| 97 #undef DYNFUNC | |
| 98 | |
| 99 #endif // wxUSE_DYNAMIC_SQLITE3_LOAD | |
| 100 | |
| 101 // Error messages | |
| 102 | |
| 103 #if wxCHECK_VERSION(2,9,0) | |
| 104 const char* wxERRMSG_NODB = wxTRANSLATE("No Database opened"); | |
| 105 const char* wxERRMSG_NOSTMT = wxTRANSLATE("Statement not accessible"); | |
| 106 const char* wxERRMSG_NOMEM = wxTRANSLATE("Out of memory"); | |
| 107 const char* wxERRMSG_DECODE = wxTRANSLATE("Cannot decode binary"); | |
| 108 const char* wxERRMSG_INVALID_INDEX = wxTRANSLATE("Invalid field index"); | |
| 109 const char* wxERRMSG_INVALID_NAME = wxTRANSLATE("Invalid field name"); | |
| 110 const char* wxERRMSG_INVALID_ROW = wxTRANSLATE("Invalid row index"); | |
| 111 const char* wxERRMSG_INVALID_QUERY = wxTRANSLATE("Invalid scalar query"); | |
| 112 const char* wxERRMSG_INVALID_BLOB = wxTRANSLATE("Invalid BLOB handle"); | |
| 113 | |
| 114 const char* wxERRMSG_NORESULT = wxTRANSLATE("Null Results pointer"); | |
| 115 const char* wxERRMSG_BIND_STR = wxTRANSLATE("Error binding string param"); | |
| 116 const char* wxERRMSG_BIND_INT = wxTRANSLATE("Error binding int param"); | |
| 117 const char* wxERRMSG_BIND_INT64 = wxTRANSLATE("Error binding int64 param"); | |
| 118 const char* wxERRMSG_BIND_DBL = wxTRANSLATE("Error binding double param"); | |
| 119 const char* wxERRMSG_BIND_BLOB = wxTRANSLATE("Error binding blob param"); | |
| 120 const char* wxERRMSG_BIND_DATETIME = wxTRANSLATE("Error binding date/time param"); | |
| 121 const char* wxERRMSG_BIND_NULL = wxTRANSLATE("Error binding NULL param"); | |
| 122 const char* wxERRMSG_BIND_ZEROBLOB = wxTRANSLATE("Error binding zero blob param"); | |
| 123 const char* wxERRMSG_BIND_CLEAR = wxTRANSLATE("Error clearing bindings"); | |
| 124 const char* wxERRMSG_NOTOWNED = wxTRANSLATE("Transfer of statement ownership not possible"); | |
| 125 | |
| 126 const char* wxERRMSG_NOMETADATA = wxTRANSLATE("Meta data support not available"); | |
| 127 const char* wxERRMSG_NOCODEC = wxTRANSLATE("Encryption support not available"); | |
| 128 const char* wxERRMSG_NOLOADEXT = wxTRANSLATE("Loadable extension support not available"); | |
| 129 const char* wxERRMSG_NOINCBLOB = wxTRANSLATE("Incremental BLOB support not available"); | |
| 130 const char* wxERRMSG_NOBLOBREBIND = wxTRANSLATE("Rebind BLOB support not available"); | |
| 131 const char* wxERRMSG_NOSAVEPOINT = wxTRANSLATE("Savepoint support not available"); | |
| 132 const char* wxERRMSG_NOBACKUP = wxTRANSLATE("Backup/restore support not available"); | |
| 133 const char* wxERRMSG_NOWAL = wxTRANSLATE("Write Ahead Log support not available"); | |
| 134 const char* wxERRMSG_NOCOLLECTIONS = wxTRANSLATE("Named collection support not available"); | |
| 135 | |
| 136 const char* wxERRMSG_SHARED_CACHE = wxTRANSLATE("Setting SQLite shared cache mode failed"); | |
| 137 | |
| 138 const char* wxERRMSG_INITIALIZE = wxTRANSLATE("Initialization of SQLite failed"); | |
| 139 const char* wxERRMSG_SHUTDOWN = wxTRANSLATE("Shutdown of SQLite failed"); | |
| 140 | |
| 141 const char* wxERRMSG_SOURCEDB_BUSY = wxTRANSLATE("Source database is busy"); | |
| 142 const char* wxERRMSG_DBOPEN_FAILED = wxTRANSLATE("Database open failed"); | |
| 143 const char* wxERRMSG_DBASSIGN_FAILED = wxTRANSLATE("Database assignment failed"); | |
| 144 #else | |
| 145 const wxChar* wxERRMSG_NODB = wxTRANSLATE("No Database opened"); | |
| 146 const wxChar* wxERRMSG_NOSTMT = wxTRANSLATE("Statement not accessible"); | |
| 147 const wxChar* wxERRMSG_NOMEM = wxTRANSLATE("Out of memory"); | |
| 148 const wxChar* wxERRMSG_DECODE = wxTRANSLATE("Cannot decode binary"); | |
| 149 const wxChar* wxERRMSG_INVALID_INDEX = wxTRANSLATE("Invalid field index"); | |
| 150 const wxChar* wxERRMSG_INVALID_NAME = wxTRANSLATE("Invalid field name"); | |
| 151 const wxChar* wxERRMSG_INVALID_ROW = wxTRANSLATE("Invalid row index"); | |
| 152 const wxChar* wxERRMSG_INVALID_QUERY = wxTRANSLATE("Invalid scalar query"); | |
| 153 const wxChar* wxERRMSG_INVALID_BLOB = wxTRANSLATE("Invalid BLOB handle"); | |
| 154 | |
| 155 const wxChar* wxERRMSG_NORESULT = wxTRANSLATE("Null Results pointer"); | |
| 156 const wxChar* wxERRMSG_BIND_STR = wxTRANSLATE("Error binding string param"); | |
| 157 const wxChar* wxERRMSG_BIND_INT = wxTRANSLATE("Error binding int param"); | |
| 158 const wxChar* wxERRMSG_BIND_INT64 = wxTRANSLATE("Error binding int64 param"); | |
| 159 const wxChar* wxERRMSG_BIND_DBL = wxTRANSLATE("Error binding double param"); | |
| 160 const wxChar* wxERRMSG_BIND_BLOB = wxTRANSLATE("Error binding blob param"); | |
| 161 const wxChar* wxERRMSG_BIND_DATETIME = wxTRANSLATE("Error binding date/time param"); | |
| 162 const wxChar* wxERRMSG_BIND_NULL = wxTRANSLATE("Error binding NULL param"); | |
| 163 const wxChar* wxERRMSG_BIND_ZEROBLOB = wxTRANSLATE("Error binding zero blob param"); | |
| 164 const wxChar* wxERRMSG_BIND_CLEAR = wxTRANSLATE("Error clearing bindings"); | |
| 165 const wxChar* wxERRMSG_NOTOWNED = wxTRANSLATE("Transfer of statement ownership not possible"); | |
| 166 | |
| 167 const wxChar* wxERRMSG_NOMETADATA = wxTRANSLATE("Meta data support not available"); | |
| 168 const wxChar* wxERRMSG_NOCODEC = wxTRANSLATE("Encryption support not available"); | |
| 169 const wxChar* wxERRMSG_NOLOADEXT = wxTRANSLATE("Loadable extension support not available"); | |
| 170 const wxChar* wxERRMSG_NOINCBLOB = wxTRANSLATE("Incremental BLOB support not available"); | |
| 171 const wxChar* wxERRMSG_NOBLOBREBIND = wxTRANSLATE("Rebind BLOB support not available"); | |
| 172 const wxChar* wxERRMSG_NOSAVEPOINT = wxTRANSLATE("Savepoint support not available"); | |
| 173 const wxChar* wxERRMSG_NOBACKUP = wxTRANSLATE("Backup/restore support not available"); | |
| 174 const wxChar* wxERRMSG_NOWAL = wxTRANSLATE("Write Ahead Log support not available"); | |
| 175 const wxChar* wxERRMSG_NOCOLLECTIONS = wxTRANSLATE("Named collection support not available"); | |
| 176 | |
| 177 const wxChar* wxERRMSG_SHARED_CACHE = wxTRANSLATE("Setting SQLite shared cache mode failed"); | |
| 178 | |
| 179 const wxChar* wxERRMSG_INITIALIZE = wxTRANSLATE("Initialization of SQLite failed"); | |
| 180 const wxChar* wxERRMSG_SHUTDOWN = wxTRANSLATE("Shutdown of SQLite failed"); | |
| 181 | |
| 182 const wxChar* wxERRMSG_SOURCEDB_BUSY = wxTRANSLATE("Source database is busy"); | |
| 183 const wxChar* wxERRMSG_DBOPEN_FAILED = wxTRANSLATE("Database open failed"); | |
| 184 const wxChar* wxERRMSG_DBASSIGN_FAILED = wxTRANSLATE("Database assignment failed"); | |
| 185 #endif | |
| 186 | |
| 187 // ---------------------------------------------------------------------------- | |
| 188 // inline conversion from wxString to wxLongLong | |
| 189 // ---------------------------------------------------------------------------- | |
| 190 | |
| 191 inline wxLongLong ConvertStringToLongLong(const wxString& str, wxLongLong defValue /*=0*/) | |
| 192 { | |
| 193 size_t n = str.Length(); | |
| 194 size_t j = 0; | |
| 195 wxLongLong value = 0; | |
| 196 bool negative = false; | |
| 197 | |
| 198 if (str[j] == '-') | |
| 199 { | |
| 200 negative = true; | |
| 201 j++; | |
| 202 } | |
| 203 | |
| 204 while (j < n) | |
| 205 { | |
| 206 if (str[j] < '0' || str[j] > '9') | |
| 207 { | |
| 208 return defValue; | |
| 209 } | |
| 210 value *= 10; | |
| 211 value += (str[j] - '0'); | |
| 212 j++; | |
| 213 } | |
| 214 | |
| 215 return negative ? -value : value; | |
| 216 } | |
| 217 | |
| 218 // ---------------------------------------------------------------------------- | |
| 219 // wxSQLite3Exception: class | |
| 220 // ---------------------------------------------------------------------------- | |
| 221 | |
| 222 wxSQLite3Exception::wxSQLite3Exception(int errorCode, const wxString& errorMsg) | |
| 223 : m_errorCode(errorCode) | |
| 224 { | |
| 225 m_errorMessage = ErrorCodeAsString(errorCode) + wxT("[") + | |
| 226 wxString::Format(wxT("%d"), errorCode) + wxT("]: ") + | |
| 227 wxGetTranslation(errorMsg); | |
| 228 } | |
| 229 | |
| 230 wxSQLite3Exception::wxSQLite3Exception(const wxSQLite3Exception& e) | |
| 231 : m_errorCode(e.m_errorCode), m_errorMessage(e.m_errorMessage) | |
| 232 { | |
| 233 } | |
| 234 | |
| 235 const wxString wxSQLite3Exception::ErrorCodeAsString(int errorCode) | |
| 236 { | |
| 237 switch (errorCode) | |
| 238 { | |
| 239 case SQLITE_OK : return wxT("SQLITE_OK"); | |
| 240 case SQLITE_ERROR : return wxT("SQLITE_ERROR"); | |
| 241 case SQLITE_INTERNAL : return wxT("SQLITE_INTERNAL"); | |
| 242 case SQLITE_PERM : return wxT("SQLITE_PERM"); | |
| 243 case SQLITE_ABORT : return wxT("SQLITE_ABORT"); | |
| 244 case SQLITE_BUSY : return wxT("SQLITE_BUSY"); | |
| 245 case SQLITE_LOCKED : return wxT("SQLITE_LOCKED"); | |
| 246 case SQLITE_NOMEM : return wxT("SQLITE_NOMEM"); | |
| 247 case SQLITE_READONLY : return wxT("SQLITE_READONLY"); | |
| 248 case SQLITE_INTERRUPT : return wxT("SQLITE_INTERRUPT"); | |
| 249 case SQLITE_IOERR : return wxT("SQLITE_IOERR"); | |
| 250 case SQLITE_CORRUPT : return wxT("SQLITE_CORRUPT"); | |
| 251 case SQLITE_NOTFOUND : return wxT("SQLITE_NOTFOUND"); | |
| 252 case SQLITE_FULL : return wxT("SQLITE_FULL"); | |
| 253 case SQLITE_CANTOPEN : return wxT("SQLITE_CANTOPEN"); | |
| 254 case SQLITE_PROTOCOL : return wxT("SQLITE_PROTOCOL"); | |
| 255 case SQLITE_EMPTY : return wxT("SQLITE_EMPTY"); | |
| 256 case SQLITE_SCHEMA : return wxT("SQLITE_SCHEMA"); | |
| 257 case SQLITE_TOOBIG : return wxT("SQLITE_TOOBIG"); | |
| 258 case SQLITE_CONSTRAINT : return wxT("SQLITE_CONSTRAINT"); | |
| 259 case SQLITE_MISMATCH : return wxT("SQLITE_MISMATCH"); | |
| 260 case SQLITE_MISUSE : return wxT("SQLITE_MISUSE"); | |
| 261 case SQLITE_NOLFS : return wxT("SQLITE_NOLFS"); | |
| 262 case SQLITE_AUTH : return wxT("SQLITE_AUTH"); | |
| 263 case SQLITE_FORMAT : return wxT("SQLITE_FORMAT"); | |
| 264 case SQLITE_RANGE : return wxT("SQLITE_RANGE"); | |
| 265 case SQLITE_NOTADB : return wxT("SQLITE_NOTADB"); | |
| 266 case SQLITE_ROW : return wxT("SQLITE_ROW"); | |
| 267 case SQLITE_DONE : return wxT("SQLITE_DONE"); | |
| 268 // Extended error codes | |
| 269 case SQLITE_IOERR_READ : return wxT("SQLITE_IOERR_READ"); | |
| 270 case SQLITE_IOERR_SHORT_READ : return wxT("SQLITE_IOERR_SHORT_READ"); | |
| 271 case SQLITE_IOERR_WRITE : return wxT("SQLITE_IOERR_WRITE"); | |
| 272 case SQLITE_IOERR_FSYNC : return wxT("SQLITE_IOERR_FSYNC"); | |
| 273 case SQLITE_IOERR_DIR_FSYNC : return wxT("SQLITE_IOERR_DIR_FSYNC"); | |
| 274 case SQLITE_IOERR_TRUNCATE : return wxT("SQLITE_IOERR_TRUNCATE"); | |
| 275 case SQLITE_IOERR_FSTAT : return wxT("SQLITE_IOERR_FSTAT"); | |
| 276 case SQLITE_IOERR_UNLOCK : return wxT("SQLITE_IOERR_UNLOCK"); | |
| 277 case SQLITE_IOERR_RDLOCK : return wxT("SQLITE_IOERR_RDLOCK"); | |
| 278 case SQLITE_IOERR_DELETE : return wxT("SQLITE_IOERR_DELETE"); | |
| 279 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 280 case SQLITE_IOERR_BLOCKED : return wxT("SQLITE_IOERR_BLOCKED"); | |
| 281 #endif | |
| 282 #if SQLITE_VERSION_NUMBER >= 3005001 | |
| 283 case SQLITE_IOERR_NOMEM : return wxT("SQLITE_IOERR_NOMEM"); | |
| 284 #endif | |
| 285 #if SQLITE_VERSION_NUMBER >= 3006000 | |
| 286 case SQLITE_IOERR_ACCESS : return wxT("SQLITE_IOERR_ACCESS"); | |
| 287 case SQLITE_IOERR_CHECKRESERVEDLOCK : return wxT("SQLITE_IOERR_CHECKRESERVEDLOCK"); | |
| 288 #endif | |
| 289 #if SQLITE_VERSION_NUMBER >= 3006002 | |
| 290 case SQLITE_IOERR_LOCK : return wxT("SQLITE_IOERR_LOCK"); | |
| 291 #endif | |
| 292 #if SQLITE_VERSION_NUMBER >= 3006007 | |
| 293 case SQLITE_IOERR_CLOSE : return wxT("SQLITE_IOERR_CLOSE"); | |
| 294 case SQLITE_IOERR_DIR_CLOSE : return wxT("SQLITE_IOERR_DIR_CLOSE"); | |
| 295 #endif | |
| 296 #if SQLITE_VERSION_NUMBER >= 3007000 | |
| 297 case SQLITE_IOERR_SHMOPEN : return wxT("SQLITE_IOERR_SHMOPEN"); | |
| 298 case SQLITE_IOERR_SHMSIZE : return wxT("SQLITE_IOERR_SHMSIZE"); | |
| 299 case SQLITE_IOERR_SHMLOCK : return wxT("SQLITE_IOERR_SHMLOCK"); | |
| 300 case SQLITE_LOCKED_SHAREDCACHE : return wxT("SQLITE_LOCKED_SHAREDCACHE"); | |
| 301 case SQLITE_BUSY_RECOVERY : return wxT("SQLITE_BUSY_RECOVERY"); | |
| 302 case SQLITE_CANTOPEN_NOTEMPDIR : return wxT("SQLITE_CANTOPEN_NOTEMPDIR"); | |
| 303 #endif | |
| 304 | |
| 305 case WXSQLITE_ERROR : return wxT("WXSQLITE_ERROR"); | |
| 306 default : return wxT("UNKNOWN_ERROR"); | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 wxSQLite3Exception::~wxSQLite3Exception() | |
| 311 { | |
| 312 } | |
| 313 | |
| 314 // ---------------------------------------------------------------------------- | |
| 315 // wxSQLite3StatementBuffer: class providing a statement buffer | |
| 316 // for use with the SQLite3 vmprintf function | |
| 317 // ---------------------------------------------------------------------------- | |
| 318 | |
| 319 wxSQLite3StatementBuffer::wxSQLite3StatementBuffer() | |
| 320 { | |
| 321 m_buffer = 0; | |
| 322 } | |
| 323 | |
| 324 wxSQLite3StatementBuffer::~wxSQLite3StatementBuffer() | |
| 325 { | |
| 326 Clear(); | |
| 327 } | |
| 328 | |
| 329 void wxSQLite3StatementBuffer::Clear() | |
| 330 { | |
| 331 if (m_buffer) | |
| 332 { | |
| 333 sqlite3_free(m_buffer); | |
| 334 m_buffer = 0; | |
| 335 } | |
| 336 | |
| 337 } | |
| 338 | |
| 339 const char* wxSQLite3StatementBuffer::Format(const char* format, ...) | |
| 340 { | |
| 341 Clear(); | |
| 342 va_list va; | |
| 343 va_start(va, format); | |
| 344 m_buffer = sqlite3_vmprintf(format, va); | |
| 345 va_end(va); | |
| 346 return m_buffer; | |
| 347 } | |
| 348 | |
| 349 const char* wxSQLite3StatementBuffer::FormatV(const char* format, va_list va) | |
| 350 { | |
| 351 Clear(); | |
| 352 m_buffer = sqlite3_vmprintf(format, va); | |
| 353 return m_buffer; | |
| 354 } | |
| 355 | |
| 356 // ---------------------------------------------------------------------------- | |
| 357 // wxSQLite3ResultSet: class providing access to the result set of a query | |
| 358 // ---------------------------------------------------------------------------- | |
| 359 | |
| 360 wxSQLite3ResultSet::wxSQLite3ResultSet() | |
| 361 { | |
| 362 m_db = 0; | |
| 363 m_stmt = 0; | |
| 364 m_eof = true; | |
| 365 m_first = true; | |
| 366 m_cols = 0; | |
| 367 m_ownStmt = false; | |
| 368 } | |
| 369 | |
| 370 wxSQLite3ResultSet::wxSQLite3ResultSet(const wxSQLite3ResultSet& resultSet) | |
| 371 { | |
| 372 m_db = resultSet.m_db; | |
| 373 m_stmt = resultSet.m_stmt; | |
| 374 // Only one object can own the statement | |
| 375 const_cast<wxSQLite3ResultSet&>(resultSet).m_stmt = 0; | |
| 376 m_eof = resultSet.m_eof; | |
| 377 m_first = resultSet.m_first; | |
| 378 m_cols = resultSet.m_cols; | |
| 379 m_ownStmt = resultSet.m_ownStmt; | |
| 380 } | |
| 381 | |
| 382 wxSQLite3ResultSet::wxSQLite3ResultSet(void* db, | |
| 383 void* stmt, | |
| 384 bool eof, | |
| 385 bool first, | |
| 386 bool ownStmt /*=true*/) | |
| 387 { | |
| 388 m_db = db; | |
| 389 m_stmt = stmt; | |
| 390 m_eof = eof; | |
| 391 m_first = first; | |
| 392 m_cols = sqlite3_column_count((sqlite3_stmt*) m_stmt); | |
| 393 m_ownStmt = ownStmt; | |
| 394 } | |
| 395 | |
| 396 wxSQLite3ResultSet::~wxSQLite3ResultSet() | |
| 397 { | |
| 398 try | |
| 399 { | |
| 400 Finalize(); | |
| 401 } | |
| 402 catch (...) | |
| 403 { | |
| 404 } | |
| 405 } | |
| 406 | |
| 407 wxSQLite3ResultSet& wxSQLite3ResultSet::operator=(const wxSQLite3ResultSet& resultSet) | |
| 408 { | |
| 409 if (this != &resultSet) | |
| 410 { | |
| 411 try | |
| 412 { | |
| 413 Finalize(); | |
| 414 } | |
| 415 catch (...) | |
| 416 { | |
| 417 } | |
| 418 m_db = resultSet.m_db; | |
| 419 m_stmt = resultSet.m_stmt; | |
| 420 // Only one object can own the statement | |
| 421 const_cast<wxSQLite3ResultSet&>(resultSet).m_stmt = 0; | |
| 422 m_eof = resultSet.m_eof; | |
| 423 m_first = resultSet.m_first; | |
| 424 m_cols = resultSet.m_cols; | |
| 425 m_ownStmt = resultSet.m_ownStmt; | |
| 426 } | |
| 427 return *this; | |
| 428 } | |
| 429 | |
| 430 int wxSQLite3ResultSet::GetColumnCount() | |
| 431 { | |
| 432 CheckStmt(); | |
| 433 return m_cols; | |
| 434 } | |
| 435 | |
| 436 wxString wxSQLite3ResultSet::GetAsString(int columnIndex) | |
| 437 { | |
| 438 CheckStmt(); | |
| 439 | |
| 440 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 441 { | |
| 442 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 443 } | |
| 444 | |
| 445 const char* localValue = (const char*) sqlite3_column_text((sqlite3_stmt*) m_stmt, columnIndex); | |
| 446 return wxString::FromUTF8(localValue); | |
| 447 } | |
| 448 | |
| 449 wxString wxSQLite3ResultSet::GetAsString(const wxString& columnName) | |
| 450 { | |
| 451 int columnIndex = FindColumnIndex(columnName); | |
| 452 const char* localValue = (const char*) sqlite3_column_text((sqlite3_stmt*) m_stmt, columnIndex); | |
| 453 return wxString::FromUTF8(localValue); | |
| 454 } | |
| 455 | |
| 456 int wxSQLite3ResultSet::GetInt(int columnIndex, int nullValue /* = 0 */) | |
| 457 { | |
| 458 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 459 { | |
| 460 return nullValue; | |
| 461 } | |
| 462 else | |
| 463 { | |
| 464 return sqlite3_column_int((sqlite3_stmt*) m_stmt, columnIndex); | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 | |
| 469 int wxSQLite3ResultSet::GetInt(const wxString& columnName, int nullValue /* = 0 */) | |
| 470 { | |
| 471 int columnIndex = FindColumnIndex(columnName); | |
| 472 return GetInt(columnIndex, nullValue); | |
| 473 } | |
| 474 | |
| 475 wxLongLong wxSQLite3ResultSet::GetInt64(int columnIndex, wxLongLong nullValue /* = 0 */) | |
| 476 { | |
| 477 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 478 { | |
| 479 return nullValue; | |
| 480 } | |
| 481 else | |
| 482 { | |
| 483 return wxLongLong(sqlite3_column_int64((sqlite3_stmt*) m_stmt, columnIndex)); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 wxLongLong wxSQLite3ResultSet::GetInt64(const wxString& columnName, wxLongLong nullValue /* = 0 */) | |
| 488 { | |
| 489 int columnIndex = FindColumnIndex(columnName); | |
| 490 return GetInt64(columnIndex, nullValue); | |
| 491 } | |
| 492 | |
| 493 double wxSQLite3ResultSet::GetDouble(int columnIndex, double nullValue /* = 0.0 */) | |
| 494 { | |
| 495 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 496 { | |
| 497 return nullValue; | |
| 498 } | |
| 499 else | |
| 500 { | |
| 501 return sqlite3_column_double((sqlite3_stmt*) m_stmt, columnIndex); | |
| 502 } | |
| 503 } | |
| 504 | |
| 505 double wxSQLite3ResultSet::GetDouble(const wxString& columnName, double nullValue /* = 0.0 */) | |
| 506 { | |
| 507 int columnIndex = FindColumnIndex(columnName); | |
| 508 return GetDouble(columnIndex, nullValue); | |
| 509 } | |
| 510 | |
| 511 wxString wxSQLite3ResultSet::GetString(int columnIndex, const wxString& nullValue /* = wxEmptyString */) | |
| 512 { | |
| 513 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 514 { | |
| 515 return nullValue; | |
| 516 } | |
| 517 else | |
| 518 { | |
| 519 const char* localValue = (const char*) sqlite3_column_text((sqlite3_stmt*) m_stmt, columnIndex); | |
| 520 return wxString::FromUTF8(localValue); | |
| 521 } | |
| 522 } | |
| 523 | |
| 524 wxString wxSQLite3ResultSet::GetString(const wxString& columnName, const wxString& nullValue /* = wxEmptyString */) | |
| 525 { | |
| 526 int columnIndex = FindColumnIndex(columnName); | |
| 527 return GetString(columnIndex, nullValue); | |
| 528 } | |
| 529 | |
| 530 const unsigned char* wxSQLite3ResultSet::GetBlob(int columnIndex, int& len) | |
| 531 { | |
| 532 CheckStmt(); | |
| 533 | |
| 534 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 535 { | |
| 536 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 537 } | |
| 538 | |
| 539 len = sqlite3_column_bytes((sqlite3_stmt*) m_stmt, columnIndex); | |
| 540 return (const unsigned char*) sqlite3_column_blob((sqlite3_stmt*) m_stmt, columnIndex); | |
| 541 } | |
| 542 | |
| 543 const unsigned char* wxSQLite3ResultSet::GetBlob(const wxString& columnName, int& len) | |
| 544 { | |
| 545 int columnIndex = FindColumnIndex(columnName); | |
| 546 return GetBlob(columnIndex, len); | |
| 547 } | |
| 548 | |
| 549 wxMemoryBuffer& wxSQLite3ResultSet::GetBlob(int columnIndex, wxMemoryBuffer& buffer) | |
| 550 { | |
| 551 CheckStmt(); | |
| 552 | |
| 553 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 554 { | |
| 555 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 556 } | |
| 557 | |
| 558 int len = sqlite3_column_bytes((sqlite3_stmt*) m_stmt, columnIndex); | |
| 559 const void* blob = sqlite3_column_blob((sqlite3_stmt*) m_stmt, columnIndex); | |
| 560 buffer.AppendData((void*) blob, (size_t) len); | |
| 561 return buffer; | |
| 562 } | |
| 563 | |
| 564 wxMemoryBuffer& wxSQLite3ResultSet::GetBlob(const wxString& columnName, wxMemoryBuffer& buffer) | |
| 565 { | |
| 566 int columnIndex = FindColumnIndex(columnName); | |
| 567 return GetBlob(columnIndex, buffer); | |
| 568 } | |
| 569 | |
| 570 wxDateTime wxSQLite3ResultSet::GetDate(int columnIndex) | |
| 571 { | |
| 572 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 573 { | |
| 574 return wxInvalidDateTime; | |
| 575 } | |
| 576 else | |
| 577 { | |
| 578 wxDateTime date; | |
| 579 if (date.ParseDate(GetString(columnIndex)) != NULL) | |
| 580 { | |
| 581 return date; | |
| 582 } | |
| 583 else | |
| 584 { | |
| 585 return wxInvalidDateTime; | |
| 586 } | |
| 587 } | |
| 588 } | |
| 589 | |
| 590 wxDateTime wxSQLite3ResultSet::GetDate(const wxString& columnName) | |
| 591 { | |
| 592 int columnIndex = FindColumnIndex(columnName); | |
| 593 return GetDate(columnIndex); | |
| 594 } | |
| 595 | |
| 596 | |
| 597 wxDateTime wxSQLite3ResultSet::GetTime(int columnIndex) | |
| 598 { | |
| 599 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 600 { | |
| 601 return wxInvalidDateTime; | |
| 602 } | |
| 603 else | |
| 604 { | |
| 605 wxDateTime date; | |
| 606 if (date.ParseTime(GetString(columnIndex)) != NULL) | |
| 607 { | |
| 608 return date; | |
| 609 } | |
| 610 else | |
| 611 { | |
| 612 return wxInvalidDateTime; | |
| 613 } | |
| 614 } | |
| 615 } | |
| 616 | |
| 617 wxDateTime wxSQLite3ResultSet::GetTime(const wxString& columnName) | |
| 618 { | |
| 619 int columnIndex = FindColumnIndex(columnName); | |
| 620 return GetTime(columnIndex); | |
| 621 } | |
| 622 | |
| 623 wxDateTime wxSQLite3ResultSet::GetDateTime(int columnIndex) | |
| 624 { | |
| 625 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 626 { | |
| 627 return wxInvalidDateTime; | |
| 628 } | |
| 629 else | |
| 630 { | |
| 631 wxDateTime date; | |
| 632 if (date.ParseDateTime(GetString(columnIndex)) != NULL) | |
| 633 { | |
| 634 date.SetMillisecond(0); | |
| 635 return date; | |
| 636 } | |
| 637 else | |
| 638 { | |
| 639 return wxInvalidDateTime; | |
| 640 } | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 wxDateTime wxSQLite3ResultSet::GetDateTime(const wxString& columnName) | |
| 645 { | |
| 646 int columnIndex = FindColumnIndex(columnName); | |
| 647 return GetDateTime(columnIndex); | |
| 648 } | |
| 649 | |
| 650 wxDateTime wxSQLite3ResultSet::GetTimestamp(int columnIndex) | |
| 651 { | |
| 652 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 653 { | |
| 654 return wxInvalidDateTime; | |
| 655 } | |
| 656 else | |
| 657 { | |
| 658 wxDateTime date; | |
| 659 if (date.ParseDateTime(GetString(columnIndex)) != NULL) | |
| 660 { | |
| 661 return date; | |
| 662 } | |
| 663 else | |
| 664 { | |
| 665 return wxInvalidDateTime; | |
| 666 } | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 wxDateTime wxSQLite3ResultSet::GetTimestamp(const wxString& columnName) | |
| 671 { | |
| 672 int columnIndex = FindColumnIndex(columnName); | |
| 673 return GetTimestamp(columnIndex); | |
| 674 } | |
| 675 | |
| 676 wxDateTime wxSQLite3ResultSet::GetNumericDateTime(int columnIndex) | |
| 677 { | |
| 678 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 679 { | |
| 680 return wxInvalidDateTime; | |
| 681 } | |
| 682 else | |
| 683 { | |
| 684 wxLongLong value = GetInt64(columnIndex); | |
| 685 return wxDateTime(value); | |
| 686 } | |
| 687 } | |
| 688 | |
| 689 wxDateTime wxSQLite3ResultSet::GetNumericDateTime(const wxString& columnName) | |
| 690 { | |
| 691 int columnIndex = FindColumnIndex(columnName); | |
| 692 return GetNumericDateTime(columnIndex); | |
| 693 } | |
| 694 | |
| 695 wxDateTime wxSQLite3ResultSet::GetJulianDayNumber(int columnIndex) | |
| 696 { | |
| 697 if (GetColumnType(columnIndex) == SQLITE_NULL) | |
| 698 { | |
| 699 return wxInvalidDateTime; | |
| 700 } | |
| 701 else | |
| 702 { | |
| 703 double value = GetDouble(columnIndex); | |
| 704 return wxDateTime(value); | |
| 705 } | |
| 706 } | |
| 707 | |
| 708 wxDateTime wxSQLite3ResultSet::GetJulianDayNumber(const wxString& columnName) | |
| 709 { | |
| 710 int columnIndex = FindColumnIndex(columnName); | |
| 711 return GetJulianDayNumber(columnIndex); | |
| 712 } | |
| 713 | |
| 714 bool wxSQLite3ResultSet::GetBool(int columnIndex) | |
| 715 { | |
| 716 return GetInt(columnIndex) != 0; | |
| 717 } | |
| 718 | |
| 719 bool wxSQLite3ResultSet::GetBool(const wxString& columnName) | |
| 720 { | |
| 721 int columnIndex = FindColumnIndex(columnName); | |
| 722 return GetBool(columnIndex); | |
| 723 } | |
| 724 | |
| 725 bool wxSQLite3ResultSet::IsNull(int columnIndex) | |
| 726 { | |
| 727 return (GetColumnType(columnIndex) == SQLITE_NULL); | |
| 728 } | |
| 729 | |
| 730 bool wxSQLite3ResultSet::IsNull(const wxString& columnName) | |
| 731 { | |
| 732 int columnIndex = FindColumnIndex(columnName); | |
| 733 return (GetColumnType(columnIndex) == SQLITE_NULL); | |
| 734 } | |
| 735 | |
| 736 int wxSQLite3ResultSet::FindColumnIndex(const wxString& columnName) | |
| 737 { | |
| 738 CheckStmt(); | |
| 739 | |
| 740 wxCharBuffer strColumnName = columnName.ToUTF8(); | |
| 741 const char* localColumnName = strColumnName; | |
| 742 | |
| 743 if (columnName.Len() > 0) | |
| 744 { | |
| 745 for (int columnIndex = 0; columnIndex < m_cols; columnIndex++) | |
| 746 { | |
| 747 const char* temp = sqlite3_column_name((sqlite3_stmt*) m_stmt, columnIndex); | |
| 748 | |
| 749 if (strcmp(localColumnName, temp) == 0) | |
| 750 { | |
| 751 return columnIndex; | |
| 752 } | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 757 } | |
| 758 | |
| 759 wxString wxSQLite3ResultSet::GetColumnName(int columnIndex) | |
| 760 { | |
| 761 CheckStmt(); | |
| 762 | |
| 763 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 764 { | |
| 765 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 766 } | |
| 767 | |
| 768 const char* localValue = sqlite3_column_name((sqlite3_stmt*) m_stmt, columnIndex); | |
| 769 return wxString::FromUTF8(localValue); | |
| 770 } | |
| 771 | |
| 772 wxString wxSQLite3ResultSet::GetDeclaredColumnType(int columnIndex) | |
| 773 { | |
| 774 CheckStmt(); | |
| 775 | |
| 776 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 777 { | |
| 778 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 779 } | |
| 780 | |
| 781 const char* localValue = sqlite3_column_decltype((sqlite3_stmt*) m_stmt, columnIndex); | |
| 782 return wxString::FromUTF8(localValue); | |
| 783 } | |
| 784 | |
| 785 int wxSQLite3ResultSet::GetColumnType(int columnIndex) | |
| 786 { | |
| 787 CheckStmt(); | |
| 788 | |
| 789 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 790 { | |
| 791 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 792 } | |
| 793 | |
| 794 return sqlite3_column_type((sqlite3_stmt*) m_stmt, columnIndex); | |
| 795 } | |
| 796 | |
| 797 bool wxSQLite3ResultSet::Eof() | |
| 798 { | |
| 799 CheckStmt(); | |
| 800 return m_eof; | |
| 801 } | |
| 802 | |
| 803 bool wxSQLite3ResultSet::NextRow() | |
| 804 { | |
| 805 CheckStmt(); | |
| 806 | |
| 807 int rc; | |
| 808 if (m_first) | |
| 809 { | |
| 810 m_first = false; | |
| 811 rc = (m_eof) ? SQLITE_DONE : SQLITE_ROW; | |
| 812 } | |
| 813 else | |
| 814 { | |
| 815 rc = sqlite3_step((sqlite3_stmt*) m_stmt); | |
| 816 } | |
| 817 | |
| 818 if (rc == SQLITE_DONE) // no more rows | |
| 819 { | |
| 820 m_eof = true; | |
| 821 return false; | |
| 822 } | |
| 823 else if (rc == SQLITE_ROW) // more rows | |
| 824 { | |
| 825 return true; | |
| 826 } | |
| 827 else | |
| 828 { | |
| 829 rc = sqlite3_finalize((sqlite3_stmt*) m_stmt); | |
| 830 m_stmt = 0; | |
| 831 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 832 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 833 } | |
| 834 } | |
| 835 | |
| 836 void wxSQLite3ResultSet::Finalize() | |
| 837 { | |
| 838 if (m_stmt && m_ownStmt) | |
| 839 { | |
| 840 int rc = sqlite3_finalize((sqlite3_stmt*) m_stmt); | |
| 841 m_stmt = 0; | |
| 842 if (rc != SQLITE_OK) | |
| 843 { | |
| 844 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 845 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 846 } | |
| 847 } | |
| 848 } | |
| 849 | |
| 850 wxString wxSQLite3ResultSet::GetSQL() | |
| 851 { | |
| 852 wxString sqlString = wxEmptyString; | |
| 853 #if SQLITE_VERSION_NUMBER >= 3005003 | |
| 854 CheckStmt(); | |
| 855 const char* sqlLocal = sqlite3_sql((sqlite3_stmt*) m_stmt); | |
| 856 if (sqlLocal != NULL) sqlString = wxString::FromUTF8(sqlLocal); | |
| 857 #endif | |
| 858 return sqlString; | |
| 859 } | |
| 860 | |
| 861 bool wxSQLite3ResultSet::IsOk() | |
| 862 { | |
| 863 return (m_db != 0) && (m_stmt != 0); | |
| 864 } | |
| 865 | |
| 866 void wxSQLite3ResultSet::CheckStmt() | |
| 867 { | |
| 868 if (m_stmt == 0) | |
| 869 { | |
| 870 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOSTMT); | |
| 871 } | |
| 872 } | |
| 873 | |
| 874 wxString wxSQLite3ResultSet::GetDatabaseName(int columnIndex) | |
| 875 { | |
| 876 #if WXSQLITE3_HAVE_METADATA | |
| 877 CheckStmt(); | |
| 878 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 879 { | |
| 880 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 881 } | |
| 882 | |
| 883 const char* localValue = sqlite3_column_database_name((sqlite3_stmt*) m_stmt, columnIndex); | |
| 884 if (localValue != NULL) | |
| 885 return wxString::FromUTF8(localValue); | |
| 886 else | |
| 887 return wxEmptyString; | |
| 888 #else | |
| 889 wxUnusedVar(columnIndex); | |
| 890 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMETADATA); | |
| 891 #endif | |
| 892 } | |
| 893 | |
| 894 wxString wxSQLite3ResultSet::GetTableName(int columnIndex) | |
| 895 { | |
| 896 #if WXSQLITE3_HAVE_METADATA | |
| 897 CheckStmt(); | |
| 898 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 899 { | |
| 900 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 901 } | |
| 902 | |
| 903 const char* localValue = sqlite3_column_table_name((sqlite3_stmt*) m_stmt, columnIndex); | |
| 904 if (localValue != NULL) | |
| 905 return wxString::FromUTF8(localValue); | |
| 906 else | |
| 907 return wxEmptyString; | |
| 908 #else | |
| 909 wxUnusedVar(columnIndex); | |
| 910 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMETADATA); | |
| 911 #endif | |
| 912 } | |
| 913 | |
| 914 wxString wxSQLite3ResultSet::GetOriginName(int columnIndex) | |
| 915 { | |
| 916 #if WXSQLITE3_HAVE_METADATA | |
| 917 CheckStmt(); | |
| 918 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 919 { | |
| 920 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 921 } | |
| 922 | |
| 923 const char* localValue = sqlite3_column_origin_name((sqlite3_stmt*) m_stmt, columnIndex); | |
| 924 if (localValue != NULL) | |
| 925 return wxString::FromUTF8(localValue); | |
| 926 else | |
| 927 return wxEmptyString; | |
| 928 #else | |
| 929 wxUnusedVar(columnIndex); | |
| 930 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMETADATA); | |
| 931 #endif | |
| 932 } | |
| 933 | |
| 934 // ---------------------------------------------------------------------------- | |
| 935 // wxSQLite3Table: class holding the complete result set of a query | |
| 936 // ---------------------------------------------------------------------------- | |
| 937 | |
| 938 wxSQLite3Table::wxSQLite3Table() | |
| 939 { | |
| 940 m_results = 0; | |
| 941 m_rows = 0; | |
| 942 m_cols = 0; | |
| 943 m_currentRow = 0; | |
| 944 } | |
| 945 | |
| 946 wxSQLite3Table::wxSQLite3Table(const wxSQLite3Table& table) | |
| 947 { | |
| 948 m_results = table.m_results; | |
| 949 // Only one object can own the results | |
| 950 const_cast<wxSQLite3Table&>(table).m_results = 0; | |
| 951 m_rows = table.m_rows; | |
| 952 m_cols = table.m_cols; | |
| 953 m_currentRow = table.m_currentRow; | |
| 954 } | |
| 955 | |
| 956 wxSQLite3Table::wxSQLite3Table(char** results, int rows, int cols) | |
| 957 { | |
| 958 m_results = results; | |
| 959 m_rows = rows; | |
| 960 m_cols = cols; | |
| 961 m_currentRow = 0; | |
| 962 } | |
| 963 | |
| 964 wxSQLite3Table::~wxSQLite3Table() | |
| 965 { | |
| 966 try | |
| 967 { | |
| 968 Finalize(); | |
| 969 } | |
| 970 catch (...) | |
| 971 { | |
| 972 } | |
| 973 } | |
| 974 | |
| 975 wxSQLite3Table& wxSQLite3Table::operator=(const wxSQLite3Table& table) | |
| 976 { | |
| 977 if (this != &table) | |
| 978 { | |
| 979 try | |
| 980 { | |
| 981 Finalize(); | |
| 982 } | |
| 983 catch (...) | |
| 984 { | |
| 985 } | |
| 986 m_results = table.m_results; | |
| 987 // Only one object can own the results | |
| 988 const_cast<wxSQLite3Table&>(table).m_results = 0; | |
| 989 m_rows = table.m_rows; | |
| 990 m_cols = table.m_cols; | |
| 991 m_currentRow = table.m_currentRow; | |
| 992 } | |
| 993 return *this; | |
| 994 } | |
| 995 | |
| 996 void wxSQLite3Table::Finalize() | |
| 997 { | |
| 998 if (m_results) | |
| 999 { | |
| 1000 sqlite3_free_table(m_results); | |
| 1001 m_results = 0; | |
| 1002 } | |
| 1003 } | |
| 1004 | |
| 1005 int wxSQLite3Table::GetColumnCount() | |
| 1006 { | |
| 1007 CheckResults(); | |
| 1008 return m_cols; | |
| 1009 } | |
| 1010 | |
| 1011 int wxSQLite3Table::GetRowCount() | |
| 1012 { | |
| 1013 CheckResults(); | |
| 1014 return m_rows; | |
| 1015 } | |
| 1016 | |
| 1017 int wxSQLite3Table::FindColumnIndex(const wxString& columnName) | |
| 1018 { | |
| 1019 CheckResults(); | |
| 1020 | |
| 1021 wxCharBuffer strColumnName = columnName.ToUTF8(); | |
| 1022 const char* localColumnName = strColumnName; | |
| 1023 | |
| 1024 if (columnName.Len() > 0) | |
| 1025 { | |
| 1026 for (int columnIndex = 0; columnIndex < m_cols; columnIndex++) | |
| 1027 { | |
| 1028 if (strcmp(localColumnName, m_results[columnIndex]) == 0) | |
| 1029 { | |
| 1030 return columnIndex; | |
| 1031 } | |
| 1032 } | |
| 1033 } | |
| 1034 | |
| 1035 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_NAME); | |
| 1036 } | |
| 1037 | |
| 1038 wxString wxSQLite3Table::GetAsString(int columnIndex) | |
| 1039 { | |
| 1040 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 1041 { | |
| 1042 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 1043 } | |
| 1044 | |
| 1045 int nIndex = (m_currentRow*m_cols) + m_cols + columnIndex; | |
| 1046 const char* localValue = m_results[nIndex]; | |
| 1047 return wxString::FromUTF8(localValue); | |
| 1048 } | |
| 1049 | |
| 1050 wxString wxSQLite3Table::GetAsString(const wxString& columnName) | |
| 1051 { | |
| 1052 int index = FindColumnIndex(columnName); | |
| 1053 return GetAsString(index); | |
| 1054 } | |
| 1055 | |
| 1056 int wxSQLite3Table::GetInt(int columnIndex, int nullValue /* = 0 */) | |
| 1057 { | |
| 1058 if (IsNull(columnIndex)) | |
| 1059 { | |
| 1060 return nullValue; | |
| 1061 } | |
| 1062 else | |
| 1063 { | |
| 1064 long value = nullValue; | |
| 1065 GetAsString(columnIndex).ToLong(&value); | |
| 1066 return (int) value; | |
| 1067 } | |
| 1068 } | |
| 1069 | |
| 1070 int wxSQLite3Table::GetInt(const wxString& columnName, int nullValue /* = 0 */) | |
| 1071 { | |
| 1072 if (IsNull(columnName)) | |
| 1073 { | |
| 1074 return nullValue; | |
| 1075 } | |
| 1076 else | |
| 1077 { | |
| 1078 long value = nullValue; | |
| 1079 GetAsString(columnName).ToLong(&value); | |
| 1080 return (int) value; | |
| 1081 } | |
| 1082 } | |
| 1083 | |
| 1084 wxLongLong wxSQLite3Table::GetInt64(int columnIndex, wxLongLong nullValue /* = 0 */) | |
| 1085 { | |
| 1086 if (IsNull(columnIndex)) | |
| 1087 { | |
| 1088 return nullValue; | |
| 1089 } | |
| 1090 else | |
| 1091 { | |
| 1092 return ConvertStringToLongLong(GetAsString(columnIndex), nullValue); | |
| 1093 } | |
| 1094 } | |
| 1095 | |
| 1096 wxLongLong wxSQLite3Table::GetInt64(const wxString& columnName, wxLongLong nullValue /* = 0 */) | |
| 1097 { | |
| 1098 if (IsNull(columnName)) | |
| 1099 { | |
| 1100 return nullValue; | |
| 1101 } | |
| 1102 else | |
| 1103 { | |
| 1104 return ConvertStringToLongLong(GetAsString(columnName), nullValue); | |
| 1105 } | |
| 1106 } | |
| 1107 | |
| 1108 // Since SQLite uses internally a locale independent string representation | |
| 1109 // of double values, we need to provide our own conversion procedure using | |
| 1110 // always a point as the decimal separator. | |
| 1111 // The following code duplicates a SQLite utility function with minor modifications. | |
| 1112 | |
| 1113 static double wxSQLite3AtoF(const char *z) | |
| 1114 { | |
| 1115 int sign = 1; | |
| 1116 long double v1 = 0.0; | |
| 1117 int nSignificant = 0; | |
| 1118 while (isspace(*(unsigned char*)z)) | |
| 1119 { | |
| 1120 ++z; | |
| 1121 } | |
| 1122 if (*z == '-') | |
| 1123 { | |
| 1124 sign = -1; | |
| 1125 ++z; | |
| 1126 } | |
| 1127 else if (*z == '+') | |
| 1128 { | |
| 1129 ++z; | |
| 1130 } | |
| 1131 while (*z == '0') | |
| 1132 { | |
| 1133 ++z; | |
| 1134 } | |
| 1135 while (isdigit(*(unsigned char*)z)) | |
| 1136 { | |
| 1137 v1 = v1*10.0 + (*z - '0'); | |
| 1138 ++z; | |
| 1139 ++nSignificant; | |
| 1140 } | |
| 1141 if (*z == '.') | |
| 1142 { | |
| 1143 long double divisor = 1.0; | |
| 1144 ++z; | |
| 1145 if (nSignificant == 0) | |
| 1146 { | |
| 1147 while (*z == '0') | |
| 1148 { | |
| 1149 divisor *= 10.0; | |
| 1150 ++z; | |
| 1151 } | |
| 1152 } | |
| 1153 while (isdigit(*(unsigned char*)z)) | |
| 1154 { | |
| 1155 if (nSignificant < 18) | |
| 1156 { | |
| 1157 v1 = v1*10.0 + (*z - '0'); | |
| 1158 divisor *= 10.0; | |
| 1159 ++nSignificant; | |
| 1160 } | |
| 1161 ++z; | |
| 1162 } | |
| 1163 v1 /= divisor; | |
| 1164 } | |
| 1165 if (*z=='e' || *z=='E') | |
| 1166 { | |
| 1167 int esign = 1; | |
| 1168 int eval = 0; | |
| 1169 long double scale = 1.0; | |
| 1170 ++z; | |
| 1171 if (*z == '-') | |
| 1172 { | |
| 1173 esign = -1; | |
| 1174 ++z; | |
| 1175 } | |
| 1176 else if (*z == '+') | |
| 1177 { | |
| 1178 ++z; | |
| 1179 } | |
| 1180 while (isdigit(*(unsigned char*)z)) | |
| 1181 { | |
| 1182 eval = eval*10 + *z - '0'; | |
| 1183 ++z; | |
| 1184 } | |
| 1185 while (eval >= 64) { scale *= 1.0e+64; eval -= 64; } | |
| 1186 while (eval >= 16) { scale *= 1.0e+16; eval -= 16; } | |
| 1187 while (eval >= 4) { scale *= 1.0e+4; eval -= 4; } | |
| 1188 while (eval >= 1) { scale *= 1.0e+1; eval -= 1; } | |
| 1189 if (esign < 0) | |
| 1190 { | |
| 1191 v1 /= scale; | |
| 1192 } | |
| 1193 else | |
| 1194 { | |
| 1195 v1 *= scale; | |
| 1196 } | |
| 1197 } | |
| 1198 return (double) ((sign < 0) ? -v1 : v1); | |
| 1199 } | |
| 1200 | |
| 1201 double wxSQLite3Table::GetDouble(int columnIndex, double nullValue /* = 0.0 */) | |
| 1202 { | |
| 1203 if (IsNull(columnIndex)) | |
| 1204 { | |
| 1205 return nullValue; | |
| 1206 } | |
| 1207 else | |
| 1208 { | |
| 1209 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 1210 { | |
| 1211 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 1212 } | |
| 1213 int nIndex = (m_currentRow*m_cols) + m_cols + columnIndex; | |
| 1214 return wxSQLite3AtoF(m_results[nIndex]); | |
| 1215 } | |
| 1216 } | |
| 1217 | |
| 1218 double wxSQLite3Table::GetDouble(const wxString& columnName, double nullValue /* = 0.0 */) | |
| 1219 { | |
| 1220 int index = FindColumnIndex(columnName); | |
| 1221 return GetDouble(index, nullValue); | |
| 1222 } | |
| 1223 | |
| 1224 wxString wxSQLite3Table::GetString(int columnIndex, const wxString& nullValue /* = wxEmptyString */) | |
| 1225 { | |
| 1226 if (IsNull(columnIndex)) | |
| 1227 { | |
| 1228 return nullValue; | |
| 1229 } | |
| 1230 else | |
| 1231 { | |
| 1232 return GetAsString(columnIndex); | |
| 1233 } | |
| 1234 } | |
| 1235 | |
| 1236 wxString wxSQLite3Table::GetString(const wxString& columnName, const wxString& nullValue /* = wxEmptyString */) | |
| 1237 { | |
| 1238 if (IsNull(columnName)) | |
| 1239 { | |
| 1240 return nullValue; | |
| 1241 } | |
| 1242 else | |
| 1243 { | |
| 1244 return GetAsString(columnName); | |
| 1245 } | |
| 1246 } | |
| 1247 | |
| 1248 wxDateTime wxSQLite3Table::GetDate(int columnIndex) | |
| 1249 { | |
| 1250 wxDateTime date; | |
| 1251 if (date.ParseDate(GetString(columnIndex)) != NULL) | |
| 1252 { | |
| 1253 return date; | |
| 1254 } | |
| 1255 else | |
| 1256 { | |
| 1257 return wxInvalidDateTime; | |
| 1258 } | |
| 1259 } | |
| 1260 | |
| 1261 wxDateTime wxSQLite3Table::GetDate(const wxString& columnName) | |
| 1262 { | |
| 1263 int columnIndex = FindColumnIndex(columnName); | |
| 1264 return GetDate(columnIndex); | |
| 1265 } | |
| 1266 | |
| 1267 wxDateTime wxSQLite3Table::GetTime(int columnIndex) | |
| 1268 { | |
| 1269 wxDateTime date; | |
| 1270 if (date.ParseTime(GetString(columnIndex)) != NULL) | |
| 1271 { | |
| 1272 return date; | |
| 1273 } | |
| 1274 else | |
| 1275 { | |
| 1276 return wxInvalidDateTime; | |
| 1277 } | |
| 1278 } | |
| 1279 | |
| 1280 wxDateTime wxSQLite3Table::GetTime(const wxString& columnName) | |
| 1281 { | |
| 1282 int columnIndex = FindColumnIndex(columnName); | |
| 1283 return GetTime(columnIndex); | |
| 1284 } | |
| 1285 | |
| 1286 wxDateTime wxSQLite3Table::GetDateTime(int columnIndex) | |
| 1287 { | |
| 1288 wxDateTime date; | |
| 1289 if (date.ParseDateTime(GetString(columnIndex)) != NULL) | |
| 1290 { | |
| 1291 return date; | |
| 1292 } | |
| 1293 else | |
| 1294 { | |
| 1295 return wxInvalidDateTime; | |
| 1296 } | |
| 1297 } | |
| 1298 | |
| 1299 wxDateTime wxSQLite3Table::GetDateTime(const wxString& columnName) | |
| 1300 { | |
| 1301 int columnIndex = FindColumnIndex(columnName); | |
| 1302 return GetDateTime(columnIndex); | |
| 1303 } | |
| 1304 | |
| 1305 bool wxSQLite3Table::GetBool(int columnIndex) | |
| 1306 { | |
| 1307 return GetInt(columnIndex) != 0; | |
| 1308 } | |
| 1309 | |
| 1310 bool wxSQLite3Table::GetBool(const wxString& columnName) | |
| 1311 { | |
| 1312 int columnIndex = FindColumnIndex(columnName); | |
| 1313 return GetBool(columnIndex); | |
| 1314 } | |
| 1315 | |
| 1316 bool wxSQLite3Table::IsNull(int columnIndex) | |
| 1317 { | |
| 1318 CheckResults(); | |
| 1319 | |
| 1320 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 1321 { | |
| 1322 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 1323 } | |
| 1324 | |
| 1325 int index = (m_currentRow*m_cols) + m_cols + columnIndex; | |
| 1326 const char* localValue = m_results[index]; | |
| 1327 return (localValue == 0); | |
| 1328 } | |
| 1329 | |
| 1330 bool wxSQLite3Table::IsNull(const wxString& columnName) | |
| 1331 { | |
| 1332 int index = FindColumnIndex(columnName); | |
| 1333 return IsNull(index); | |
| 1334 } | |
| 1335 | |
| 1336 wxString wxSQLite3Table::GetColumnName(int columnIndex) | |
| 1337 { | |
| 1338 CheckResults(); | |
| 1339 | |
| 1340 if (columnIndex < 0 || columnIndex > m_cols-1) | |
| 1341 { | |
| 1342 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_INDEX); | |
| 1343 } | |
| 1344 | |
| 1345 const char* localValue = m_results[columnIndex]; | |
| 1346 return wxString::FromUTF8(localValue); | |
| 1347 } | |
| 1348 | |
| 1349 void wxSQLite3Table::SetRow(int row) | |
| 1350 { | |
| 1351 CheckResults(); | |
| 1352 | |
| 1353 if (row < 0 || row > m_rows-1) | |
| 1354 { | |
| 1355 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_ROW); | |
| 1356 } | |
| 1357 | |
| 1358 m_currentRow = row; | |
| 1359 } | |
| 1360 | |
| 1361 bool wxSQLite3Table::IsOk() | |
| 1362 { | |
| 1363 return (m_results != 0); | |
| 1364 } | |
| 1365 | |
| 1366 void wxSQLite3Table::CheckResults() | |
| 1367 { | |
| 1368 if (m_results == 0) | |
| 1369 { | |
| 1370 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NORESULT); | |
| 1371 } | |
| 1372 } | |
| 1373 | |
| 1374 // ---------------------------------------------------------------------------- | |
| 1375 // wxSQLite3Statement: class holding a prepared statement | |
| 1376 // ---------------------------------------------------------------------------- | |
| 1377 | |
| 1378 wxSQLite3Statement::wxSQLite3Statement() | |
| 1379 { | |
| 1380 m_db = 0; | |
| 1381 m_stmt = 0; | |
| 1382 m_hasOwnership = false; | |
| 1383 } | |
| 1384 | |
| 1385 wxSQLite3Statement::wxSQLite3Statement(const wxSQLite3Statement& statement) | |
| 1386 { | |
| 1387 m_db = statement.m_db; | |
| 1388 m_stmt = statement.m_stmt; | |
| 1389 m_hasOwnership = statement.m_hasOwnership; | |
| 1390 // Only one object can own prepared statement | |
| 1391 const_cast<wxSQLite3Statement&>(statement).m_hasOwnership = false; | |
| 1392 } | |
| 1393 | |
| 1394 wxSQLite3Statement::wxSQLite3Statement(void* db, void* stmt) | |
| 1395 { | |
| 1396 m_db = db; | |
| 1397 m_stmt = stmt; | |
| 1398 m_hasOwnership = true; | |
| 1399 } | |
| 1400 | |
| 1401 wxSQLite3Statement::~wxSQLite3Statement() | |
| 1402 { | |
| 1403 try | |
| 1404 { | |
| 1405 Finalize(); | |
| 1406 } | |
| 1407 catch (...) | |
| 1408 { | |
| 1409 } | |
| 1410 } | |
| 1411 | |
| 1412 wxSQLite3Statement& wxSQLite3Statement::operator=(const wxSQLite3Statement& statement) | |
| 1413 { | |
| 1414 if (this != &statement) | |
| 1415 { | |
| 1416 try | |
| 1417 { | |
| 1418 Finalize(); | |
| 1419 } | |
| 1420 catch (...) | |
| 1421 { | |
| 1422 } | |
| 1423 m_db = statement.m_db; | |
| 1424 m_stmt = statement.m_stmt; | |
| 1425 m_hasOwnership = statement.m_hasOwnership; | |
| 1426 // Only one object can own prepared statement | |
| 1427 const_cast<wxSQLite3Statement&>(statement).m_hasOwnership = false; | |
| 1428 } | |
| 1429 return *this; | |
| 1430 } | |
| 1431 | |
| 1432 int wxSQLite3Statement::ExecuteUpdate() | |
| 1433 { | |
| 1434 CheckDatabase(); | |
| 1435 CheckStmt(); | |
| 1436 | |
| 1437 const char* localError=0; | |
| 1438 | |
| 1439 int rc = sqlite3_step((sqlite3_stmt*) m_stmt); | |
| 1440 | |
| 1441 if (rc == SQLITE_DONE) | |
| 1442 { | |
| 1443 int rowsChanged = sqlite3_changes((sqlite3*) m_db); | |
| 1444 | |
| 1445 rc = sqlite3_reset((sqlite3_stmt*) m_stmt); | |
| 1446 | |
| 1447 if (rc != SQLITE_OK) | |
| 1448 { | |
| 1449 localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1450 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1451 } | |
| 1452 | |
| 1453 return rowsChanged; | |
| 1454 } | |
| 1455 else | |
| 1456 { | |
| 1457 rc = sqlite3_reset((sqlite3_stmt*) m_stmt); | |
| 1458 localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1459 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1460 } | |
| 1461 } | |
| 1462 | |
| 1463 wxSQLite3ResultSet wxSQLite3Statement::ExecuteQuery(bool transferStatementOwnership) | |
| 1464 { | |
| 1465 CheckDatabase(); | |
| 1466 CheckStmt(); | |
| 1467 if (transferStatementOwnership) | |
| 1468 { | |
| 1469 if (m_hasOwnership) | |
| 1470 { | |
| 1471 m_hasOwnership = false; | |
| 1472 } | |
| 1473 else | |
| 1474 { | |
| 1475 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOTOWNED); | |
| 1476 } | |
| 1477 } | |
| 1478 | |
| 1479 int rc = sqlite3_step((sqlite3_stmt*) m_stmt); | |
| 1480 | |
| 1481 if (rc == SQLITE_DONE) // no more rows | |
| 1482 { | |
| 1483 return wxSQLite3ResultSet(m_db, m_stmt, true/*eof*/, true/*first*/, transferStatementOwnership); | |
| 1484 } | |
| 1485 else if (rc == SQLITE_ROW) // one or more rows | |
| 1486 { | |
| 1487 return wxSQLite3ResultSet(m_db, m_stmt, false/*eof*/, true/*first*/, transferStatementOwnership); | |
| 1488 } | |
| 1489 else | |
| 1490 { | |
| 1491 rc = sqlite3_reset((sqlite3_stmt*) m_stmt); | |
| 1492 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1493 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1494 } | |
| 1495 } | |
| 1496 | |
| 1497 int wxSQLite3Statement::GetParamCount() | |
| 1498 { | |
| 1499 CheckStmt(); | |
| 1500 return sqlite3_bind_parameter_count((sqlite3_stmt*) m_stmt); | |
| 1501 } | |
| 1502 | |
| 1503 int wxSQLite3Statement::GetParamIndex(const wxString& paramName) | |
| 1504 { | |
| 1505 CheckStmt(); | |
| 1506 | |
| 1507 wxCharBuffer strParamName = paramName.ToUTF8(); | |
| 1508 const char* localParamName = strParamName; | |
| 1509 | |
| 1510 return sqlite3_bind_parameter_index((sqlite3_stmt*) m_stmt, localParamName); | |
| 1511 } | |
| 1512 | |
| 1513 wxString wxSQLite3Statement::GetParamName(int paramIndex) | |
| 1514 { | |
| 1515 CheckStmt(); | |
| 1516 const char* localParamName = sqlite3_bind_parameter_name((sqlite3_stmt*) m_stmt, paramIndex); | |
| 1517 return wxString::FromUTF8(localParamName); | |
| 1518 } | |
| 1519 | |
| 1520 void wxSQLite3Statement::Bind(int paramIndex, const wxString& stringValue) | |
| 1521 { | |
| 1522 CheckStmt(); | |
| 1523 | |
| 1524 wxCharBuffer strStringValue = stringValue.ToUTF8(); | |
| 1525 const char* localStringValue = strStringValue; | |
| 1526 | |
| 1527 int rc = sqlite3_bind_text((sqlite3_stmt*) m_stmt, paramIndex, localStringValue, -1, SQLITE_TRANSIENT); | |
| 1528 | |
| 1529 if (rc != SQLITE_OK) | |
| 1530 { | |
| 1531 throw wxSQLite3Exception(rc, wxERRMSG_BIND_STR); | |
| 1532 } | |
| 1533 } | |
| 1534 | |
| 1535 void wxSQLite3Statement::Bind(int paramIndex, int intValue) | |
| 1536 { | |
| 1537 CheckStmt(); | |
| 1538 int rc = sqlite3_bind_int((sqlite3_stmt*) m_stmt, paramIndex, intValue); | |
| 1539 | |
| 1540 if (rc != SQLITE_OK) | |
| 1541 { | |
| 1542 throw wxSQLite3Exception(rc, wxERRMSG_BIND_INT); | |
| 1543 } | |
| 1544 } | |
| 1545 | |
| 1546 void wxSQLite3Statement::Bind(int paramIndex, wxLongLong int64Value) | |
| 1547 { | |
| 1548 CheckStmt(); | |
| 1549 int rc = sqlite3_bind_int64((sqlite3_stmt*) m_stmt, paramIndex, int64Value.GetValue()); | |
| 1550 | |
| 1551 if (rc != SQLITE_OK) | |
| 1552 { | |
| 1553 throw wxSQLite3Exception(rc, wxERRMSG_BIND_INT64); | |
| 1554 } | |
| 1555 } | |
| 1556 | |
| 1557 void wxSQLite3Statement::Bind(int paramIndex, double doubleValue) | |
| 1558 { | |
| 1559 CheckStmt(); | |
| 1560 int rc = sqlite3_bind_double((sqlite3_stmt*) m_stmt, paramIndex, doubleValue); | |
| 1561 | |
| 1562 if (rc != SQLITE_OK) | |
| 1563 { | |
| 1564 throw wxSQLite3Exception(rc, wxERRMSG_BIND_DBL); | |
| 1565 } | |
| 1566 } | |
| 1567 | |
| 1568 void wxSQLite3Statement::Bind(int paramIndex, const char* charValue) | |
| 1569 { | |
| 1570 CheckStmt(); | |
| 1571 int rc = sqlite3_bind_text((sqlite3_stmt*) m_stmt, paramIndex, charValue, -1, SQLITE_TRANSIENT); | |
| 1572 | |
| 1573 if (rc != SQLITE_OK) | |
| 1574 { | |
| 1575 throw wxSQLite3Exception(rc, wxERRMSG_BIND_STR); | |
| 1576 } | |
| 1577 } | |
| 1578 | |
| 1579 void wxSQLite3Statement::Bind(int paramIndex, const unsigned char* blobValue, int blobLen) | |
| 1580 { | |
| 1581 CheckStmt(); | |
| 1582 int rc = sqlite3_bind_blob((sqlite3_stmt*) m_stmt, paramIndex, | |
| 1583 (const void*)blobValue, blobLen, SQLITE_TRANSIENT); | |
| 1584 | |
| 1585 if (rc != SQLITE_OK) | |
| 1586 { | |
| 1587 throw wxSQLite3Exception(rc, wxERRMSG_BIND_BLOB); | |
| 1588 } | |
| 1589 } | |
| 1590 | |
| 1591 void wxSQLite3Statement::Bind(int paramIndex, const wxMemoryBuffer& blobValue) | |
| 1592 { | |
| 1593 CheckStmt(); | |
| 1594 int blobLen = (int) blobValue.GetDataLen(); | |
| 1595 int rc = sqlite3_bind_blob((sqlite3_stmt*) m_stmt, paramIndex, | |
| 1596 (const void*)blobValue.GetData(), blobLen, SQLITE_TRANSIENT); | |
| 1597 | |
| 1598 if (rc != SQLITE_OK) | |
| 1599 { | |
| 1600 throw wxSQLite3Exception(rc, wxERRMSG_BIND_BLOB); | |
| 1601 } | |
| 1602 } | |
| 1603 | |
| 1604 void wxSQLite3Statement::BindDate(int paramIndex, const wxDateTime& date) | |
| 1605 { | |
| 1606 if (date.IsValid()) | |
| 1607 { | |
| 1608 Bind(paramIndex,date.FormatISODate()); | |
| 1609 } | |
| 1610 else | |
| 1611 { | |
| 1612 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1613 } | |
| 1614 } | |
| 1615 | |
| 1616 void wxSQLite3Statement::BindTime(int paramIndex, const wxDateTime& time) | |
| 1617 { | |
| 1618 if (time.IsValid()) | |
| 1619 { | |
| 1620 Bind(paramIndex,time.FormatISOTime()); | |
| 1621 } | |
| 1622 else | |
| 1623 { | |
| 1624 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1625 } | |
| 1626 } | |
| 1627 | |
| 1628 void wxSQLite3Statement::BindDateTime(int paramIndex, const wxDateTime& datetime) | |
| 1629 { | |
| 1630 if (datetime.IsValid()) | |
| 1631 { | |
| 1632 Bind(paramIndex,datetime.Format(wxT("%Y-%m-%d %H:%M:%S"))); | |
| 1633 } | |
| 1634 else | |
| 1635 { | |
| 1636 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1637 } | |
| 1638 } | |
| 1639 | |
| 1640 void wxSQLite3Statement::BindTimestamp(int paramIndex, const wxDateTime& timestamp) | |
| 1641 { | |
| 1642 if (timestamp.IsValid()) | |
| 1643 { | |
| 1644 Bind(paramIndex,timestamp.Format(wxT("%Y-%m-%d %H:%M:%S.%l"))); | |
| 1645 } | |
| 1646 else | |
| 1647 { | |
| 1648 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1649 } | |
| 1650 } | |
| 1651 | |
| 1652 void wxSQLite3Statement::BindNumericDateTime(int paramIndex, const wxDateTime& datetime) | |
| 1653 { | |
| 1654 if (datetime.IsValid()) | |
| 1655 { | |
| 1656 Bind(paramIndex, datetime.GetValue()); | |
| 1657 } | |
| 1658 else | |
| 1659 { | |
| 1660 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1661 } | |
| 1662 } | |
| 1663 | |
| 1664 void wxSQLite3Statement::BindJulianDayNumber(int paramIndex, const wxDateTime& datetime) | |
| 1665 { | |
| 1666 if (datetime.IsValid()) | |
| 1667 { | |
| 1668 Bind(paramIndex, datetime.GetJulianDayNumber()); | |
| 1669 } | |
| 1670 else | |
| 1671 { | |
| 1672 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_BIND_DATETIME); | |
| 1673 } | |
| 1674 } | |
| 1675 | |
| 1676 void wxSQLite3Statement::BindBool(int paramIndex, bool value) | |
| 1677 { | |
| 1678 Bind(paramIndex, value ? 1 : 0); | |
| 1679 } | |
| 1680 | |
| 1681 void wxSQLite3Statement::BindNull(int paramIndex) | |
| 1682 { | |
| 1683 CheckStmt(); | |
| 1684 int rc = sqlite3_bind_null((sqlite3_stmt*) m_stmt, paramIndex); | |
| 1685 | |
| 1686 if (rc != SQLITE_OK) | |
| 1687 { | |
| 1688 throw wxSQLite3Exception(rc, wxERRMSG_BIND_NULL); | |
| 1689 } | |
| 1690 } | |
| 1691 | |
| 1692 void wxSQLite3Statement::BindZeroBlob(int paramIndex, int blobSize) | |
| 1693 { | |
| 1694 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 1695 CheckStmt(); | |
| 1696 int rc = sqlite3_bind_zeroblob((sqlite3_stmt*) m_stmt, paramIndex, blobSize); | |
| 1697 if (rc != SQLITE_OK) | |
| 1698 { | |
| 1699 throw wxSQLite3Exception(rc, wxERRMSG_BIND_ZEROBLOB); | |
| 1700 } | |
| 1701 #else | |
| 1702 wxUnusedVar(paramIndex); | |
| 1703 wxUnusedVar(blobSize); | |
| 1704 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 1705 #endif | |
| 1706 } | |
| 1707 | |
| 1708 void wxSQLite3Statement::ClearBindings() | |
| 1709 { | |
| 1710 CheckStmt(); | |
| 1711 #if 0 // missing in SQLite DLL | |
| 1712 int rc = sqlite3_clear_bindings((sqlite3_stmt*) m_stmt); | |
| 1713 | |
| 1714 if (rc != SQLITE_OK) | |
| 1715 { | |
| 1716 throw wxSQLite3Exception(rc, wxERRMSG_BIND_CLEAR); | |
| 1717 } | |
| 1718 #else | |
| 1719 for (int paramIndex = 1; paramIndex <= GetParamCount(); paramIndex++) | |
| 1720 { | |
| 1721 BindNull(paramIndex); | |
| 1722 } | |
| 1723 #endif | |
| 1724 } | |
| 1725 | |
| 1726 wxString wxSQLite3Statement::GetSQL() | |
| 1727 { | |
| 1728 wxString sqlString = wxEmptyString; | |
| 1729 #if SQLITE_VERSION_NUMBER >= 3005003 | |
| 1730 CheckStmt(); | |
| 1731 const char* sqlLocal = sqlite3_sql((sqlite3_stmt*) m_stmt); | |
| 1732 if (sqlLocal != NULL) sqlString = wxString::FromUTF8(sqlLocal); | |
| 1733 #endif | |
| 1734 return sqlString; | |
| 1735 } | |
| 1736 | |
| 1737 void wxSQLite3Statement::Reset() | |
| 1738 { | |
| 1739 if (m_stmt) | |
| 1740 { | |
| 1741 int rc = sqlite3_reset((sqlite3_stmt*) m_stmt); | |
| 1742 | |
| 1743 if (rc != SQLITE_OK) | |
| 1744 { | |
| 1745 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1746 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1747 } | |
| 1748 } | |
| 1749 } | |
| 1750 | |
| 1751 bool wxSQLite3Statement::IsReadOnly() | |
| 1752 { | |
| 1753 #if SQLITE_VERSION_NUMBER >= 3007004 | |
| 1754 CheckStmt(); | |
| 1755 return sqlite3_stmt_readonly((sqlite3_stmt*) m_stmt) != 0; | |
| 1756 #else | |
| 1757 return false; | |
| 1758 #endif | |
| 1759 } | |
| 1760 | |
| 1761 void wxSQLite3Statement::Finalize() | |
| 1762 { | |
| 1763 if (m_stmt && m_hasOwnership) | |
| 1764 { | |
| 1765 int rc = sqlite3_finalize((sqlite3_stmt*) m_stmt); | |
| 1766 m_stmt = 0; | |
| 1767 m_hasOwnership = false; | |
| 1768 | |
| 1769 if (rc != SQLITE_OK) | |
| 1770 { | |
| 1771 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1772 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1773 } | |
| 1774 } | |
| 1775 } | |
| 1776 | |
| 1777 bool wxSQLite3Statement::IsOk() | |
| 1778 { | |
| 1779 return (m_db != 0) && (m_stmt != 0); | |
| 1780 } | |
| 1781 | |
| 1782 void wxSQLite3Statement::CheckDatabase() | |
| 1783 { | |
| 1784 if (m_db == 0) | |
| 1785 { | |
| 1786 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NODB); | |
| 1787 } | |
| 1788 } | |
| 1789 | |
| 1790 void wxSQLite3Statement::CheckStmt() | |
| 1791 { | |
| 1792 if (m_stmt == 0) | |
| 1793 { | |
| 1794 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOSTMT); | |
| 1795 } | |
| 1796 } | |
| 1797 | |
| 1798 // | |
| 1799 | |
| 1800 wxSQLite3Blob::wxSQLite3Blob() | |
| 1801 { | |
| 1802 m_db = NULL; | |
| 1803 m_blob = NULL; | |
| 1804 m_ok = false; | |
| 1805 m_writable = false; | |
| 1806 } | |
| 1807 | |
| 1808 wxSQLite3Blob::wxSQLite3Blob(const wxSQLite3Blob& blob) | |
| 1809 { | |
| 1810 m_db = blob.m_db; | |
| 1811 m_blob = blob.m_blob; | |
| 1812 m_ok = blob.m_ok; | |
| 1813 m_writable = blob.m_writable; | |
| 1814 } | |
| 1815 | |
| 1816 wxSQLite3Blob& wxSQLite3Blob::operator=(const wxSQLite3Blob& blob) | |
| 1817 { | |
| 1818 if (this != &blob) | |
| 1819 { | |
| 1820 try | |
| 1821 { | |
| 1822 Finalize(); | |
| 1823 } | |
| 1824 catch (...) | |
| 1825 { | |
| 1826 } | |
| 1827 m_db = blob.m_db; | |
| 1828 m_blob = blob.m_blob; | |
| 1829 m_ok = blob.m_ok; | |
| 1830 m_writable = blob.m_writable; | |
| 1831 // only one blob can own the blob handle | |
| 1832 const_cast<wxSQLite3Blob&>(blob).m_ok = false; | |
| 1833 } | |
| 1834 return *this; | |
| 1835 } | |
| 1836 | |
| 1837 wxSQLite3Blob::wxSQLite3Blob(void* db, void* blobHandle, bool writable) | |
| 1838 { | |
| 1839 m_db = db; | |
| 1840 m_blob = blobHandle; | |
| 1841 m_ok = true; | |
| 1842 m_writable = writable; | |
| 1843 } | |
| 1844 | |
| 1845 wxSQLite3Blob::~wxSQLite3Blob() | |
| 1846 { | |
| 1847 try | |
| 1848 { | |
| 1849 Finalize(); | |
| 1850 } | |
| 1851 catch (...) | |
| 1852 { | |
| 1853 } | |
| 1854 } | |
| 1855 | |
| 1856 wxMemoryBuffer& wxSQLite3Blob::Read(wxMemoryBuffer& blobValue, int length, int offset) | |
| 1857 { | |
| 1858 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 1859 CheckBlob(); | |
| 1860 char* localBuffer = (char*) blobValue.GetAppendBuf((size_t) length); | |
| 1861 int rc = sqlite3_blob_read((sqlite3_blob*) m_blob, localBuffer, length, offset); | |
| 1862 | |
| 1863 if (rc != SQLITE_OK) | |
| 1864 { | |
| 1865 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1866 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1867 } | |
| 1868 | |
| 1869 blobValue.UngetAppendBuf((size_t) length); | |
| 1870 #else | |
| 1871 wxUnusedVar(blobValue); | |
| 1872 wxUnusedVar(length); | |
| 1873 wxUnusedVar(offset); | |
| 1874 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 1875 #endif | |
| 1876 return blobValue; | |
| 1877 } | |
| 1878 | |
| 1879 void wxSQLite3Blob::Write(const wxMemoryBuffer& blobValue, int offset) | |
| 1880 { | |
| 1881 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 1882 CheckBlob(); | |
| 1883 if (m_writable) | |
| 1884 { | |
| 1885 int blobLen = (int) blobValue.GetDataLen(); | |
| 1886 int rc = sqlite3_blob_write((sqlite3_blob*) m_blob, | |
| 1887 (const void*) blobValue.GetData(), blobLen, offset); | |
| 1888 | |
| 1889 if (rc != SQLITE_OK) | |
| 1890 { | |
| 1891 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1892 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1893 } | |
| 1894 } | |
| 1895 else | |
| 1896 { | |
| 1897 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_BLOB); | |
| 1898 } | |
| 1899 #else | |
| 1900 wxUnusedVar(blobValue); | |
| 1901 wxUnusedVar(offset); | |
| 1902 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 1903 #endif | |
| 1904 } | |
| 1905 | |
| 1906 bool wxSQLite3Blob::IsOk() | |
| 1907 { | |
| 1908 return m_ok; | |
| 1909 } | |
| 1910 | |
| 1911 bool wxSQLite3Blob::IsReadOnly() | |
| 1912 { | |
| 1913 return !m_writable; | |
| 1914 } | |
| 1915 | |
| 1916 int wxSQLite3Blob::GetSize() | |
| 1917 { | |
| 1918 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 1919 CheckBlob(); | |
| 1920 return sqlite3_blob_bytes((sqlite3_blob*) m_blob); | |
| 1921 #else | |
| 1922 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 1923 return 0; | |
| 1924 #endif | |
| 1925 } | |
| 1926 | |
| 1927 void wxSQLite3Blob::Rebind(wxLongLong rowid) | |
| 1928 { | |
| 1929 #if SQLITE_VERSION_NUMBER >= 3007004 | |
| 1930 CheckBlob(); | |
| 1931 int rc = sqlite3_blob_reopen((sqlite3_blob*) m_blob, rowid.GetValue()); | |
| 1932 if (rc != SQLITE_OK) | |
| 1933 { | |
| 1934 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1935 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1936 } | |
| 1937 #else | |
| 1938 wxUnusedVar(rowid); | |
| 1939 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOBLOBREBIND); | |
| 1940 #endif | |
| 1941 } | |
| 1942 | |
| 1943 void wxSQLite3Blob::Finalize() | |
| 1944 { | |
| 1945 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 1946 if (m_ok) | |
| 1947 { | |
| 1948 int rc = sqlite3_blob_close((sqlite3_blob*) m_blob); | |
| 1949 m_blob = NULL; | |
| 1950 m_ok = false; | |
| 1951 if (rc != SQLITE_OK) | |
| 1952 { | |
| 1953 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 1954 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 1955 } | |
| 1956 } | |
| 1957 #else | |
| 1958 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 1959 #endif | |
| 1960 } | |
| 1961 | |
| 1962 void wxSQLite3Blob::CheckBlob() | |
| 1963 { | |
| 1964 if (!m_ok) | |
| 1965 { | |
| 1966 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_BLOB); | |
| 1967 } | |
| 1968 } | |
| 1969 | |
| 1970 // ---------------------------------------------------------------------------- | |
| 1971 // wxSQLite3Database: class holding a SQLite3 database object | |
| 1972 // ---------------------------------------------------------------------------- | |
| 1973 | |
| 1974 bool wxSQLite3Database::ms_sharedCacheEnabled = false; | |
| 1975 | |
| 1976 void | |
| 1977 wxSQLite3Database::SetSharedCache(bool enable) | |
| 1978 { | |
| 1979 int flag = (enable) ? 1 : 0; | |
| 1980 int rc = sqlite3_enable_shared_cache(flag); | |
| 1981 if (rc != SQLITE_OK) | |
| 1982 { | |
| 1983 throw wxSQLite3Exception(rc, wxERRMSG_SHARED_CACHE); | |
| 1984 } | |
| 1985 ms_sharedCacheEnabled = enable; | |
| 1986 } | |
| 1987 | |
| 1988 #if WXSQLITE3_HAVE_CODEC | |
| 1989 bool wxSQLite3Database::ms_hasEncryptionSupport = true; | |
| 1990 #else | |
| 1991 bool wxSQLite3Database::ms_hasEncryptionSupport = false; | |
| 1992 #endif | |
| 1993 | |
| 1994 #if WXSQLITE3_HAVE_METADATA | |
| 1995 bool wxSQLite3Database::ms_hasMetaDataSupport = true; | |
| 1996 #else | |
| 1997 bool wxSQLite3Database::ms_hasMetaDataSupport = false; | |
| 1998 #endif | |
| 1999 | |
| 2000 #if WXSQLITE3_HAVE_LOAD_EXTENSION | |
| 2001 bool wxSQLite3Database::ms_hasLoadExtSupport = true; | |
| 2002 #else | |
| 2003 bool wxSQLite3Database::ms_hasLoadExtSupport = false; | |
| 2004 #endif | |
| 2005 | |
| 2006 #if WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 2007 bool wxSQLite3Database::ms_hasNamedCollectionSupport = true; | |
| 2008 #else | |
| 2009 bool wxSQLite3Database::ms_hasNamedCollectionSupport = false; | |
| 2010 #endif | |
| 2011 | |
| 2012 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 2013 bool wxSQLite3Database::ms_hasIncrementalBlobSupport = true; | |
| 2014 #else | |
| 2015 bool wxSQLite3Database::ms_hasIncrementalBlobSupport = false; | |
| 2016 #endif | |
| 2017 | |
| 2018 #if SQLITE_VERSION_NUMBER >= 3006008 | |
| 2019 bool wxSQLite3Database::ms_hasSavepointSupport = true; | |
| 2020 #else | |
| 2021 bool wxSQLite3Database::ms_hasSavepointSupport = false; | |
| 2022 #endif | |
| 2023 | |
| 2024 #if SQLITE_VERSION_NUMBER >= 3006011 | |
| 2025 bool wxSQLite3Database::ms_hasBackupSupport = true; | |
| 2026 #else | |
| 2027 bool wxSQLite3Database::ms_hasBackupSupport = false; | |
| 2028 #endif | |
| 2029 | |
| 2030 #if SQLITE_VERSION_NUMBER >= 3007000 | |
| 2031 bool wxSQLite3Database::ms_hasWriteAheadLogSupport = true; | |
| 2032 #else | |
| 2033 bool wxSQLite3Database::ms_hasWriteAheadLogSupport = false; | |
| 2034 #endif | |
| 2035 | |
| 2036 bool | |
| 2037 wxSQLite3Database::HasEncryptionSupport() | |
| 2038 { | |
| 2039 return ms_hasEncryptionSupport; | |
| 2040 } | |
| 2041 | |
| 2042 bool | |
| 2043 wxSQLite3Database::HasMetaDataSupport() | |
| 2044 { | |
| 2045 return ms_hasMetaDataSupport; | |
| 2046 } | |
| 2047 | |
| 2048 bool | |
| 2049 wxSQLite3Database::HasLoadExtSupport() | |
| 2050 { | |
| 2051 return ms_hasLoadExtSupport; | |
| 2052 } | |
| 2053 | |
| 2054 bool | |
| 2055 wxSQLite3Database::HasNamedCollectionSupport() | |
| 2056 { | |
| 2057 return ms_hasNamedCollectionSupport; | |
| 2058 } | |
| 2059 | |
| 2060 bool | |
| 2061 wxSQLite3Database::HasIncrementalBlobSupport() | |
| 2062 { | |
| 2063 return ms_hasIncrementalBlobSupport; | |
| 2064 } | |
| 2065 | |
| 2066 bool | |
| 2067 wxSQLite3Database::HasSavepointSupport() | |
| 2068 { | |
| 2069 return ms_hasSavepointSupport; | |
| 2070 } | |
| 2071 | |
| 2072 bool | |
| 2073 wxSQLite3Database::HasBackupSupport() | |
| 2074 { | |
| 2075 return ms_hasBackupSupport; | |
| 2076 } | |
| 2077 | |
| 2078 bool | |
| 2079 wxSQLite3Database::HasWriteAheadLogSupport() | |
| 2080 { | |
| 2081 return ms_hasWriteAheadLogSupport; | |
| 2082 } | |
| 2083 | |
| 2084 wxSQLite3Database::wxSQLite3Database() | |
| 2085 { | |
| 2086 m_db = 0; | |
| 2087 m_busyTimeoutMs = 60000; // 60 seconds | |
| 2088 m_isEncrypted = false; | |
| 2089 } | |
| 2090 | |
| 2091 wxSQLite3Database::wxSQLite3Database(const wxSQLite3Database& db) | |
| 2092 { | |
| 2093 m_db = db.m_db; | |
| 2094 m_busyTimeoutMs = 60000; // 60 seconds | |
| 2095 m_isEncrypted = false; | |
| 2096 } | |
| 2097 | |
| 2098 wxSQLite3Database::~wxSQLite3Database() | |
| 2099 { | |
| 2100 Close(); | |
| 2101 } | |
| 2102 | |
| 2103 wxSQLite3Database& wxSQLite3Database::operator=(const wxSQLite3Database& db) | |
| 2104 { | |
| 2105 if (this != &db) | |
| 2106 { | |
| 2107 if (m_db == 0) | |
| 2108 { | |
| 2109 m_db = db.m_db; | |
| 2110 m_busyTimeoutMs = 60000; // 60 seconds | |
| 2111 m_isEncrypted = db.m_isEncrypted; | |
| 2112 } | |
| 2113 else | |
| 2114 { | |
| 2115 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_DBASSIGN_FAILED); | |
| 2116 } | |
| 2117 } | |
| 2118 return *this; | |
| 2119 } | |
| 2120 | |
| 2121 void wxSQLite3Database::Open(const wxString& fileName, const wxString& key, int flags) | |
| 2122 { | |
| 2123 wxCharBuffer strLocalKey = key.ToUTF8(); | |
| 2124 const char* localKey = strLocalKey; | |
| 2125 wxMemoryBuffer binaryKey; | |
| 2126 if (key.Length() > 0) | |
| 2127 { | |
| 2128 binaryKey.AppendData((void*) localKey, strlen(localKey)); | |
| 2129 } | |
| 2130 Open(fileName, binaryKey, flags); | |
| 2131 } | |
| 2132 | |
| 2133 void wxSQLite3Database::Open(const wxString& fileName, const wxMemoryBuffer& key, int flags) | |
| 2134 { | |
| 2135 wxCharBuffer strFileName = fileName.ToUTF8(); | |
| 2136 const char* localFileName = strFileName; | |
| 2137 | |
| 2138 int rc = sqlite3_open_v2((const char*) localFileName, (sqlite3**) &m_db, flags, NULL); | |
| 2139 | |
| 2140 if (rc != SQLITE_OK) | |
| 2141 { | |
| 2142 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2143 Close(); | |
| 2144 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2145 } | |
| 2146 | |
| 2147 rc = sqlite3_extended_result_codes((sqlite3*) m_db, 1); | |
| 2148 if (rc != SQLITE_OK) | |
| 2149 { | |
| 2150 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2151 Close(); | |
| 2152 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2153 } | |
| 2154 | |
| 2155 #if WXSQLITE3_HAVE_CODEC | |
| 2156 if (key.GetDataLen() > 0) | |
| 2157 { | |
| 2158 rc = sqlite3_key((sqlite3*) m_db, key.GetData(), (int) key.GetDataLen()); | |
| 2159 if (rc != SQLITE_OK) | |
| 2160 { | |
| 2161 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2162 Close(); | |
| 2163 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2164 } | |
| 2165 m_isEncrypted = true; | |
| 2166 } | |
| 2167 #else | |
| 2168 wxUnusedVar(key); | |
| 2169 #endif | |
| 2170 | |
| 2171 SetBusyTimeout(m_busyTimeoutMs); | |
| 2172 } | |
| 2173 | |
| 2174 bool wxSQLite3Database::IsOpen() const | |
| 2175 { | |
| 2176 return (m_db != NULL); | |
| 2177 } | |
| 2178 | |
| 2179 void wxSQLite3Database::Close() | |
| 2180 { | |
| 2181 if (m_db) | |
| 2182 { | |
| 2183 #if SQLITE_VERSION_NUMBER >= 3006000 | |
| 2184 // Unfortunately the following code leads to a crash if the RTree module is used | |
| 2185 // therefore it is disabled for now | |
| 2186 #if 0 | |
| 2187 // Finalize all unfinalized prepared statements | |
| 2188 sqlite3_stmt *pStmt; | |
| 2189 while( (pStmt = sqlite3_next_stmt((sqlite3*) m_db, 0))!=0 ) | |
| 2190 { | |
| 2191 sqlite3_finalize(pStmt); | |
| 2192 } | |
| 2193 #endif | |
| 2194 #endif | |
| 2195 sqlite3_close((sqlite3*) m_db); | |
| 2196 m_db = 0; | |
| 2197 m_isEncrypted = false; | |
| 2198 } | |
| 2199 } | |
| 2200 | |
| 2201 void wxSQLite3Database::Backup(const wxString& targetFileName, const wxString& key, const wxString& sourceDatabaseName) | |
| 2202 { | |
| 2203 wxCharBuffer strLocalKey = key.ToUTF8(); | |
| 2204 const char* localKey = strLocalKey; | |
| 2205 wxMemoryBuffer binaryKey; | |
| 2206 if (key.Length() > 0) | |
| 2207 { | |
| 2208 binaryKey.AppendData((void*) localKey, strlen(localKey)); | |
| 2209 } | |
| 2210 Backup(targetFileName, binaryKey, sourceDatabaseName); | |
| 2211 } | |
| 2212 | |
| 2213 void wxSQLite3Database::Backup(const wxString& targetFileName, const wxMemoryBuffer& key, const wxString& sourceDatabaseName) | |
| 2214 { | |
| 2215 #if SQLITE_VERSION_NUMBER >= 3006011 | |
| 2216 CheckDatabase(); | |
| 2217 | |
| 2218 wxCharBuffer strFileName = targetFileName.ToUTF8(); | |
| 2219 const char* localTargetFileName = strFileName; | |
| 2220 wxCharBuffer strDatabaseName = sourceDatabaseName.ToUTF8(); | |
| 2221 const char* localSourceDatabaseName = strDatabaseName; | |
| 2222 | |
| 2223 sqlite3* pDest; | |
| 2224 sqlite3_backup* pBackup; | |
| 2225 int rc; | |
| 2226 rc = sqlite3_open(localTargetFileName, &pDest); | |
| 2227 if (rc != SQLITE_OK) | |
| 2228 { | |
| 2229 sqlite3_close(pDest); | |
| 2230 throw wxSQLite3Exception(rc, wxERRMSG_DBOPEN_FAILED); | |
| 2231 } | |
| 2232 #if WXSQLITE3_HAVE_CODEC | |
| 2233 if (key.GetDataLen() > 0) | |
| 2234 { | |
| 2235 rc = sqlite3_key(pDest, key.GetData(), (int) key.GetDataLen()); | |
| 2236 if (rc != SQLITE_OK) | |
| 2237 { | |
| 2238 const char* localError = sqlite3_errmsg((sqlite3*) pDest); | |
| 2239 sqlite3_close(pDest); | |
| 2240 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2241 } | |
| 2242 } | |
| 2243 #else | |
| 2244 wxUnusedVar(key); | |
| 2245 #endif | |
| 2246 | |
| 2247 pBackup = sqlite3_backup_init(pDest, "main", (sqlite3*) m_db, localSourceDatabaseName); | |
| 2248 if (pBackup == 0) | |
| 2249 { | |
| 2250 const char* localError = sqlite3_errmsg(pDest); | |
| 2251 sqlite3_close(pDest); | |
| 2252 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2253 } | |
| 2254 | |
| 2255 do | |
| 2256 { | |
| 2257 rc = sqlite3_backup_step(pBackup, 10); | |
| 2258 #if 0 | |
| 2259 xProgress(sqlite3_backup_remaining(pBackup), | |
| 2260 sqlite3_backup_pagecount(pBackup)); | |
| 2261 #endif | |
| 2262 if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) | |
| 2263 { | |
| 2264 sqlite3_sleep(250); | |
| 2265 } | |
| 2266 } | |
| 2267 while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); | |
| 2268 | |
| 2269 sqlite3_backup_finish(pBackup); | |
| 2270 if (rc == SQLITE_DONE) | |
| 2271 { | |
| 2272 sqlite3_close(pDest); | |
| 2273 } | |
| 2274 else | |
| 2275 { | |
| 2276 const char* localError = sqlite3_errmsg(pDest); | |
| 2277 sqlite3_close(pDest); | |
| 2278 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2279 } | |
| 2280 #else | |
| 2281 wxUnusedVar(targetFileName); | |
| 2282 wxUnusedVar(sourceDatabaseName); | |
| 2283 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOBACKUP); | |
| 2284 #endif | |
| 2285 } | |
| 2286 | |
| 2287 void wxSQLite3Database::Restore(const wxString& sourceFileName, const wxString& key, const wxString& targetDatabaseName) | |
| 2288 { | |
| 2289 wxCharBuffer strLocalKey = key.ToUTF8(); | |
| 2290 const char* localKey = strLocalKey; | |
| 2291 wxMemoryBuffer binaryKey; | |
| 2292 if (key.Length() > 0) | |
| 2293 { | |
| 2294 binaryKey.AppendData((void*) localKey, strlen(localKey)); | |
| 2295 } | |
| 2296 Restore(sourceFileName, binaryKey, targetDatabaseName); | |
| 2297 } | |
| 2298 | |
| 2299 void wxSQLite3Database::Restore(const wxString& sourceFileName, const wxMemoryBuffer& key, const wxString& targetDatabaseName) | |
| 2300 { | |
| 2301 #if SQLITE_VERSION_NUMBER >= 3006011 | |
| 2302 CheckDatabase(); | |
| 2303 | |
| 2304 wxCharBuffer strFileName = sourceFileName.ToUTF8(); | |
| 2305 const char* localSourceFileName = strFileName; | |
| 2306 wxCharBuffer strDatabaseName = targetDatabaseName.ToUTF8(); | |
| 2307 const char* localTargetDatabaseName = strDatabaseName; | |
| 2308 | |
| 2309 sqlite3* pSrc; | |
| 2310 sqlite3_backup* pBackup; | |
| 2311 int rc; | |
| 2312 int nTimeout = 0; | |
| 2313 | |
| 2314 rc = sqlite3_open(localSourceFileName, &pSrc); | |
| 2315 if (rc != SQLITE_OK) | |
| 2316 { | |
| 2317 sqlite3_close(pSrc); | |
| 2318 throw wxSQLite3Exception(rc, wxERRMSG_DBOPEN_FAILED); | |
| 2319 } | |
| 2320 #if WXSQLITE3_HAVE_CODEC | |
| 2321 if (key.GetDataLen() > 0) | |
| 2322 { | |
| 2323 rc = sqlite3_key(pSrc, key.GetData(), (int) key.GetDataLen()); | |
| 2324 if (rc != SQLITE_OK) | |
| 2325 { | |
| 2326 const char* localError = sqlite3_errmsg((sqlite3*) pSrc); | |
| 2327 sqlite3_close(pSrc); | |
| 2328 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2329 } | |
| 2330 } | |
| 2331 #else | |
| 2332 wxUnusedVar(key); | |
| 2333 #endif | |
| 2334 | |
| 2335 pBackup = sqlite3_backup_init((sqlite3*) m_db, localTargetDatabaseName, pSrc, "main"); | |
| 2336 if (pBackup == 0) | |
| 2337 { | |
| 2338 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2339 sqlite3_close(pSrc); | |
| 2340 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2341 } | |
| 2342 while ((rc = sqlite3_backup_step(pBackup, 100)) == SQLITE_OK || rc == SQLITE_BUSY) | |
| 2343 { | |
| 2344 if (rc == SQLITE_BUSY) | |
| 2345 { | |
| 2346 if (nTimeout++ >= 3) break; | |
| 2347 sqlite3_sleep(100); | |
| 2348 } | |
| 2349 } | |
| 2350 sqlite3_backup_finish(pBackup); | |
| 2351 if (rc == SQLITE_DONE) | |
| 2352 { | |
| 2353 sqlite3_close(pSrc); | |
| 2354 } | |
| 2355 else if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) | |
| 2356 { | |
| 2357 sqlite3_close(pSrc); | |
| 2358 throw wxSQLite3Exception(rc, wxERRMSG_SOURCEDB_BUSY); | |
| 2359 } | |
| 2360 else | |
| 2361 { | |
| 2362 const char* localError = sqlite3_errmsg(pSrc); | |
| 2363 sqlite3_close(pSrc); | |
| 2364 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2365 } | |
| 2366 #else | |
| 2367 wxUnusedVar(sourceFileName); | |
| 2368 wxUnusedVar(targetDatabaseName); | |
| 2369 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOBACKUP); | |
| 2370 #endif | |
| 2371 } | |
| 2372 | |
| 2373 void wxSQLite3Database::Begin(wxSQLite3TransactionType transactionType) | |
| 2374 { | |
| 2375 wxString sql; | |
| 2376 switch (transactionType) | |
| 2377 { | |
| 2378 case WXSQLITE_TRANSACTION_DEFERRED: | |
| 2379 sql << wxT("begin deferred transaction"); | |
| 2380 break; | |
| 2381 case WXSQLITE_TRANSACTION_IMMEDIATE: | |
| 2382 sql << wxT("begin immediate transaction"); | |
| 2383 break; | |
| 2384 case WXSQLITE_TRANSACTION_EXCLUSIVE: | |
| 2385 sql << wxT("begin exclusive transaction"); | |
| 2386 break; | |
| 2387 default: | |
| 2388 sql << wxT("begin transaction"); | |
| 2389 break; | |
| 2390 } | |
| 2391 ExecuteUpdate(sql); | |
| 2392 } | |
| 2393 | |
| 2394 void wxSQLite3Database::Commit() | |
| 2395 { | |
| 2396 ExecuteUpdate("commit transaction"); | |
| 2397 } | |
| 2398 | |
| 2399 void wxSQLite3Database::Rollback(const wxString& savepointName) | |
| 2400 { | |
| 2401 #if SQLITE_VERSION_NUMBER >= 3006008 | |
| 2402 if (savepointName.IsEmpty()) | |
| 2403 { | |
| 2404 #endif | |
| 2405 ExecuteUpdate("rollback transaction"); | |
| 2406 #if SQLITE_VERSION_NUMBER >= 3006008 | |
| 2407 } | |
| 2408 else | |
| 2409 { | |
| 2410 ExecuteUpdate(wxString(wxT("rollback transaction to savepoint "))+savepointName); | |
| 2411 } | |
| 2412 #endif | |
| 2413 } | |
| 2414 | |
| 2415 bool wxSQLite3Database::GetAutoCommit() | |
| 2416 { | |
| 2417 CheckDatabase(); | |
| 2418 return sqlite3_get_autocommit((sqlite3*) m_db) != 0; | |
| 2419 } | |
| 2420 | |
| 2421 void wxSQLite3Database::Savepoint(const wxString& savepointName) | |
| 2422 { | |
| 2423 #if SQLITE_VERSION_NUMBER >= 3006008 | |
| 2424 ExecuteUpdate(wxString(wxT("savepoint "))+savepointName); | |
| 2425 #else | |
| 2426 wxUnusedVar(savepointName); | |
| 2427 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOSAVEPOINT); | |
| 2428 #endif | |
| 2429 } | |
| 2430 | |
| 2431 void wxSQLite3Database::ReleaseSavepoint(const wxString& savepointName) | |
| 2432 { | |
| 2433 #if SQLITE_VERSION_NUMBER >= 3006008 | |
| 2434 ExecuteUpdate(wxString(wxT("release savepoint "))+savepointName); | |
| 2435 #else | |
| 2436 wxUnusedVar(savepointName); | |
| 2437 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOSAVEPOINT); | |
| 2438 #endif | |
| 2439 } | |
| 2440 | |
| 2441 wxSQLite3Statement wxSQLite3Database::PrepareStatement(const wxString& sql) | |
| 2442 { | |
| 2443 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2444 const char* localSql = strSql; | |
| 2445 return PrepareStatement(localSql); | |
| 2446 } | |
| 2447 | |
| 2448 wxSQLite3Statement wxSQLite3Database::PrepareStatement(const wxSQLite3StatementBuffer& sql) | |
| 2449 { | |
| 2450 return PrepareStatement((const char*) sql); | |
| 2451 } | |
| 2452 | |
| 2453 wxSQLite3Statement wxSQLite3Database::PrepareStatement(const char* sql) | |
| 2454 { | |
| 2455 CheckDatabase(); | |
| 2456 sqlite3_stmt* stmt = (sqlite3_stmt*) Prepare(sql); | |
| 2457 return wxSQLite3Statement(m_db, stmt); | |
| 2458 } | |
| 2459 | |
| 2460 bool wxSQLite3Database::TableExists(const wxString& tableName, const wxString& databaseName) | |
| 2461 { | |
| 2462 wxString sql; | |
| 2463 if (databaseName.IsEmpty()) | |
| 2464 { | |
| 2465 sql = wxT("select count(*) from sqlite_master where type='table' and name like ?"); | |
| 2466 } | |
| 2467 else | |
| 2468 { | |
| 2469 sql = wxString(wxT("select count(*) from ")) + databaseName + wxString(wxT(".sqlite_master where type='table' and name like ?")); | |
| 2470 } | |
| 2471 wxSQLite3Statement stmt = PrepareStatement(sql); | |
| 2472 stmt.Bind(1, tableName); | |
| 2473 wxSQLite3ResultSet resultSet = stmt.ExecuteQuery(); | |
| 2474 long value = 0; | |
| 2475 resultSet.GetAsString(0).ToLong(&value); | |
| 2476 return (value > 0); | |
| 2477 } | |
| 2478 | |
| 2479 bool wxSQLite3Database::TableExists(const wxString& tableName, wxArrayString& databaseNames) | |
| 2480 { | |
| 2481 wxArrayString databaseList; | |
| 2482 GetDatabaseList(databaseList); | |
| 2483 | |
| 2484 bool found = false; | |
| 2485 size_t count = databaseList.GetCount(); | |
| 2486 if (count > 0) | |
| 2487 { | |
| 2488 size_t j; | |
| 2489 for (j = 0; j < count; j++) | |
| 2490 { | |
| 2491 if (TableExists(tableName, databaseList.Item(j))) | |
| 2492 { | |
| 2493 found = true; | |
| 2494 databaseNames.Add(databaseList.Item(j)); | |
| 2495 } | |
| 2496 } | |
| 2497 } | |
| 2498 return found; | |
| 2499 } | |
| 2500 | |
| 2501 void wxSQLite3Database::GetDatabaseList(wxArrayString& databaseNames) | |
| 2502 { | |
| 2503 databaseNames.Empty(); | |
| 2504 wxSQLite3ResultSet resultSet = ExecuteQuery("PRAGMA database_list;"); | |
| 2505 while (resultSet.NextRow()) | |
| 2506 { | |
| 2507 databaseNames.Add(resultSet.GetString(1)); | |
| 2508 } | |
| 2509 } | |
| 2510 | |
| 2511 void wxSQLite3Database::GetDatabaseList(wxArrayString& databaseNames, wxArrayString& databaseFiles) | |
| 2512 { | |
| 2513 databaseNames.Empty(); | |
| 2514 databaseFiles.Empty(); | |
| 2515 wxSQLite3ResultSet resultSet = ExecuteQuery("PRAGMA database_list;"); | |
| 2516 while (resultSet.NextRow()) | |
| 2517 { | |
| 2518 databaseNames.Add(resultSet.GetString(1)); | |
| 2519 databaseFiles.Add(resultSet.GetString(2)); | |
| 2520 } | |
| 2521 } | |
| 2522 | |
| 2523 bool wxSQLite3Database::EnableForeignKeySupport(bool enable) | |
| 2524 { | |
| 2525 if (enable) | |
| 2526 { | |
| 2527 ExecuteUpdate("PRAGMA foreign_keys=ON;"); | |
| 2528 } | |
| 2529 else | |
| 2530 { | |
| 2531 ExecuteUpdate("PRAGMA foreign_keys=OFF;"); | |
| 2532 } | |
| 2533 bool enabled = IsForeignKeySupportEnabled(); | |
| 2534 return (enable && enabled) || (!enable && !enabled); | |
| 2535 } | |
| 2536 | |
| 2537 bool wxSQLite3Database::IsForeignKeySupportEnabled() | |
| 2538 { | |
| 2539 bool enabled = false; | |
| 2540 wxSQLite3ResultSet resultSet = ExecuteQuery("PRAGMA foreign_keys;"); | |
| 2541 if (resultSet.NextRow()) | |
| 2542 { | |
| 2543 enabled = (resultSet.GetInt(0) == 1); | |
| 2544 } | |
| 2545 return enabled; | |
| 2546 } | |
| 2547 | |
| 2548 wxSQLite3JournalMode | |
| 2549 wxSQLite3Database::SetJournalMode(wxSQLite3JournalMode journalMode, const wxString& database) | |
| 2550 { | |
| 2551 wxString mode = ConvertJournalMode(journalMode); | |
| 2552 wxString query = wxT("PRAGMA "); | |
| 2553 if (!database.IsEmpty()) | |
| 2554 { | |
| 2555 query += database; | |
| 2556 query += wxT("."); | |
| 2557 } | |
| 2558 query += wxT("journal_mode="); | |
| 2559 query += mode; | |
| 2560 query += wxT(";"); | |
| 2561 wxSQLite3ResultSet resultSet = ExecuteQuery(query); | |
| 2562 if (resultSet.NextRow()) | |
| 2563 { | |
| 2564 mode = resultSet.GetString(0); | |
| 2565 } | |
| 2566 return ConvertJournalMode(mode); | |
| 2567 } | |
| 2568 | |
| 2569 wxSQLite3JournalMode | |
| 2570 wxSQLite3Database::GetJournalMode(const wxString& database) | |
| 2571 { | |
| 2572 wxString mode = wxT("DELETE"); | |
| 2573 wxString query = wxT("PRAGMA "); | |
| 2574 if (!database.IsEmpty()) | |
| 2575 { | |
| 2576 query += database; | |
| 2577 query += wxT("."); | |
| 2578 } | |
| 2579 query += wxT("journal_mode;"); | |
| 2580 wxSQLite3ResultSet resultSet = ExecuteQuery(query); | |
| 2581 if (resultSet.NextRow()) | |
| 2582 { | |
| 2583 mode = resultSet.GetString(0); | |
| 2584 } | |
| 2585 return ConvertJournalMode(mode); | |
| 2586 } | |
| 2587 | |
| 2588 /* static */ | |
| 2589 wxString wxSQLite3Database::ConvertJournalMode(wxSQLite3JournalMode mode) | |
| 2590 { | |
| 2591 wxString journalMode; | |
| 2592 if (mode == WXSQLITE_JOURNALMODE_DELETE) journalMode = wxT("DELETE"); | |
| 2593 else if (mode == WXSQLITE_JOURNALMODE_PERSIST) journalMode = wxT("PERSIST"); | |
| 2594 else if (mode == WXSQLITE_JOURNALMODE_OFF) journalMode = wxT("OFF"); | |
| 2595 else if (mode == WXSQLITE_JOURNALMODE_TRUNCATE) journalMode = wxT("TRUNCATE"); | |
| 2596 else if (mode == WXSQLITE_JOURNALMODE_MEMORY) journalMode = wxT("MEMORY"); | |
| 2597 else if (mode == WXSQLITE_JOURNALMODE_WAL) journalMode = wxT("WAL"); | |
| 2598 else journalMode = wxT("DELETE"); | |
| 2599 return journalMode; | |
| 2600 } | |
| 2601 | |
| 2602 /* static */ | |
| 2603 wxSQLite3JournalMode wxSQLite3Database::ConvertJournalMode(const wxString& mode) | |
| 2604 { | |
| 2605 wxSQLite3JournalMode journalMode; | |
| 2606 if (mode.IsSameAs(wxT("DELETE"))) journalMode = WXSQLITE_JOURNALMODE_DELETE; | |
| 2607 else if (mode.IsSameAs(wxT("PERSIST"))) journalMode = WXSQLITE_JOURNALMODE_PERSIST; | |
| 2608 else if (mode.IsSameAs(wxT("OFF"))) journalMode = WXSQLITE_JOURNALMODE_OFF; | |
| 2609 else if (mode.IsSameAs(wxT("TRUNCATE"))) journalMode = WXSQLITE_JOURNALMODE_TRUNCATE; | |
| 2610 else if (mode.IsSameAs(wxT("MEMORY"))) journalMode = WXSQLITE_JOURNALMODE_MEMORY; | |
| 2611 else if (mode.IsSameAs(wxT("WAL"))) journalMode = WXSQLITE_JOURNALMODE_WAL; | |
| 2612 else journalMode = WXSQLITE_JOURNALMODE_DELETE; | |
| 2613 return journalMode; | |
| 2614 } | |
| 2615 | |
| 2616 bool wxSQLite3Database::CheckSyntax(const wxString& sql) | |
| 2617 { | |
| 2618 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2619 const char* localSql = strSql; | |
| 2620 return CheckSyntax(localSql); | |
| 2621 } | |
| 2622 | |
| 2623 bool wxSQLite3Database::CheckSyntax(const wxSQLite3StatementBuffer& sql) | |
| 2624 { | |
| 2625 return CheckSyntax((const char*) sql); | |
| 2626 } | |
| 2627 | |
| 2628 bool wxSQLite3Database::CheckSyntax(const char* sql) | |
| 2629 { | |
| 2630 return sqlite3_complete(sql) != 0; | |
| 2631 } | |
| 2632 | |
| 2633 int wxSQLite3Database::ExecuteUpdate(const wxString& sql) | |
| 2634 { | |
| 2635 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2636 const char* localSql = strSql; | |
| 2637 return ExecuteUpdate(localSql); | |
| 2638 } | |
| 2639 | |
| 2640 int wxSQLite3Database::ExecuteUpdate(const wxSQLite3StatementBuffer& sql) | |
| 2641 { | |
| 2642 return ExecuteUpdate((const char*) sql); | |
| 2643 } | |
| 2644 | |
| 2645 int wxSQLite3Database::ExecuteUpdate(const char* sql) | |
| 2646 { | |
| 2647 CheckDatabase(); | |
| 2648 | |
| 2649 char* localError=0; | |
| 2650 | |
| 2651 int rc = sqlite3_exec((sqlite3*) m_db, sql, 0, 0, &localError); | |
| 2652 | |
| 2653 if (rc == SQLITE_OK) | |
| 2654 { | |
| 2655 return sqlite3_changes((sqlite3*) m_db); | |
| 2656 } | |
| 2657 else | |
| 2658 { | |
| 2659 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2660 } | |
| 2661 } | |
| 2662 | |
| 2663 wxSQLite3ResultSet wxSQLite3Database::ExecuteQuery(const wxString& sql) | |
| 2664 { | |
| 2665 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2666 const char* localSql = strSql; | |
| 2667 return ExecuteQuery(localSql); | |
| 2668 } | |
| 2669 | |
| 2670 wxSQLite3ResultSet wxSQLite3Database::ExecuteQuery(const wxSQLite3StatementBuffer& sql) | |
| 2671 { | |
| 2672 return ExecuteQuery((const char*) sql); | |
| 2673 } | |
| 2674 | |
| 2675 wxSQLite3ResultSet wxSQLite3Database::ExecuteQuery(const char* sql) | |
| 2676 { | |
| 2677 CheckDatabase(); | |
| 2678 | |
| 2679 sqlite3_stmt* stmt = (sqlite3_stmt*) Prepare(sql); | |
| 2680 | |
| 2681 int rc = sqlite3_step(stmt); | |
| 2682 | |
| 2683 if (rc == SQLITE_DONE) // no rows | |
| 2684 { | |
| 2685 return wxSQLite3ResultSet(m_db, stmt, true /* eof */); | |
| 2686 } | |
| 2687 else if (rc == SQLITE_ROW) // one or more rows | |
| 2688 { | |
| 2689 return wxSQLite3ResultSet(m_db, stmt, false /* eof */); | |
| 2690 } | |
| 2691 else | |
| 2692 { | |
| 2693 rc = sqlite3_finalize(stmt); | |
| 2694 const char* localError= sqlite3_errmsg((sqlite3*) m_db); | |
| 2695 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2696 } | |
| 2697 } | |
| 2698 | |
| 2699 int wxSQLite3Database::ExecuteScalar(const wxString& sql) | |
| 2700 { | |
| 2701 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2702 const char* localSql = strSql; | |
| 2703 return ExecuteScalar(localSql); | |
| 2704 } | |
| 2705 | |
| 2706 int wxSQLite3Database::ExecuteScalar(const wxSQLite3StatementBuffer& sql) | |
| 2707 { | |
| 2708 return ExecuteScalar((const char*) sql); | |
| 2709 } | |
| 2710 | |
| 2711 int wxSQLite3Database::ExecuteScalar(const char* sql) | |
| 2712 { | |
| 2713 wxSQLite3ResultSet resultSet = ExecuteQuery(sql); | |
| 2714 | |
| 2715 if (resultSet.Eof() || resultSet.GetColumnCount() < 1) | |
| 2716 { | |
| 2717 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_INVALID_QUERY); | |
| 2718 } | |
| 2719 | |
| 2720 long value = 0; | |
| 2721 resultSet.GetAsString(0).ToLong(&value); | |
| 2722 return (int) value; | |
| 2723 } | |
| 2724 | |
| 2725 wxSQLite3Table wxSQLite3Database::GetTable(const wxString& sql) | |
| 2726 { | |
| 2727 wxCharBuffer strSql = sql.ToUTF8(); | |
| 2728 const char* localSql = strSql; | |
| 2729 return GetTable(localSql); | |
| 2730 } | |
| 2731 | |
| 2732 wxSQLite3Table wxSQLite3Database::GetTable(const wxSQLite3StatementBuffer& sql) | |
| 2733 { | |
| 2734 return GetTable((const char*) sql); | |
| 2735 } | |
| 2736 | |
| 2737 wxSQLite3Table wxSQLite3Database::GetTable(const char* sql) | |
| 2738 { | |
| 2739 CheckDatabase(); | |
| 2740 | |
| 2741 char* localError=0; | |
| 2742 char** results=0; | |
| 2743 int rc; | |
| 2744 int rows(0); | |
| 2745 int cols(0); | |
| 2746 | |
| 2747 rc = sqlite3_get_table((sqlite3*) m_db, sql, &results, &rows, &cols, &localError); | |
| 2748 | |
| 2749 if (rc == SQLITE_OK) | |
| 2750 { | |
| 2751 return wxSQLite3Table(results, rows, cols); | |
| 2752 } | |
| 2753 else | |
| 2754 { | |
| 2755 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2756 } | |
| 2757 } | |
| 2758 | |
| 2759 wxLongLong wxSQLite3Database::GetLastRowId() | |
| 2760 { | |
| 2761 CheckDatabase(); | |
| 2762 return wxLongLong(sqlite3_last_insert_rowid((sqlite3*) m_db)); | |
| 2763 } | |
| 2764 | |
| 2765 wxSQLite3Blob wxSQLite3Database::GetReadOnlyBlob(wxLongLong rowId, | |
| 2766 const wxString& columnName, | |
| 2767 const wxString& tableName, | |
| 2768 const wxString& dbName) | |
| 2769 { | |
| 2770 return GetBlob(rowId, columnName, tableName, dbName, false); | |
| 2771 } | |
| 2772 | |
| 2773 wxSQLite3Blob wxSQLite3Database::GetWritableBlob(wxLongLong rowId, | |
| 2774 const wxString& columnName, | |
| 2775 const wxString& tableName, | |
| 2776 const wxString& dbName) | |
| 2777 { | |
| 2778 return GetBlob(rowId, columnName, tableName, dbName, true); | |
| 2779 } | |
| 2780 | |
| 2781 wxSQLite3Blob wxSQLite3Database::GetBlob(wxLongLong rowId, | |
| 2782 const wxString& columnName, | |
| 2783 const wxString& tableName, | |
| 2784 const wxString& dbName, | |
| 2785 bool writable) | |
| 2786 { | |
| 2787 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 2788 wxCharBuffer strColumnName = columnName.ToUTF8(); | |
| 2789 const char* localColumnName = strColumnName; | |
| 2790 wxCharBuffer strTableName = tableName.ToUTF8(); | |
| 2791 const char* localTableName = strTableName; | |
| 2792 wxCharBuffer strDbName = dbName.ToUTF8(); | |
| 2793 const char* localDbName = (!dbName.IsEmpty()) ? (const char*) strDbName : (const char*) NULL; | |
| 2794 int flags = (writable) ? 1 : 0; | |
| 2795 sqlite3_blob* blobHandle; | |
| 2796 CheckDatabase(); | |
| 2797 int rc = sqlite3_blob_open((sqlite3*) m_db, localDbName, localTableName, localColumnName, rowId.GetValue(), flags, &blobHandle); | |
| 2798 if (rc != SQLITE_OK) | |
| 2799 { | |
| 2800 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2801 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2802 } | |
| 2803 return wxSQLite3Blob(m_db, (void*) blobHandle, writable); | |
| 2804 #else | |
| 2805 wxUnusedVar(rowId); | |
| 2806 wxUnusedVar(columnName); | |
| 2807 wxUnusedVar(tableName); | |
| 2808 wxUnusedVar(dbName); | |
| 2809 wxUnusedVar(writable); | |
| 2810 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOINCBLOB); | |
| 2811 return NULL; | |
| 2812 #endif | |
| 2813 } | |
| 2814 | |
| 2815 void wxSQLite3Database::Interrupt() | |
| 2816 { | |
| 2817 CheckDatabase(); | |
| 2818 sqlite3_interrupt((sqlite3*) m_db); | |
| 2819 } | |
| 2820 | |
| 2821 void wxSQLite3Database::SetBusyTimeout(int nMillisecs) | |
| 2822 { | |
| 2823 CheckDatabase(); | |
| 2824 m_busyTimeoutMs = nMillisecs; | |
| 2825 sqlite3_busy_timeout((sqlite3*) m_db, m_busyTimeoutMs); | |
| 2826 } | |
| 2827 | |
| 2828 wxString wxSQLite3Database::GetVersion() | |
| 2829 { | |
| 2830 return wxString::FromUTF8(sqlite3_libversion()); | |
| 2831 } | |
| 2832 | |
| 2833 wxString wxSQLite3Database::GetSourceId() | |
| 2834 { | |
| 2835 #if SQLITE_VERSION_NUMBER >= 3006018 | |
| 2836 return wxString::FromUTF8(sqlite3_sourceid()); | |
| 2837 #else | |
| 2838 return wxEmptyString; | |
| 2839 #endif | |
| 2840 } | |
| 2841 | |
| 2842 bool wxSQLite3Database::CompileOptionUsed(const wxString& optionName) | |
| 2843 { | |
| 2844 #if SQLITE_VERSION_NUMBER >= 3006023 | |
| 2845 wxCharBuffer strOption = optionName.ToUTF8(); | |
| 2846 const char* localOption = strOption; | |
| 2847 return sqlite3_compileoption_used(localOption) == 1; | |
| 2848 #else | |
| 2849 return false; | |
| 2850 #endif | |
| 2851 } | |
| 2852 | |
| 2853 wxString wxSQLite3Database::GetCompileOptionName(int optionIndex) | |
| 2854 { | |
| 2855 #if SQLITE_VERSION_NUMBER >= 3006023 | |
| 2856 const char* unknownOption = ""; | |
| 2857 const char* optionName = sqlite3_compileoption_get(optionIndex); | |
| 2858 if (optionName == NULL) | |
| 2859 { | |
| 2860 optionName = unknownOption; | |
| 2861 } | |
| 2862 return wxString::FromUTF8(optionName); | |
| 2863 #else | |
| 2864 return wxEmptyString; | |
| 2865 #endif | |
| 2866 } | |
| 2867 | |
| 2868 bool wxSQLite3Database::CreateFunction(const wxString& funcName, int argCount, wxSQLite3ScalarFunction& function) | |
| 2869 { | |
| 2870 CheckDatabase(); | |
| 2871 wxCharBuffer strFuncName = funcName.ToUTF8(); | |
| 2872 const char* localFuncName = strFuncName; | |
| 2873 int rc = sqlite3_create_function((sqlite3*) m_db, localFuncName, argCount, | |
| 2874 SQLITE_UTF8, &function, | |
| 2875 (void (*)(sqlite3_context*,int,sqlite3_value**)) wxSQLite3FunctionContext::ExecScalarFunction, NULL, NULL); | |
| 2876 return rc == SQLITE_OK; | |
| 2877 } | |
| 2878 | |
| 2879 bool wxSQLite3Database::CreateFunction(const wxString& funcName, int argCount, wxSQLite3AggregateFunction& function) | |
| 2880 { | |
| 2881 CheckDatabase(); | |
| 2882 wxCharBuffer strFuncName = funcName.ToUTF8(); | |
| 2883 const char* localFuncName = strFuncName; | |
| 2884 int rc = sqlite3_create_function((sqlite3*) m_db, localFuncName, argCount, | |
| 2885 SQLITE_UTF8, &function, | |
| 2886 NULL, | |
| 2887 (void (*)(sqlite3_context*,int,sqlite3_value**)) wxSQLite3FunctionContext::ExecAggregateStep, | |
| 2888 (void (*)(sqlite3_context*)) wxSQLite3FunctionContext::ExecAggregateFinalize); | |
| 2889 return rc == SQLITE_OK; | |
| 2890 } | |
| 2891 | |
| 2892 bool wxSQLite3Database::SetAuthorizer(wxSQLite3Authorizer& authorizer) | |
| 2893 { | |
| 2894 CheckDatabase(); | |
| 2895 int rc = sqlite3_set_authorizer((sqlite3*) m_db, wxSQLite3FunctionContext::ExecAuthorizer, &authorizer); | |
| 2896 return rc == SQLITE_OK; | |
| 2897 } | |
| 2898 | |
| 2899 void wxSQLite3Database::SetCommitHook(wxSQLite3Hook* commitHook) | |
| 2900 { | |
| 2901 CheckDatabase(); | |
| 2902 if (commitHook) | |
| 2903 { | |
| 2904 sqlite3_commit_hook((sqlite3*) m_db, (int(*)(void*)) wxSQLite3FunctionContext::ExecCommitHook, commitHook); | |
| 2905 } | |
| 2906 else | |
| 2907 { | |
| 2908 sqlite3_commit_hook((sqlite3*) m_db, (int(*)(void*)) NULL, NULL); | |
| 2909 } | |
| 2910 } | |
| 2911 | |
| 2912 void wxSQLite3Database::SetRollbackHook(wxSQLite3Hook* rollbackHook) | |
| 2913 { | |
| 2914 CheckDatabase(); | |
| 2915 if (rollbackHook) | |
| 2916 { | |
| 2917 sqlite3_rollback_hook((sqlite3*) m_db, (void(*)(void*)) wxSQLite3FunctionContext::ExecRollbackHook, rollbackHook); | |
| 2918 } | |
| 2919 else | |
| 2920 { | |
| 2921 sqlite3_rollback_hook((sqlite3*) m_db, (void(*)(void*)) NULL, NULL); | |
| 2922 } | |
| 2923 } | |
| 2924 | |
| 2925 void wxSQLite3Database::SetUpdateHook(wxSQLite3Hook* updateHook) | |
| 2926 { | |
| 2927 CheckDatabase(); | |
| 2928 if (updateHook) | |
| 2929 { | |
| 2930 sqlite3_update_hook((sqlite3*) m_db, (void(*)(void*,int,const char*,const char*, wxsqlite_int64)) wxSQLite3FunctionContext::ExecUpdateHook, updateHook); | |
| 2931 } | |
| 2932 else | |
| 2933 { | |
| 2934 sqlite3_update_hook((sqlite3*) m_db, (void(*)(void*,int,const char*,const char*, wxsqlite_int64)) NULL, NULL); | |
| 2935 } | |
| 2936 } | |
| 2937 | |
| 2938 void wxSQLite3Database::SetWriteAheadLogHook(wxSQLite3Hook* walHook) | |
| 2939 { | |
| 2940 #if SQLITE_VERSION_NUMBER >= 3007000 | |
| 2941 CheckDatabase(); | |
| 2942 if (walHook) | |
| 2943 { | |
| 2944 walHook->SetDatabase(this); | |
| 2945 sqlite3_wal_hook((sqlite3*) m_db, (int(*)(void *,sqlite3*,const char*,int)) wxSQLite3FunctionContext::ExecWriteAheadLogHook, walHook); | |
| 2946 } | |
| 2947 else | |
| 2948 { | |
| 2949 sqlite3_wal_hook((sqlite3*) m_db, (int(*)(void *,sqlite3*,const char*,int)) NULL, NULL); | |
| 2950 } | |
| 2951 #else | |
| 2952 wxUnusedVar(walHook); | |
| 2953 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOWAL); | |
| 2954 #endif | |
| 2955 } | |
| 2956 | |
| 2957 void wxSQLite3Database::WriteAheadLogCheckpoint(const wxString& database) | |
| 2958 { | |
| 2959 #if SQLITE_VERSION_NUMBER >= 3007000 | |
| 2960 CheckDatabase(); | |
| 2961 wxCharBuffer strDatabase = database.ToUTF8(); | |
| 2962 const char* localDatabase = strDatabase; | |
| 2963 int rc = sqlite3_wal_checkpoint((sqlite3*) m_db, localDatabase); | |
| 2964 | |
| 2965 if (rc != SQLITE_OK) | |
| 2966 { | |
| 2967 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2968 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2969 } | |
| 2970 #else | |
| 2971 wxUnusedVar(database); | |
| 2972 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOWAL); | |
| 2973 #endif | |
| 2974 } | |
| 2975 | |
| 2976 void wxSQLite3Database::AutoWriteAheadLogCheckpoint(int frameCount) | |
| 2977 { | |
| 2978 #if SQLITE_VERSION_NUMBER >= 3007000 | |
| 2979 CheckDatabase(); | |
| 2980 int rc = sqlite3_wal_autocheckpoint((sqlite3*) m_db, frameCount); | |
| 2981 | |
| 2982 if (rc != SQLITE_OK) | |
| 2983 { | |
| 2984 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 2985 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 2986 } | |
| 2987 #else | |
| 2988 wxUnusedVar(frameCount); | |
| 2989 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOWAL); | |
| 2990 #endif | |
| 2991 } | |
| 2992 | |
| 2993 void wxSQLite3Database::SetCollation(const wxString& collationName, wxSQLite3Collation* collation) | |
| 2994 { | |
| 2995 CheckDatabase(); | |
| 2996 wxCharBuffer strCollationName = collationName.ToUTF8(); | |
| 2997 const char* localCollationName = strCollationName; | |
| 2998 int rc; | |
| 2999 if (collation) | |
| 3000 { | |
| 3001 rc = sqlite3_create_collation((sqlite3*) m_db, localCollationName, SQLITE_UTF8, collation, (int(*)(void*,int,const void*,int,const void*)) wxSQLite3Database::ExecComparisonWithCollation); | |
| 3002 } | |
| 3003 else | |
| 3004 { | |
| 3005 rc = sqlite3_create_collation((sqlite3*) m_db, localCollationName, SQLITE_UTF8, NULL, (int(*)(void*,int,const void*,int,const void*)) NULL); | |
| 3006 } | |
| 3007 } | |
| 3008 | |
| 3009 void wxSQLite3Database::SetCollationNeededCallback() | |
| 3010 { | |
| 3011 CheckDatabase(); | |
| 3012 int rc = sqlite3_collation_needed((sqlite3*) m_db, this, (void(*)(void*,sqlite3*,int,const char*)) wxSQLite3Database::ExecCollationNeeded); | |
| 3013 if (rc != SQLITE_OK) | |
| 3014 { | |
| 3015 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3016 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3017 } | |
| 3018 } | |
| 3019 | |
| 3020 void wxSQLite3Database::CheckDatabase() | |
| 3021 { | |
| 3022 if (!m_db) | |
| 3023 { | |
| 3024 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NODB); | |
| 3025 } | |
| 3026 } | |
| 3027 | |
| 3028 void* wxSQLite3Database::Prepare(const char* sql) | |
| 3029 { | |
| 3030 CheckDatabase(); | |
| 3031 | |
| 3032 const char* tail=0; | |
| 3033 sqlite3_stmt* stmt; | |
| 3034 | |
| 3035 int rc = sqlite3_prepare_v2((sqlite3*) m_db, sql, -1, &stmt, &tail); | |
| 3036 | |
| 3037 if (rc != SQLITE_OK) | |
| 3038 { | |
| 3039 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3040 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3041 } | |
| 3042 | |
| 3043 return stmt; | |
| 3044 } | |
| 3045 | |
| 3046 /* static */ | |
| 3047 int wxSQLite3Database::ExecComparisonWithCollation(void* collation, | |
| 3048 int len1, const void* text1, | |
| 3049 int len2, const void* text2) | |
| 3050 { | |
| 3051 wxString locText1 = wxString::FromUTF8((const char*) text1, (size_t) len1); | |
| 3052 wxString locText2 = wxString::FromUTF8((const char*) text2, (size_t) len2); | |
| 3053 return ((wxSQLite3Collation*) collation)->Compare(locText1, locText2); | |
| 3054 } | |
| 3055 | |
| 3056 void wxSQLite3Database::ExecCollationNeeded(void* db, void*, int, const char* collationName) | |
| 3057 { | |
| 3058 wxString locCollation = wxString::FromUTF8((const char*) collationName); | |
| 3059 ((wxSQLite3Database*) db)->SetNeededCollation(locCollation); | |
| 3060 } | |
| 3061 | |
| 3062 void wxSQLite3Database::GetMetaData(const wxString& databaseName, const wxString& tableName, const wxString& columnName, | |
| 3063 wxString* dataType, wxString* collation, bool* notNull, bool* primaryKey, bool* autoIncrement) | |
| 3064 { | |
| 3065 #if WXSQLITE3_HAVE_METADATA | |
| 3066 wxCharBuffer strDatabaseName = databaseName.ToUTF8(); | |
| 3067 const char* localDatabaseName = strDatabaseName; | |
| 3068 if (databaseName == wxEmptyString) localDatabaseName = NULL; | |
| 3069 wxCharBuffer strTableName = tableName.ToUTF8(); | |
| 3070 const char* localTableName = strTableName; | |
| 3071 wxCharBuffer strColumnName = columnName.ToUTF8(); | |
| 3072 const char* localColumnName = strColumnName; | |
| 3073 const char* localDataType; | |
| 3074 const char* localCollation; | |
| 3075 int localNotNull; | |
| 3076 int localPrimaryKey; | |
| 3077 int localAutoIncrement; | |
| 3078 int rc = sqlite3_table_column_metadata((sqlite3*) m_db, localDatabaseName, localTableName, localColumnName, | |
| 3079 &localDataType, &localCollation, &localNotNull, &localPrimaryKey, &localAutoIncrement); | |
| 3080 | |
| 3081 if (rc != SQLITE_OK) | |
| 3082 { | |
| 3083 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3084 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3085 } | |
| 3086 | |
| 3087 if (dataType != NULL) *dataType = wxString::FromUTF8(localDataType); | |
| 3088 if (collation != NULL) *collation = wxString::FromUTF8(localCollation); | |
| 3089 | |
| 3090 if (notNull != NULL) *notNull = (localNotNull != 0); | |
| 3091 if (primaryKey != NULL) *primaryKey = (localPrimaryKey != 0); | |
| 3092 if (autoIncrement != NULL) *autoIncrement = (localAutoIncrement != 0); | |
| 3093 #else | |
| 3094 wxUnusedVar(databaseName); | |
| 3095 wxUnusedVar(tableName); | |
| 3096 wxUnusedVar(columnName); | |
| 3097 wxUnusedVar(dataType); | |
| 3098 wxUnusedVar(collation); | |
| 3099 wxUnusedVar(notNull); | |
| 3100 wxUnusedVar(primaryKey); | |
| 3101 wxUnusedVar(autoIncrement); | |
| 3102 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMETADATA); | |
| 3103 #endif | |
| 3104 } | |
| 3105 | |
| 3106 void wxSQLite3Database::LoadExtension(const wxString& fileName, const wxString& entryPoint) | |
| 3107 { | |
| 3108 #if WXSQLITE3_HAVE_LOAD_EXTENSION | |
| 3109 wxCharBuffer strFileName = fileName.ToUTF8(); | |
| 3110 const char* localFileName = strFileName; | |
| 3111 wxCharBuffer strEntryPoint = entryPoint.ToUTF8(); | |
| 3112 const char* localEntryPoint = strEntryPoint; | |
| 3113 | |
| 3114 int rc = sqlite3_load_extension((sqlite3 *) m_db, localFileName, localEntryPoint, NULL); | |
| 3115 if (rc != SQLITE_OK) | |
| 3116 { | |
| 3117 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3118 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3119 } | |
| 3120 #else | |
| 3121 wxUnusedVar(fileName); | |
| 3122 wxUnusedVar(entryPoint); | |
| 3123 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOLOADEXT); | |
| 3124 #endif | |
| 3125 } | |
| 3126 | |
| 3127 void wxSQLite3Database::EnableLoadExtension(bool enable) | |
| 3128 { | |
| 3129 #if WXSQLITE3_HAVE_LOAD_EXTENSION | |
| 3130 int onoff = (enable) ? 1 : 0; | |
| 3131 int rc = sqlite3_enable_load_extension((sqlite3 *) m_db, onoff); | |
| 3132 if (rc != SQLITE_OK) | |
| 3133 { | |
| 3134 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3135 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3136 } | |
| 3137 #else | |
| 3138 wxUnusedVar(enable); | |
| 3139 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOLOADEXT); | |
| 3140 #endif | |
| 3141 } | |
| 3142 | |
| 3143 void wxSQLite3Database::ReKey(const wxString& newKey) | |
| 3144 { | |
| 3145 #if WXSQLITE3_HAVE_CODEC | |
| 3146 wxCharBuffer strLocalNewKey = newKey.ToUTF8(); | |
| 3147 const char* localNewKey = strLocalNewKey; | |
| 3148 wxMemoryBuffer binaryNewKey; | |
| 3149 if (newKey.Length() > 0) | |
| 3150 { | |
| 3151 binaryNewKey.AppendData((void*) localNewKey, strlen(localNewKey)); | |
| 3152 } | |
| 3153 ReKey(binaryNewKey); | |
| 3154 #else | |
| 3155 wxUnusedVar(newKey); | |
| 3156 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOCODEC); | |
| 3157 #endif | |
| 3158 } | |
| 3159 | |
| 3160 void wxSQLite3Database::ReKey(const wxMemoryBuffer& newKey) | |
| 3161 { | |
| 3162 #if WXSQLITE3_HAVE_CODEC | |
| 3163 int rc = sqlite3_rekey((sqlite3*) m_db, newKey.GetData(), (int) newKey.GetDataLen()); | |
| 3164 if (rc != SQLITE_OK) | |
| 3165 { | |
| 3166 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 3167 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 3168 } | |
| 3169 #else | |
| 3170 wxUnusedVar(newKey); | |
| 3171 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOCODEC); | |
| 3172 #endif | |
| 3173 } | |
| 3174 | |
| 3175 int wxSQLite3Database::GetLimit(wxSQLite3LimitType id) | |
| 3176 { | |
| 3177 int value = -1; | |
| 3178 #if SQLITE_VERSION_NUMBER >= 3005008 | |
| 3179 CheckDatabase(); | |
| 3180 if (id >= WXSQLITE_LIMIT_LENGTH && id <= WXSQLITE_LIMIT_VARIABLE_NUMBER) | |
| 3181 { | |
| 3182 value = sqlite3_limit((sqlite3 *) m_db, id, -1); | |
| 3183 } | |
| 3184 #else | |
| 3185 wxUnusedVar(id); | |
| 3186 #endif | |
| 3187 return value; | |
| 3188 } | |
| 3189 | |
| 3190 int wxSQLite3Database::SetLimit(wxSQLite3LimitType id, int newValue) | |
| 3191 { | |
| 3192 int value = -1; | |
| 3193 #if SQLITE_VERSION_NUMBER >= 3005008 | |
| 3194 CheckDatabase(); | |
| 3195 if (id >= WXSQLITE_LIMIT_LENGTH && id <= WXSQLITE_LIMIT_VARIABLE_NUMBER) | |
| 3196 { | |
| 3197 value = sqlite3_limit((sqlite3 *) m_db, id, newValue); | |
| 3198 } | |
| 3199 #else | |
| 3200 wxUnusedVar(id); | |
| 3201 wxUnusedVar(newValue); | |
| 3202 #endif | |
| 3203 return value; | |
| 3204 } | |
| 3205 | |
| 3206 static const wxChar* limitCodeString[] = | |
| 3207 { wxT("SQLITE_LIMIT_LENGTH"), wxT("SQLITE_LIMIT_SQL_LENGTH"), | |
| 3208 wxT("SQLITE_LIMIT_COLUMN"), wxT("SQLITE_LIMIT_EXPR_DEPTH"), | |
| 3209 wxT("SQLITE_LIMIT_COMPOUND_SELECT"), wxT("SQLITE_LIMIT_VDBE_OP"), | |
| 3210 wxT("SQLITE_LIMIT_FUNCTION_ARG"), wxT("SQLITE_LIMIT_ATTACHED"), | |
| 3211 wxT("SQLITE_LIMIT_LIKE_PATTERN_LENGTH"), wxT("SQLITE_LIMIT_VARIABLE_NUMBER"), | |
| 3212 wxT("SQLITE_LIMIT_TRIGGER_DEPTH") | |
| 3213 }; | |
| 3214 | |
| 3215 | |
| 3216 /* static */ | |
| 3217 wxString wxSQLite3Database::LimitTypeToString(wxSQLite3LimitType type) | |
| 3218 { | |
| 3219 const wxChar* limitString = wxT("Unknown"); | |
| 3220 if (type >= WXSQLITE_LIMIT_LENGTH && type <= WXSQLITE_LIMIT_VARIABLE_NUMBER) | |
| 3221 { | |
| 3222 limitString = limitCodeString[type]; | |
| 3223 } | |
| 3224 return wxString(limitString); | |
| 3225 } | |
| 3226 | |
| 3227 /* static */ | |
| 3228 void wxSQLite3Database::InitializeSQLite() | |
| 3229 { | |
| 3230 #if SQLITE_VERSION_NUMBER >= 3006000 | |
| 3231 int rc = sqlite3_initialize(); | |
| 3232 if (rc != SQLITE_OK) | |
| 3233 { | |
| 3234 throw wxSQLite3Exception(rc, wxERRMSG_INITIALIZE); | |
| 3235 } | |
| 3236 #endif | |
| 3237 } | |
| 3238 | |
| 3239 /* static */ | |
| 3240 void wxSQLite3Database::ShutdownSQLite() | |
| 3241 { | |
| 3242 #if SQLITE_VERSION_NUMBER >= 3006000 | |
| 3243 int rc = sqlite3_shutdown(); | |
| 3244 if (rc != SQLITE_OK) | |
| 3245 { | |
| 3246 throw wxSQLite3Exception(rc, wxERRMSG_SHUTDOWN); | |
| 3247 } | |
| 3248 #endif | |
| 3249 } | |
| 3250 | |
| 3251 /* static */ | |
| 3252 bool wxSQLite3Database::Randomness(int n, wxMemoryBuffer& random) | |
| 3253 { | |
| 3254 bool ok = false; | |
| 3255 #if SQLITE_VERSION_NUMBER >= 3005008 | |
| 3256 if (n > 0) | |
| 3257 { | |
| 3258 void* buffer = random.GetWriteBuf(n); | |
| 3259 sqlite3_randomness(n, buffer); | |
| 3260 random.UngetWriteBuf(n); | |
| 3261 ok = true; | |
| 3262 } | |
| 3263 #else | |
| 3264 wxUnusedVar(n); | |
| 3265 wxUnusedVar(random); | |
| 3266 #endif | |
| 3267 return ok; | |
| 3268 } | |
| 3269 | |
| 3270 // ---------------------------------------------------------------------------- | |
| 3271 // wxSQLite3FunctionContext: class providing the function context | |
| 3272 // for user defined functions | |
| 3273 // ---------------------------------------------------------------------------- | |
| 3274 | |
| 3275 int wxSQLite3FunctionContext::GetArgCount() | |
| 3276 { | |
| 3277 return m_argc; | |
| 3278 } | |
| 3279 | |
| 3280 int wxSQLite3FunctionContext::GetArgType(int argIndex) | |
| 3281 { | |
| 3282 if (argIndex >= 0 && argIndex < m_argc) | |
| 3283 { | |
| 3284 return sqlite3_value_type((sqlite3_value*) m_argv[argIndex]); | |
| 3285 } | |
| 3286 else | |
| 3287 { | |
| 3288 return SQLITE_NULL; | |
| 3289 } | |
| 3290 } | |
| 3291 | |
| 3292 bool wxSQLite3FunctionContext::IsNull(int argIndex) | |
| 3293 { | |
| 3294 if (argIndex >= 0 && argIndex < m_argc) | |
| 3295 { | |
| 3296 return sqlite3_value_type((sqlite3_value*) m_argv[argIndex]) == SQLITE_NULL; | |
| 3297 } | |
| 3298 else | |
| 3299 { | |
| 3300 return true; | |
| 3301 } | |
| 3302 } | |
| 3303 | |
| 3304 int wxSQLite3FunctionContext::GetInt(int argIndex, int nullValue) | |
| 3305 { | |
| 3306 if (argIndex >= 0 && argIndex < m_argc) | |
| 3307 { | |
| 3308 if (!IsNull(argIndex)) | |
| 3309 { | |
| 3310 return sqlite3_value_int((sqlite3_value*) m_argv[argIndex]); | |
| 3311 } | |
| 3312 else | |
| 3313 { | |
| 3314 return nullValue; | |
| 3315 } | |
| 3316 } | |
| 3317 else | |
| 3318 { | |
| 3319 return nullValue; | |
| 3320 } | |
| 3321 } | |
| 3322 | |
| 3323 wxLongLong wxSQLite3FunctionContext::GetInt64(int argIndex, wxLongLong nullValue) | |
| 3324 { | |
| 3325 if (argIndex >= 0 && argIndex < m_argc) | |
| 3326 { | |
| 3327 if (!IsNull(argIndex)) | |
| 3328 { | |
| 3329 return wxLongLong(sqlite3_value_int64((sqlite3_value*) m_argv[argIndex])); | |
| 3330 } | |
| 3331 else | |
| 3332 { | |
| 3333 return nullValue; | |
| 3334 } | |
| 3335 } | |
| 3336 else | |
| 3337 { | |
| 3338 return nullValue; | |
| 3339 } | |
| 3340 } | |
| 3341 | |
| 3342 double wxSQLite3FunctionContext::GetDouble(int argIndex, double nullValue) | |
| 3343 { | |
| 3344 if (argIndex >= 0 && argIndex < m_argc) | |
| 3345 { | |
| 3346 if (!IsNull(argIndex)) | |
| 3347 { | |
| 3348 return sqlite3_value_double((sqlite3_value*) m_argv[argIndex]); | |
| 3349 } | |
| 3350 else | |
| 3351 { | |
| 3352 return nullValue; | |
| 3353 } | |
| 3354 } | |
| 3355 else | |
| 3356 { | |
| 3357 return nullValue; | |
| 3358 } | |
| 3359 } | |
| 3360 | |
| 3361 wxString wxSQLite3FunctionContext::GetString(int argIndex, const wxString& nullValue) | |
| 3362 { | |
| 3363 if (argIndex >= 0 && argIndex < m_argc) | |
| 3364 { | |
| 3365 if (!IsNull(argIndex)) | |
| 3366 { | |
| 3367 const char* localValue = (const char*) sqlite3_value_text((sqlite3_value*) m_argv[argIndex]); | |
| 3368 return wxString::FromUTF8(localValue); | |
| 3369 } | |
| 3370 else | |
| 3371 { | |
| 3372 return nullValue; | |
| 3373 } | |
| 3374 } | |
| 3375 else | |
| 3376 { | |
| 3377 return nullValue; | |
| 3378 } | |
| 3379 } | |
| 3380 | |
| 3381 wxMemoryBuffer& wxSQLite3FunctionContext::GetBlob(int argIndex, wxMemoryBuffer& buffer) | |
| 3382 { | |
| 3383 if (argIndex >= 0 && argIndex < m_argc) | |
| 3384 { | |
| 3385 if (!IsNull(argIndex)) | |
| 3386 { | |
| 3387 int len = sqlite3_value_bytes((sqlite3_value*) m_argv[argIndex]); | |
| 3388 const void* blob = sqlite3_value_blob((sqlite3_value*) m_argv[argIndex]); | |
| 3389 buffer.AppendData((void*) blob, (size_t) len); | |
| 3390 } | |
| 3391 } | |
| 3392 return buffer; | |
| 3393 } | |
| 3394 | |
| 3395 void wxSQLite3FunctionContext::SetResult(int value) | |
| 3396 { | |
| 3397 sqlite3_result_int((sqlite3_context*) m_ctx, value); | |
| 3398 } | |
| 3399 | |
| 3400 void wxSQLite3FunctionContext::SetResult(wxLongLong value) | |
| 3401 { | |
| 3402 sqlite3_result_int64((sqlite3_context*) m_ctx, value.GetValue()); | |
| 3403 } | |
| 3404 | |
| 3405 void wxSQLite3FunctionContext::SetResult(double value) | |
| 3406 { | |
| 3407 sqlite3_result_double((sqlite3_context*) m_ctx, value); | |
| 3408 } | |
| 3409 | |
| 3410 void wxSQLite3FunctionContext::SetResult(const wxString& value) | |
| 3411 { | |
| 3412 wxCharBuffer strValue = value.ToUTF8(); | |
| 3413 const char* localValue = strValue; | |
| 3414 sqlite3_result_text((sqlite3_context*) m_ctx, localValue, -1, SQLITE_TRANSIENT); | |
| 3415 } | |
| 3416 | |
| 3417 void wxSQLite3FunctionContext::SetResult(unsigned char* value, int len) | |
| 3418 { | |
| 3419 sqlite3_result_blob((sqlite3_context*) m_ctx, value, len, SQLITE_TRANSIENT); | |
| 3420 } | |
| 3421 | |
| 3422 void wxSQLite3FunctionContext::SetResult(const wxMemoryBuffer& buffer) | |
| 3423 { | |
| 3424 sqlite3_result_blob((sqlite3_context*) m_ctx, buffer.GetData(), (int) buffer.GetDataLen(), SQLITE_TRANSIENT); | |
| 3425 } | |
| 3426 | |
| 3427 void wxSQLite3FunctionContext::SetResultNull() | |
| 3428 { | |
| 3429 sqlite3_result_null((sqlite3_context*) m_ctx); | |
| 3430 } | |
| 3431 | |
| 3432 void wxSQLite3FunctionContext::SetResultZeroBlob(int blobSize) | |
| 3433 { | |
| 3434 #if SQLITE_VERSION_NUMBER >= 3004000 | |
| 3435 sqlite3_result_zeroblob((sqlite3_context*) m_ctx, blobSize); | |
| 3436 #endif | |
| 3437 } | |
| 3438 | |
| 3439 void wxSQLite3FunctionContext::SetResultArg(int argIndex) | |
| 3440 { | |
| 3441 if (argIndex >= 0 && argIndex < m_argc) { | |
| 3442 sqlite3_result_value((sqlite3_context*) m_ctx, (sqlite3_value*) m_argv[argIndex]); | |
| 3443 } else { | |
| 3444 sqlite3_result_null((sqlite3_context*) m_ctx); | |
| 3445 } | |
| 3446 } | |
| 3447 | |
| 3448 void wxSQLite3FunctionContext::SetResultError(const wxString& errmsg) | |
| 3449 { | |
| 3450 wxCharBuffer strErrmsg = errmsg.ToUTF8(); | |
| 3451 const char* localErrmsg = strErrmsg; | |
| 3452 sqlite3_result_error((sqlite3_context*) m_ctx, localErrmsg, -1); | |
| 3453 } | |
| 3454 | |
| 3455 int wxSQLite3FunctionContext::GetAggregateCount() | |
| 3456 { | |
| 3457 if (m_isAggregate) | |
| 3458 { | |
| 3459 return m_count; | |
| 3460 } | |
| 3461 else | |
| 3462 { | |
| 3463 return 0; | |
| 3464 } | |
| 3465 } | |
| 3466 | |
| 3467 void* wxSQLite3FunctionContext::GetAggregateStruct(int len) | |
| 3468 { | |
| 3469 if (m_isAggregate) | |
| 3470 { | |
| 3471 return sqlite3_aggregate_context((sqlite3_context*) m_ctx, len); | |
| 3472 } | |
| 3473 else | |
| 3474 { | |
| 3475 return NULL; | |
| 3476 } | |
| 3477 } | |
| 3478 | |
| 3479 /* static */ | |
| 3480 void wxSQLite3FunctionContext::ExecScalarFunction(void* ctx, int argc, void** argv) | |
| 3481 { | |
| 3482 wxSQLite3FunctionContext context(ctx, false, argc, argv); | |
| 3483 wxSQLite3ScalarFunction* func = (wxSQLite3ScalarFunction*) sqlite3_user_data((sqlite3_context*) ctx); | |
| 3484 func->Execute(context); | |
| 3485 } | |
| 3486 | |
| 3487 /* static */ | |
| 3488 void wxSQLite3FunctionContext::ExecAggregateStep(void* ctx, int argc, void** argv) | |
| 3489 { | |
| 3490 wxSQLite3FunctionContext context(ctx, true, argc, argv); | |
| 3491 wxSQLite3AggregateFunction* func = (wxSQLite3AggregateFunction*) sqlite3_user_data((sqlite3_context*) ctx); | |
| 3492 func->m_count++; | |
| 3493 context.m_count = func->m_count; | |
| 3494 func->Aggregate(context); | |
| 3495 } | |
| 3496 | |
| 3497 /* static */ | |
| 3498 void wxSQLite3FunctionContext::ExecAggregateFinalize(void* ctx) | |
| 3499 { | |
| 3500 wxSQLite3FunctionContext context(ctx, true, 0, NULL); | |
| 3501 wxSQLite3AggregateFunction* func = (wxSQLite3AggregateFunction*) sqlite3_user_data((sqlite3_context*) ctx); | |
| 3502 context.m_count = func->m_count; | |
| 3503 func->Finalize(context); | |
| 3504 } | |
| 3505 | |
| 3506 /* static */ | |
| 3507 int wxSQLite3FunctionContext::ExecAuthorizer(void* func, int type, | |
| 3508 const char* arg1, const char* arg2, | |
| 3509 const char* arg3, const char* arg4) | |
| 3510 { | |
| 3511 wxString locArg1 = wxString::FromUTF8(arg1); | |
| 3512 wxString locArg2 = wxString::FromUTF8(arg2); | |
| 3513 wxString locArg3 = wxString::FromUTF8(arg3); | |
| 3514 wxString locArg4 = wxString::FromUTF8(arg4); | |
| 3515 wxSQLite3Authorizer::wxAuthorizationCode localType = (wxSQLite3Authorizer::wxAuthorizationCode) type; | |
| 3516 return (int) ((wxSQLite3Authorizer*) func)->Authorize(localType, locArg1, locArg2, locArg3, locArg3); | |
| 3517 } | |
| 3518 | |
| 3519 /* static */ | |
| 3520 int wxSQLite3FunctionContext::ExecCommitHook(void* hook) | |
| 3521 { | |
| 3522 return (int) ((wxSQLite3Hook*) hook)->CommitCallback(); | |
| 3523 } | |
| 3524 | |
| 3525 /* static */ | |
| 3526 void wxSQLite3FunctionContext::ExecRollbackHook(void* hook) | |
| 3527 { | |
| 3528 ((wxSQLite3Hook*) hook)->RollbackCallback(); | |
| 3529 } | |
| 3530 | |
| 3531 /* static */ | |
| 3532 void wxSQLite3FunctionContext::ExecUpdateHook(void* hook, int type, | |
| 3533 const char* database, const char* table, | |
| 3534 wxsqlite_int64 rowid) | |
| 3535 { | |
| 3536 wxString locDatabase = wxString::FromUTF8(database); | |
| 3537 wxString locTable = wxString::FromUTF8(table); | |
| 3538 wxSQLite3Hook::wxUpdateType locType = (wxSQLite3Hook::wxUpdateType) type; | |
| 3539 wxLongLong locRowid = rowid; | |
| 3540 ((wxSQLite3Hook*) hook)->UpdateCallback(locType, locDatabase, locTable, locRowid); | |
| 3541 } | |
| 3542 | |
| 3543 wxSQLite3FunctionContext::wxSQLite3FunctionContext(void* ctx, bool isAggregate, int argc, void** argv) | |
| 3544 : m_ctx(ctx), m_isAggregate(isAggregate), m_count(0), m_argc(argc), m_argv(argv) | |
| 3545 { | |
| 3546 } | |
| 3547 | |
| 3548 /* static */ | |
| 3549 int wxSQLite3FunctionContext::ExecWriteAheadLogHook(void* hook, void* dbHandle, | |
| 3550 const char* database, int numPages) | |
| 3551 { | |
| 3552 wxString locDatabase = wxString::FromUTF8(database); | |
| 3553 wxUnusedVar(dbHandle); | |
| 3554 return (int) ((wxSQLite3Hook*) hook)->WriteAheadLogCallback(locDatabase, numPages); | |
| 3555 } | |
| 3556 | |
| 3557 static const wxChar* authCodeString[] = | |
| 3558 { wxT("SQLITE_COPY"), wxT("SQLITE_CREATE_INDEX"), wxT("SQLITE_CREATE_TABLE"), | |
| 3559 wxT("SQLITE_CREATE_TEMP_INDEX"), wxT("SQLITE_CREATE_TEMP_TABLE"), wxT("SQLITE_CREATE_TEMP_TRIGGER"), | |
| 3560 wxT("SQLITE_CREATE_TEMP_VIEW"), wxT("SQLITE_CREATE_TRIGGER"), wxT("SQLITE_CREATE_VIEW"), | |
| 3561 wxT("SQLITE_DELETE"), wxT("SQLITE_DROP_INDEX"), wxT("SQLITE_DROP_TABLE"), | |
| 3562 wxT("SQLITE_DROP_TEMP_INDEX"), wxT("SQLITE_DROP_TEMP_TABLE"), wxT("SQLITE_DROP_TEMP_TRIGGER"), | |
| 3563 wxT("SQLITE_DROP_TEMP_VIEW"), wxT("SQLITE_DROP_TRIGGER"), wxT("SQLITE_DROP_VIEW"), | |
| 3564 wxT("SQLITE_INSERT"), wxT("SQLITE_PRAGMA"), wxT("SQLITE_READ"), | |
| 3565 wxT("SQLITE_SELECT"), wxT("SQLITE_TRANSACTION"), wxT("SQLITE_UPDATE"), | |
| 3566 wxT("SQLITE_ATTACH"), wxT("SQLITE_DETACH"), wxT("SQLITE_ALTER_TABLE"), | |
| 3567 wxT("SQLITE_REINDEX"), wxT("SQLITE_ANALYZE"), wxT("SQLITE_CREATE_VTABLE"), | |
| 3568 wxT("SQLITE_DROP_VTABLE"), wxT("SQLITE_FUNCTION"), wxT("SQLITE_SAVEPOINT") | |
| 3569 }; | |
| 3570 | |
| 3571 | |
| 3572 /* static */ | |
| 3573 wxString wxSQLite3Authorizer::AuthorizationCodeToString(wxSQLite3Authorizer::wxAuthorizationCode type) | |
| 3574 { | |
| 3575 const wxChar* authString = wxT("Unknown"); | |
| 3576 if (type >= SQLITE_COPY && type <= SQLITE_MAX_CODE) | |
| 3577 { | |
| 3578 authString = authCodeString[type]; | |
| 3579 } | |
| 3580 return wxString(authString); | |
| 3581 } | |
| 3582 | |
| 3583 // ---------------------------------------------------------------------------- | |
| 3584 // wxSQLite3Transaction | |
| 3585 // ---------------------------------------------------------------------------- | |
| 3586 | |
| 3587 wxSQLite3Transaction::wxSQLite3Transaction(wxSQLite3Database* db, wxSQLite3TransactionType transactionType) | |
| 3588 { | |
| 3589 assert(db != NULL); | |
| 3590 m_database = db; | |
| 3591 try | |
| 3592 { | |
| 3593 m_database->Begin(transactionType); | |
| 3594 } | |
| 3595 catch (...) | |
| 3596 { | |
| 3597 m_database = NULL; // Flag that transaction is not active | |
| 3598 } | |
| 3599 } | |
| 3600 | |
| 3601 wxSQLite3Transaction::~wxSQLite3Transaction() | |
| 3602 { | |
| 3603 if (m_database != NULL) | |
| 3604 { | |
| 3605 m_database->Rollback(); | |
| 3606 } | |
| 3607 } | |
| 3608 | |
| 3609 void wxSQLite3Transaction::Commit() | |
| 3610 { | |
| 3611 try | |
| 3612 { | |
| 3613 m_database->Commit(); | |
| 3614 } | |
| 3615 catch (...) | |
| 3616 { | |
| 3617 m_database->Rollback(); | |
| 3618 } | |
| 3619 m_database = NULL; | |
| 3620 } | |
| 3621 | |
| 3622 void wxSQLite3Transaction::Rollback() | |
| 3623 { | |
| 3624 try | |
| 3625 { | |
| 3626 m_database->Rollback(); | |
| 3627 } | |
| 3628 catch (...) | |
| 3629 { | |
| 3630 m_database->Rollback(); | |
| 3631 } | |
| 3632 m_database = NULL; | |
| 3633 } | |
| 3634 | |
| 3635 // --- User defined function classes | |
| 3636 | |
| 3637 #if wxUSE_REGEX | |
| 3638 | |
| 3639 wxSQLite3RegExpOperator::wxSQLite3RegExpOperator(int flags) : m_flags(flags) | |
| 3640 { | |
| 3641 } | |
| 3642 | |
| 3643 wxSQLite3RegExpOperator::~wxSQLite3RegExpOperator() | |
| 3644 { | |
| 3645 } | |
| 3646 | |
| 3647 void wxSQLite3RegExpOperator::Execute(wxSQLite3FunctionContext& ctx) | |
| 3648 { | |
| 3649 int argCount = ctx.GetArgCount(); | |
| 3650 if (argCount == 2) | |
| 3651 { | |
| 3652 wxString exprStr = ctx.GetString(0); | |
| 3653 wxString textStr = ctx.GetString(1); | |
| 3654 if (!m_exprStr.IsSameAs(exprStr)) | |
| 3655 { | |
| 3656 m_exprStr = exprStr; | |
| 3657 m_regEx.Compile(m_exprStr, m_flags); | |
| 3658 } | |
| 3659 if (m_regEx.IsValid()) | |
| 3660 { | |
| 3661 int rc = (m_regEx.Matches(textStr)) ? 1 : 0; | |
| 3662 ctx.SetResult(rc); | |
| 3663 } | |
| 3664 else | |
| 3665 { | |
| 3666 ctx.SetResultError(wxString(_("Regular expression invalid: '"))+exprStr+_T("'.")); | |
| 3667 } | |
| 3668 } | |
| 3669 else | |
| 3670 { | |
| 3671 ctx.SetResultError(wxString::Format(_("REGEXP called with wrong number of arguments: %d instead of 2."), argCount)); | |
| 3672 } | |
| 3673 } | |
| 3674 | |
| 3675 #endif | |
| 3676 | |
| 3677 // --- Support for named collections | |
| 3678 | |
| 3679 #if WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 3680 | |
| 3681 // The following code is based on the SQLite test_intarray source code. | |
| 3682 | |
| 3683 #include <string.h> | |
| 3684 #include <assert.h> | |
| 3685 | |
| 3686 /// Definition of the sqlite3_intarray object (internal) | |
| 3687 struct sqlite3_intarray | |
| 3688 { | |
| 3689 int n; // Number of elements in the array | |
| 3690 sqlite3_int64* a; // Contents of the array | |
| 3691 void (*xFree)(void*); // Function used to free a[] | |
| 3692 }; | |
| 3693 | |
| 3694 // Objects used internally by the virtual table implementation | |
| 3695 typedef struct intarray_vtab intarray_vtab; | |
| 3696 typedef struct intarray_cursor intarray_cursor; | |
| 3697 | |
| 3698 /// Definition of intarray table object (internal) | |
| 3699 struct intarray_vtab | |
| 3700 { | |
| 3701 sqlite3_vtab base; // Base class | |
| 3702 sqlite3_intarray* pContent; // Content of the integer array | |
| 3703 }; | |
| 3704 | |
| 3705 /// Definition of intarray cursor object (internal) | |
| 3706 struct intarray_cursor | |
| 3707 { | |
| 3708 sqlite3_vtab_cursor base; // Base class | |
| 3709 int i; // Current cursor position | |
| 3710 }; | |
| 3711 | |
| 3712 // Free an sqlite3_intarray object. | |
| 3713 static void intarrayFree(sqlite3_intarray* p) | |
| 3714 { | |
| 3715 if (p->a != NULL && p->xFree) | |
| 3716 { | |
| 3717 p->xFree(p->a); | |
| 3718 } | |
| 3719 sqlite3_free(p); | |
| 3720 } | |
| 3721 | |
| 3722 // Table destructor for the intarray module. | |
| 3723 static int intarrayDestroy(sqlite3_vtab* p) | |
| 3724 { | |
| 3725 intarray_vtab* pVtab = (intarray_vtab*)p; | |
| 3726 sqlite3_free(pVtab); | |
| 3727 return 0; | |
| 3728 } | |
| 3729 | |
| 3730 // Table constructor for the intarray module. | |
| 3731 static int intarrayCreate(sqlite3* db, // Database where module is created | |
| 3732 void* pAux, // clientdata for the module | |
| 3733 int /*argc*/, // Number of arguments | |
| 3734 const char* const* /*argv*/, // Value for all arguments | |
| 3735 sqlite3_vtab** ppVtab, // Write the new virtual table object here | |
| 3736 char** /*pzErr*/) // Put error message text here | |
| 3737 { | |
| 3738 int rc = SQLITE_NOMEM; | |
| 3739 intarray_vtab* pVtab = (intarray_vtab*) sqlite3_malloc(sizeof(intarray_vtab)); | |
| 3740 | |
| 3741 if (pVtab) | |
| 3742 { | |
| 3743 memset(pVtab, 0, sizeof(intarray_vtab)); | |
| 3744 pVtab->pContent = (sqlite3_intarray*)pAux; | |
| 3745 rc = sqlite3_declare_vtab(db, "CREATE TABLE x(value INTEGER PRIMARY KEY)"); | |
| 3746 } | |
| 3747 *ppVtab = (sqlite3_vtab*)pVtab; | |
| 3748 return rc; | |
| 3749 } | |
| 3750 | |
| 3751 // Open a new cursor on the intarray table. | |
| 3752 static int intarrayOpen(sqlite3_vtab* /*pVTab*/, sqlite3_vtab_cursor** ppCursor) | |
| 3753 { | |
| 3754 int rc = SQLITE_NOMEM; | |
| 3755 intarray_cursor* pCur = (intarray_cursor*) sqlite3_malloc(sizeof(intarray_cursor)); | |
| 3756 if (pCur) | |
| 3757 { | |
| 3758 memset(pCur, 0, sizeof(intarray_cursor)); | |
| 3759 *ppCursor = (sqlite3_vtab_cursor *)pCur; | |
| 3760 rc = SQLITE_OK; | |
| 3761 } | |
| 3762 return rc; | |
| 3763 } | |
| 3764 | |
| 3765 // Close a intarray table cursor. | |
| 3766 static int intarrayClose(sqlite3_vtab_cursor* cur) | |
| 3767 { | |
| 3768 intarray_cursor* pCur = (intarray_cursor*)cur; | |
| 3769 sqlite3_free(pCur); | |
| 3770 return SQLITE_OK; | |
| 3771 } | |
| 3772 | |
| 3773 // Retrieve a column of data. | |
| 3774 static int intarrayColumn(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int /*i*/) | |
| 3775 { | |
| 3776 intarray_cursor* pCur = (intarray_cursor*)cur; | |
| 3777 intarray_vtab* pVtab = (intarray_vtab*)cur->pVtab; | |
| 3778 if (pCur->i >= 0 && pCur->i < pVtab->pContent->n) | |
| 3779 { | |
| 3780 sqlite3_result_int64(ctx, pVtab->pContent->a[pCur->i]); | |
| 3781 } | |
| 3782 return SQLITE_OK; | |
| 3783 } | |
| 3784 | |
| 3785 // Retrieve the current rowid. | |
| 3786 static int intarrayRowid(sqlite3_vtab_cursor* cur, sqlite_int64* pRowid) | |
| 3787 { | |
| 3788 intarray_cursor* pCur = (intarray_cursor*)cur; | |
| 3789 *pRowid = pCur->i; | |
| 3790 return SQLITE_OK; | |
| 3791 } | |
| 3792 | |
| 3793 static int intarrayEof(sqlite3_vtab_cursor* cur) | |
| 3794 { | |
| 3795 intarray_cursor* pCur = (intarray_cursor*)cur; | |
| 3796 intarray_vtab* pVtab = (intarray_vtab*)cur->pVtab; | |
| 3797 return pCur->i >= pVtab->pContent->n; | |
| 3798 } | |
| 3799 | |
| 3800 // Advance the cursor to the next row. | |
| 3801 static int intarrayNext(sqlite3_vtab_cursor* cur) | |
| 3802 { | |
| 3803 intarray_cursor* pCur = (intarray_cursor*)cur; | |
| 3804 pCur->i++; | |
| 3805 return SQLITE_OK; | |
| 3806 } | |
| 3807 | |
| 3808 // Reset a intarray table cursor. | |
| 3809 static int intarrayFilter(sqlite3_vtab_cursor* pVtabCursor, | |
| 3810 int /*idxNum*/, const char* /*idxStr*/, | |
| 3811 int /*argc*/, sqlite3_value** /*argv*/) | |
| 3812 { | |
| 3813 intarray_cursor *pCur = (intarray_cursor *)pVtabCursor; | |
| 3814 pCur->i = 0; | |
| 3815 return SQLITE_OK; | |
| 3816 } | |
| 3817 | |
| 3818 // Analyse the WHERE condition. | |
| 3819 static int intarrayBestIndex(sqlite3_vtab* /*tab*/, sqlite3_index_info* /*pIdxInfo*/) | |
| 3820 { | |
| 3821 return SQLITE_OK; | |
| 3822 } | |
| 3823 | |
| 3824 // Definition of a virtual table module for integer collections | |
| 3825 static sqlite3_module intarrayModule = | |
| 3826 { | |
| 3827 0, // iVersion | |
| 3828 intarrayCreate, // xCreate - create a new virtual table | |
| 3829 intarrayCreate, // xConnect - connect to an existing vtab | |
| 3830 intarrayBestIndex, // xBestIndex - find the best query index | |
| 3831 intarrayDestroy, // xDisconnect - disconnect a vtab | |
| 3832 intarrayDestroy, // xDestroy - destroy a vtab | |
| 3833 intarrayOpen, // xOpen - open a cursor | |
| 3834 intarrayClose, // xClose - close a cursor | |
| 3835 intarrayFilter, // xFilter - configure scan constraints | |
| 3836 intarrayNext, // xNext - advance a cursor | |
| 3837 intarrayEof, // xEof | |
| 3838 intarrayColumn, // xColumn - read data | |
| 3839 intarrayRowid, // xRowid - read data | |
| 3840 0, // xUpdate | |
| 3841 0, // xBegin | |
| 3842 0, // xSync | |
| 3843 0, // xCommit | |
| 3844 0, // xRollback | |
| 3845 0, // xFindMethod | |
| 3846 0, // xRename | |
| 3847 }; | |
| 3848 | |
| 3849 /// Definition of the sqlite3_chararray object (internal) | |
| 3850 struct sqlite3_chararray | |
| 3851 { | |
| 3852 int n; // Number of elements in the array | |
| 3853 char** a; // Contents of the array | |
| 3854 void (*xFree)(void*); // Function used to free a[] | |
| 3855 }; | |
| 3856 | |
| 3857 // Objects used internally by the virtual table implementation | |
| 3858 typedef struct chararray_vtab chararray_vtab; | |
| 3859 typedef struct chararray_cursor chararray_cursor; | |
| 3860 | |
| 3861 /// Definition of chararray table object (internal) | |
| 3862 struct chararray_vtab | |
| 3863 { | |
| 3864 sqlite3_vtab base; // Base class | |
| 3865 sqlite3_chararray* pContent; // Content of the char array | |
| 3866 }; | |
| 3867 | |
| 3868 /// Definition of chararray cursor object (internal) | |
| 3869 struct chararray_cursor | |
| 3870 { | |
| 3871 sqlite3_vtab_cursor base; // Base class | |
| 3872 int i; // Current cursor position | |
| 3873 }; | |
| 3874 | |
| 3875 // Free an sqlite3_chararray object. | |
| 3876 static void chararrayFree(sqlite3_chararray* p) | |
| 3877 { | |
| 3878 if (p->a != NULL && p->xFree) | |
| 3879 { | |
| 3880 int j; | |
| 3881 for (j = 0; j < p->n; ++j) | |
| 3882 { | |
| 3883 p->xFree(p->a[j]); | |
| 3884 } | |
| 3885 p->xFree(p->a); | |
| 3886 } | |
| 3887 sqlite3_free(p); | |
| 3888 } | |
| 3889 | |
| 3890 // Table destructor for the chararray module. | |
| 3891 static int chararrayDestroy(sqlite3_vtab* p) | |
| 3892 { | |
| 3893 chararray_vtab* pVtab = (chararray_vtab*)p; | |
| 3894 sqlite3_free(pVtab); | |
| 3895 return 0; | |
| 3896 } | |
| 3897 | |
| 3898 // Table constructor for the chararray module. | |
| 3899 static int chararrayCreate(sqlite3* db, // Database where module is created | |
| 3900 void* pAux, // clientdata for the module | |
| 3901 int /*argc*/, // Number of arguments | |
| 3902 const char* const* /*argv*/, // Value for all arguments | |
| 3903 sqlite3_vtab** ppVtab, // Write the new virtual table object here | |
| 3904 char** /*pzErr*/) // Put error message text here | |
| 3905 { | |
| 3906 int rc = SQLITE_NOMEM; | |
| 3907 chararray_vtab* pVtab = (chararray_vtab*) sqlite3_malloc(sizeof(chararray_vtab)); | |
| 3908 | |
| 3909 if (pVtab) | |
| 3910 { | |
| 3911 memset(pVtab, 0, sizeof(chararray_vtab)); | |
| 3912 pVtab->pContent = (sqlite3_chararray*)pAux; | |
| 3913 rc = sqlite3_declare_vtab(db, "CREATE TABLE x(value CHAR PRIMARY KEY)"); | |
| 3914 } | |
| 3915 *ppVtab = (sqlite3_vtab*)pVtab; | |
| 3916 return rc; | |
| 3917 } | |
| 3918 | |
| 3919 // Open a new cursor on the chararray table. | |
| 3920 static int chararrayOpen(sqlite3_vtab* /*pVTab*/, sqlite3_vtab_cursor** ppCursor) | |
| 3921 { | |
| 3922 int rc = SQLITE_NOMEM; | |
| 3923 chararray_cursor* pCur = (chararray_cursor*) sqlite3_malloc(sizeof(chararray_cursor)); | |
| 3924 if (pCur) | |
| 3925 { | |
| 3926 memset(pCur, 0, sizeof(chararray_cursor)); | |
| 3927 *ppCursor = (sqlite3_vtab_cursor *)pCur; | |
| 3928 rc = SQLITE_OK; | |
| 3929 } | |
| 3930 return rc; | |
| 3931 } | |
| 3932 | |
| 3933 // Close a chararray table cursor. | |
| 3934 static int chararrayClose(sqlite3_vtab_cursor* cur) | |
| 3935 { | |
| 3936 chararray_cursor* pCur = (chararray_cursor*)cur; | |
| 3937 sqlite3_free(pCur); | |
| 3938 return SQLITE_OK; | |
| 3939 } | |
| 3940 | |
| 3941 // Retrieve a column of data. | |
| 3942 static int chararrayColumn(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int /*i*/) | |
| 3943 { | |
| 3944 chararray_cursor* pCur = (chararray_cursor*)cur; | |
| 3945 chararray_vtab* pVtab = (chararray_vtab*)cur->pVtab; | |
| 3946 if (pCur->i >= 0 && pCur->i < pVtab->pContent->n) | |
| 3947 { | |
| 3948 sqlite3_result_text(ctx, pVtab->pContent->a[pCur->i], -1, SQLITE_STATIC); | |
| 3949 } | |
| 3950 return SQLITE_OK; | |
| 3951 } | |
| 3952 | |
| 3953 // Retrieve the current rowid. | |
| 3954 static int chararrayRowid(sqlite3_vtab_cursor* cur, sqlite_int64* pRowid) | |
| 3955 { | |
| 3956 chararray_cursor* pCur = (chararray_cursor*)cur; | |
| 3957 *pRowid = pCur->i; | |
| 3958 return SQLITE_OK; | |
| 3959 } | |
| 3960 | |
| 3961 static int chararrayEof(sqlite3_vtab_cursor* cur) | |
| 3962 { | |
| 3963 chararray_cursor* pCur = (chararray_cursor*)cur; | |
| 3964 chararray_vtab* pVtab = (chararray_vtab*)cur->pVtab; | |
| 3965 return pCur->i >= pVtab->pContent->n; | |
| 3966 } | |
| 3967 | |
| 3968 // Advance the cursor to the next row. | |
| 3969 static int chararrayNext(sqlite3_vtab_cursor* cur) | |
| 3970 { | |
| 3971 chararray_cursor* pCur = (chararray_cursor*)cur; | |
| 3972 pCur->i++; | |
| 3973 return SQLITE_OK; | |
| 3974 } | |
| 3975 | |
| 3976 // Reset a chararray table cursor. | |
| 3977 static int chararrayFilter(sqlite3_vtab_cursor* pVtabCursor, | |
| 3978 int /*idxNum*/, const char* /*idxStr*/, | |
| 3979 int /*argc*/, sqlite3_value** /*argv*/) | |
| 3980 { | |
| 3981 chararray_cursor *pCur = (chararray_cursor *)pVtabCursor; | |
| 3982 pCur->i = 0; | |
| 3983 return SQLITE_OK; | |
| 3984 } | |
| 3985 | |
| 3986 // Analyse the WHERE condition. | |
| 3987 static int chararrayBestIndex(sqlite3_vtab* /*tab*/, sqlite3_index_info* /*pIdxInfo*/) | |
| 3988 { | |
| 3989 return SQLITE_OK; | |
| 3990 } | |
| 3991 | |
| 3992 // Definition of a virtual table module for string collections | |
| 3993 static sqlite3_module chararrayModule = | |
| 3994 { | |
| 3995 0, // iVersion | |
| 3996 chararrayCreate, // xCreate - create a new virtual table | |
| 3997 chararrayCreate, // xConnect - connect to an existing vtab | |
| 3998 chararrayBestIndex, // xBestIndex - find the best query index | |
| 3999 chararrayDestroy, // xDisconnect - disconnect a vtab | |
| 4000 chararrayDestroy, // xDestroy - destroy a vtab | |
| 4001 chararrayOpen, // xOpen - open a cursor | |
| 4002 chararrayClose, // xClose - close a cursor | |
| 4003 chararrayFilter, // xFilter - configure scan constraints | |
| 4004 chararrayNext, // xNext - advance a cursor | |
| 4005 chararrayEof, // xEof | |
| 4006 chararrayColumn, // xColumn - read data | |
| 4007 chararrayRowid, // xRowid - read data | |
| 4008 0, // xUpdate | |
| 4009 0, // xBegin | |
| 4010 0, // xSync | |
| 4011 0, // xCommit | |
| 4012 0, // xRollback | |
| 4013 0, // xFindMethod | |
| 4014 0, // xRename | |
| 4015 }; | |
| 4016 | |
| 4017 #endif // WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 4018 | |
| 4019 wxSQLite3NamedCollection::wxSQLite3NamedCollection() | |
| 4020 { | |
| 4021 m_name = wxEmptyString; | |
| 4022 m_data = NULL; | |
| 4023 } | |
| 4024 | |
| 4025 wxSQLite3NamedCollection::wxSQLite3NamedCollection(const wxString& collectionName, void* collectionData) | |
| 4026 { | |
| 4027 m_name = collectionName; | |
| 4028 m_data = collectionData; | |
| 4029 } | |
| 4030 | |
| 4031 wxSQLite3NamedCollection::wxSQLite3NamedCollection(const wxSQLite3NamedCollection& collection) | |
| 4032 : m_name(collection.m_name), m_data(collection.m_data) | |
| 4033 { | |
| 4034 } | |
| 4035 | |
| 4036 wxSQLite3NamedCollection& | |
| 4037 wxSQLite3NamedCollection::operator=(const wxSQLite3NamedCollection& collection) | |
| 4038 { | |
| 4039 if (this != &collection) | |
| 4040 { | |
| 4041 m_name = collection.m_name; | |
| 4042 m_data = collection.m_data; | |
| 4043 } | |
| 4044 return *this; | |
| 4045 } | |
| 4046 | |
| 4047 wxSQLite3NamedCollection::~wxSQLite3NamedCollection() | |
| 4048 { | |
| 4049 } | |
| 4050 | |
| 4051 wxSQLite3IntegerCollection::wxSQLite3IntegerCollection() | |
| 4052 : wxSQLite3NamedCollection(wxEmptyString, NULL) | |
| 4053 { | |
| 4054 } | |
| 4055 | |
| 4056 wxSQLite3IntegerCollection::wxSQLite3IntegerCollection(const wxSQLite3IntegerCollection& collection) | |
| 4057 : wxSQLite3NamedCollection(collection) | |
| 4058 { | |
| 4059 } | |
| 4060 | |
| 4061 wxSQLite3IntegerCollection& | |
| 4062 wxSQLite3IntegerCollection::operator=(const wxSQLite3IntegerCollection& collection) | |
| 4063 { | |
| 4064 if (this != &collection) | |
| 4065 { | |
| 4066 wxSQLite3NamedCollection::operator=(collection); | |
| 4067 } | |
| 4068 return *this; | |
| 4069 } | |
| 4070 | |
| 4071 wxSQLite3IntegerCollection::wxSQLite3IntegerCollection(const wxString& collectionName, void* collectionData) | |
| 4072 : wxSQLite3NamedCollection(collectionName, collectionData) | |
| 4073 { | |
| 4074 } | |
| 4075 | |
| 4076 wxSQLite3IntegerCollection::~wxSQLite3IntegerCollection() | |
| 4077 { | |
| 4078 } | |
| 4079 | |
| 4080 void | |
| 4081 wxSQLite3IntegerCollection::Bind(const wxArrayInt& integerCollection) | |
| 4082 { | |
| 4083 size_t n = integerCollection.Count(); | |
| 4084 sqlite3_intarray* pIntArray = (sqlite3_intarray*) m_data; | |
| 4085 if (m_data != NULL) | |
| 4086 { | |
| 4087 if (pIntArray->a != NULL && pIntArray->xFree) | |
| 4088 { | |
| 4089 pIntArray->xFree(pIntArray->a); | |
| 4090 } | |
| 4091 } | |
| 4092 pIntArray->n = n; | |
| 4093 if (n > 0) | |
| 4094 { | |
| 4095 pIntArray->a = (sqlite3_int64*) sqlite3_malloc(sizeof(sqlite3_int64)*n); | |
| 4096 pIntArray->xFree = sqlite3_free; | |
| 4097 } | |
| 4098 else | |
| 4099 { | |
| 4100 pIntArray->a = NULL; | |
| 4101 pIntArray->xFree = NULL; | |
| 4102 } | |
| 4103 | |
| 4104 size_t j; | |
| 4105 for (j = 0; j < n; ++j) | |
| 4106 { | |
| 4107 pIntArray->a[j] = integerCollection[j]; | |
| 4108 } | |
| 4109 } | |
| 4110 | |
| 4111 void | |
| 4112 wxSQLite3IntegerCollection::Bind(int n, int* integerCollection) | |
| 4113 { | |
| 4114 sqlite3_intarray* pIntArray = (sqlite3_intarray*) m_data; | |
| 4115 if (m_data != NULL) | |
| 4116 { | |
| 4117 if (pIntArray->a != NULL && pIntArray->xFree) | |
| 4118 { | |
| 4119 pIntArray->xFree(pIntArray->a); | |
| 4120 } | |
| 4121 } | |
| 4122 pIntArray->n = n; | |
| 4123 if (n > 0) | |
| 4124 { | |
| 4125 pIntArray->a = (sqlite3_int64*) sqlite3_malloc(sizeof(sqlite3_int64)*n); | |
| 4126 pIntArray->xFree = sqlite3_free; | |
| 4127 } | |
| 4128 else | |
| 4129 { | |
| 4130 pIntArray->a = NULL; | |
| 4131 pIntArray->xFree = NULL; | |
| 4132 } | |
| 4133 | |
| 4134 int j; | |
| 4135 for (j = 0; j < n; ++j) | |
| 4136 { | |
| 4137 pIntArray->a[j] = integerCollection[j]; | |
| 4138 } | |
| 4139 } | |
| 4140 | |
| 4141 wxSQLite3IntegerCollection | |
| 4142 wxSQLite3Database::CreateIntegerCollection(const wxString& collectionName) | |
| 4143 { | |
| 4144 #if WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 4145 int rc = SQLITE_OK; | |
| 4146 wxCharBuffer strCollectionName = collectionName.ToUTF8(); | |
| 4147 const char* zName = strCollectionName; | |
| 4148 sqlite3_intarray* p = (sqlite3_intarray*) sqlite3_malloc( sizeof(*p) ); | |
| 4149 if (p == 0) | |
| 4150 { | |
| 4151 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMEM); | |
| 4152 } | |
| 4153 p->n = 0; | |
| 4154 p->a= NULL; | |
| 4155 p->xFree = NULL; | |
| 4156 rc = sqlite3_create_module_v2((sqlite3*)m_db, zName, &intarrayModule, p, (void(*)(void*))intarrayFree); | |
| 4157 if (rc == SQLITE_OK) | |
| 4158 { | |
| 4159 wxSQLite3StatementBuffer zBuffer; | |
| 4160 const char* zSql = zBuffer.Format("CREATE VIRTUAL TABLE temp.%Q USING %Q", zName, zName); | |
| 4161 rc = sqlite3_exec((sqlite3*)m_db, zSql, 0, 0, 0); | |
| 4162 } | |
| 4163 if (rc != SQLITE_OK) | |
| 4164 { | |
| 4165 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 4166 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 4167 } | |
| 4168 return wxSQLite3IntegerCollection(collectionName, p); | |
| 4169 #else | |
| 4170 wxUnusedVar(collectionName); | |
| 4171 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOCOLLECTIONS); | |
| 4172 #endif // WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 4173 } | |
| 4174 | |
| 4175 wxSQLite3StringCollection::wxSQLite3StringCollection() | |
| 4176 : wxSQLite3NamedCollection(wxEmptyString, NULL) | |
| 4177 { | |
| 4178 } | |
| 4179 | |
| 4180 wxSQLite3StringCollection::wxSQLite3StringCollection(const wxSQLite3StringCollection& collection) | |
| 4181 : wxSQLite3NamedCollection(collection) | |
| 4182 { | |
| 4183 } | |
| 4184 | |
| 4185 wxSQLite3StringCollection& | |
| 4186 wxSQLite3StringCollection::operator=(const wxSQLite3StringCollection& collection) | |
| 4187 { | |
| 4188 if (this != &collection) | |
| 4189 { | |
| 4190 wxSQLite3StringCollection::operator=(collection); | |
| 4191 } | |
| 4192 return *this; | |
| 4193 } | |
| 4194 | |
| 4195 wxSQLite3StringCollection::wxSQLite3StringCollection(const wxString& collectionName, void* collectionData) | |
| 4196 : wxSQLite3NamedCollection(collectionName, collectionData) | |
| 4197 { | |
| 4198 } | |
| 4199 | |
| 4200 wxSQLite3StringCollection::~wxSQLite3StringCollection() | |
| 4201 { | |
| 4202 } | |
| 4203 | |
| 4204 void | |
| 4205 wxSQLite3StringCollection::Bind(const wxArrayString& stringCollection) | |
| 4206 { | |
| 4207 size_t n = stringCollection.Count(); | |
| 4208 sqlite3_chararray* pCharArray = (sqlite3_chararray*) m_data; | |
| 4209 if (m_data != NULL) | |
| 4210 { | |
| 4211 if (pCharArray->a != NULL && pCharArray->xFree) | |
| 4212 { | |
| 4213 pCharArray->xFree(pCharArray->a); | |
| 4214 } | |
| 4215 } | |
| 4216 pCharArray->n = n; | |
| 4217 if (n > 0) | |
| 4218 { | |
| 4219 pCharArray->a = (char**) sqlite3_malloc(sizeof(char*)*n); | |
| 4220 pCharArray->xFree = sqlite3_free; | |
| 4221 } | |
| 4222 else | |
| 4223 { | |
| 4224 pCharArray->a = NULL; | |
| 4225 pCharArray->xFree = NULL; | |
| 4226 } | |
| 4227 | |
| 4228 size_t j; | |
| 4229 for (j = 0; j < n; ++j) | |
| 4230 { | |
| 4231 wxCharBuffer strValue = stringCollection[j].ToUTF8(); | |
| 4232 const char* zValue = strValue; | |
| 4233 size_t k = strlen(zValue) + 1; | |
| 4234 pCharArray->a[j] = (char*) sqlite3_malloc(sizeof(char)*k); | |
| 4235 strcpy(pCharArray->a[j], zValue); | |
| 4236 } | |
| 4237 } | |
| 4238 | |
| 4239 wxSQLite3StringCollection | |
| 4240 wxSQLite3Database::CreateStringCollection(const wxString& collectionName) | |
| 4241 { | |
| 4242 #if WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 4243 int rc = SQLITE_OK; | |
| 4244 wxCharBuffer strCollectionName = collectionName.ToUTF8(); | |
| 4245 const char* zName = strCollectionName; | |
| 4246 sqlite3_chararray* p = (sqlite3_chararray*) sqlite3_malloc( sizeof(*p) ); | |
| 4247 if (p == 0) | |
| 4248 { | |
| 4249 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOMEM); | |
| 4250 } | |
| 4251 p->n = 0; | |
| 4252 p->a= NULL; | |
| 4253 p->xFree = NULL; | |
| 4254 rc = sqlite3_create_module_v2((sqlite3*)m_db, zName, &chararrayModule, p, (void(*)(void*))chararrayFree); | |
| 4255 if (rc == SQLITE_OK) | |
| 4256 { | |
| 4257 wxSQLite3StatementBuffer zBuffer; | |
| 4258 const char* zSql = zBuffer.Format("CREATE VIRTUAL TABLE temp.%Q USING %Q", zName, zName); | |
| 4259 rc = sqlite3_exec((sqlite3*)m_db, zSql, 0, 0, 0); | |
| 4260 } | |
| 4261 if (rc != SQLITE_OK) | |
| 4262 { | |
| 4263 const char* localError = sqlite3_errmsg((sqlite3*) m_db); | |
| 4264 throw wxSQLite3Exception(rc, wxString::FromUTF8(localError)); | |
| 4265 } | |
| 4266 return wxSQLite3StringCollection(collectionName, p); | |
| 4267 #else | |
| 4268 wxUnusedVar(collectionName); | |
| 4269 throw wxSQLite3Exception(WXSQLITE_ERROR, wxERRMSG_NOCOLLECTIONS); | |
| 4270 #endif // WXSQLITE3_USE_NAMED_COLLECTIONS | |
| 4271 } | |
| 4272 |
