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