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