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