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