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