OLD | NEW |
| (Empty) |
1 /* | |
2 ** 2013-06-12 | |
3 ** | |
4 ** The author disclaims copyright to this source code. In place of | |
5 ** a legal notice, here is a blessing: | |
6 ** | |
7 ** May you do good and not evil. | |
8 ** May you find forgiveness for yourself and forgive others. | |
9 ** May you share freely, never taking more than you give. | |
10 ** | |
11 ************************************************************************* | |
12 ** | |
13 ** A shim that sits between the SQLite virtual table interface and | |
14 ** runtimes with garbage collector based memory management. | |
15 */ | |
16 #include "sqlite3ext.h" | |
17 SQLITE_EXTENSION_INIT1 | |
18 #include <assert.h> | |
19 #include <string.h> | |
20 | |
21 #ifndef SQLITE_OMIT_VIRTUALTABLE | |
22 | |
23 /* Forward references */ | |
24 typedef struct vtshim_aux vtshim_aux; | |
25 typedef struct vtshim_vtab vtshim_vtab; | |
26 typedef struct vtshim_cursor vtshim_cursor; | |
27 | |
28 | |
29 /* The vtshim_aux argument is the auxiliary parameter that is passed | |
30 ** into sqlite3_create_module_v2(). | |
31 */ | |
32 struct vtshim_aux { | |
33 void *pChildAux; /* pAux for child virtual tables */ | |
34 void (*xChildDestroy)(void*); /* Destructor for pChildAux */ | |
35 sqlite3_module *pMod; /* Methods for child virtual tables */ | |
36 sqlite3 *db; /* The database to which we are attached */ | |
37 char *zName; /* Name of the module */ | |
38 int bDisposed; /* True if disposed */ | |
39 vtshim_vtab *pAllVtab; /* List of all vtshim_vtab objects */ | |
40 sqlite3_module sSelf; /* Methods used by this shim */ | |
41 }; | |
42 | |
43 /* A vtshim virtual table object */ | |
44 struct vtshim_vtab { | |
45 sqlite3_vtab base; /* Base class - must be first */ | |
46 sqlite3_vtab *pChild; /* Child virtual table */ | |
47 vtshim_aux *pAux; /* Pointer to vtshim_aux object */ | |
48 vtshim_cursor *pAllCur; /* List of all cursors */ | |
49 vtshim_vtab **ppPrev; /* Previous on list */ | |
50 vtshim_vtab *pNext; /* Next on list */ | |
51 }; | |
52 | |
53 /* A vtshim cursor object */ | |
54 struct vtshim_cursor { | |
55 sqlite3_vtab_cursor base; /* Base class - must be first */ | |
56 sqlite3_vtab_cursor *pChild; /* Cursor generated by the managed subclass */ | |
57 vtshim_cursor **ppPrev; /* Previous on list of all cursors */ | |
58 vtshim_cursor *pNext; /* Next on list of all cursors */ | |
59 }; | |
60 | |
61 /* Macro used to copy the child vtable error message to outer vtable */ | |
62 #define VTSHIM_COPY_ERRMSG() \ | |
63 do { \ | |
64 sqlite3_free(pVtab->base.zErrMsg); \ | |
65 pVtab->base.zErrMsg = sqlite3_mprintf("%s", pVtab->pChild->zErrMsg); \ | |
66 } while (0) | |
67 | |
68 /* Methods for the vtshim module */ | |
69 static int vtshimCreate( | |
70 sqlite3 *db, | |
71 void *ppAux, | |
72 int argc, | |
73 const char *const*argv, | |
74 sqlite3_vtab **ppVtab, | |
75 char **pzErr | |
76 ){ | |
77 vtshim_aux *pAux = (vtshim_aux*)ppAux; | |
78 vtshim_vtab *pNew; | |
79 int rc; | |
80 | |
81 assert( db==pAux->db ); | |
82 if( pAux->bDisposed ){ | |
83 if( pzErr ){ | |
84 *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"", | |
85 pAux->zName); | |
86 } | |
87 return SQLITE_ERROR; | |
88 } | |
89 pNew = sqlite3_malloc( sizeof(*pNew) ); | |
90 *ppVtab = (sqlite3_vtab*)pNew; | |
91 if( pNew==0 ) return SQLITE_NOMEM; | |
92 memset(pNew, 0, sizeof(*pNew)); | |
93 rc = pAux->pMod->xCreate(db, pAux->pChildAux, argc, argv, | |
94 &pNew->pChild, pzErr); | |
95 if( rc ){ | |
96 sqlite3_free(pNew); | |
97 *ppVtab = 0; | |
98 } | |
99 pNew->pAux = pAux; | |
100 pNew->ppPrev = &pAux->pAllVtab; | |
101 pNew->pNext = pAux->pAllVtab; | |
102 if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; | |
103 pAux->pAllVtab = pNew; | |
104 return rc; | |
105 } | |
106 | |
107 static int vtshimConnect( | |
108 sqlite3 *db, | |
109 void *ppAux, | |
110 int argc, | |
111 const char *const*argv, | |
112 sqlite3_vtab **ppVtab, | |
113 char **pzErr | |
114 ){ | |
115 vtshim_aux *pAux = (vtshim_aux*)ppAux; | |
116 vtshim_vtab *pNew; | |
117 int rc; | |
118 | |
119 assert( db==pAux->db ); | |
120 if( pAux->bDisposed ){ | |
121 if( pzErr ){ | |
122 *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"", | |
123 pAux->zName); | |
124 } | |
125 return SQLITE_ERROR; | |
126 } | |
127 pNew = sqlite3_malloc( sizeof(*pNew) ); | |
128 *ppVtab = (sqlite3_vtab*)pNew; | |
129 if( pNew==0 ) return SQLITE_NOMEM; | |
130 memset(pNew, 0, sizeof(*pNew)); | |
131 rc = pAux->pMod->xConnect(db, pAux->pChildAux, argc, argv, | |
132 &pNew->pChild, pzErr); | |
133 if( rc ){ | |
134 sqlite3_free(pNew); | |
135 *ppVtab = 0; | |
136 } | |
137 pNew->pAux = pAux; | |
138 pNew->ppPrev = &pAux->pAllVtab; | |
139 pNew->pNext = pAux->pAllVtab; | |
140 if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; | |
141 pAux->pAllVtab = pNew; | |
142 return rc; | |
143 } | |
144 | |
145 static int vtshimBestIndex( | |
146 sqlite3_vtab *pBase, | |
147 sqlite3_index_info *pIdxInfo | |
148 ){ | |
149 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
150 vtshim_aux *pAux = pVtab->pAux; | |
151 int rc; | |
152 if( pAux->bDisposed ) return SQLITE_ERROR; | |
153 rc = pAux->pMod->xBestIndex(pVtab->pChild, pIdxInfo); | |
154 if( rc!=SQLITE_OK ){ | |
155 VTSHIM_COPY_ERRMSG(); | |
156 } | |
157 return rc; | |
158 } | |
159 | |
160 static int vtshimDisconnect(sqlite3_vtab *pBase){ | |
161 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
162 vtshim_aux *pAux = pVtab->pAux; | |
163 int rc = SQLITE_OK; | |
164 if( !pAux->bDisposed ){ | |
165 rc = pAux->pMod->xDisconnect(pVtab->pChild); | |
166 } | |
167 if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; | |
168 *pVtab->ppPrev = pVtab->pNext; | |
169 sqlite3_free(pVtab); | |
170 return rc; | |
171 } | |
172 | |
173 static int vtshimDestroy(sqlite3_vtab *pBase){ | |
174 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
175 vtshim_aux *pAux = pVtab->pAux; | |
176 int rc = SQLITE_OK; | |
177 if( !pAux->bDisposed ){ | |
178 rc = pAux->pMod->xDestroy(pVtab->pChild); | |
179 } | |
180 if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; | |
181 *pVtab->ppPrev = pVtab->pNext; | |
182 sqlite3_free(pVtab); | |
183 return rc; | |
184 } | |
185 | |
186 static int vtshimOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor){ | |
187 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
188 vtshim_aux *pAux = pVtab->pAux; | |
189 vtshim_cursor *pCur; | |
190 int rc; | |
191 *ppCursor = 0; | |
192 if( pAux->bDisposed ) return SQLITE_ERROR; | |
193 pCur = sqlite3_malloc( sizeof(*pCur) ); | |
194 if( pCur==0 ) return SQLITE_NOMEM; | |
195 memset(pCur, 0, sizeof(*pCur)); | |
196 rc = pAux->pMod->xOpen(pVtab->pChild, &pCur->pChild); | |
197 if( rc ){ | |
198 sqlite3_free(pCur); | |
199 VTSHIM_COPY_ERRMSG(); | |
200 return rc; | |
201 } | |
202 pCur->pChild->pVtab = pVtab->pChild; | |
203 *ppCursor = &pCur->base; | |
204 pCur->ppPrev = &pVtab->pAllCur; | |
205 if( pVtab->pAllCur ) pVtab->pAllCur->ppPrev = &pCur->pNext; | |
206 pCur->pNext = pVtab->pAllCur; | |
207 pVtab->pAllCur = pCur; | |
208 return SQLITE_OK; | |
209 } | |
210 | |
211 static int vtshimClose(sqlite3_vtab_cursor *pX){ | |
212 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
213 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
214 vtshim_aux *pAux = pVtab->pAux; | |
215 int rc = SQLITE_OK; | |
216 if( !pAux->bDisposed ){ | |
217 rc = pAux->pMod->xClose(pCur->pChild); | |
218 if( rc!=SQLITE_OK ){ | |
219 VTSHIM_COPY_ERRMSG(); | |
220 } | |
221 } | |
222 if( pCur->pNext ) pCur->pNext->ppPrev = pCur->ppPrev; | |
223 *pCur->ppPrev = pCur->pNext; | |
224 sqlite3_free(pCur); | |
225 return rc; | |
226 } | |
227 | |
228 static int vtshimFilter( | |
229 sqlite3_vtab_cursor *pX, | |
230 int idxNum, | |
231 const char *idxStr, | |
232 int argc, | |
233 sqlite3_value **argv | |
234 ){ | |
235 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
236 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
237 vtshim_aux *pAux = pVtab->pAux; | |
238 int rc; | |
239 if( pAux->bDisposed ) return SQLITE_ERROR; | |
240 rc = pAux->pMod->xFilter(pCur->pChild, idxNum, idxStr, argc, argv); | |
241 if( rc!=SQLITE_OK ){ | |
242 VTSHIM_COPY_ERRMSG(); | |
243 } | |
244 return rc; | |
245 } | |
246 | |
247 static int vtshimNext(sqlite3_vtab_cursor *pX){ | |
248 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
249 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
250 vtshim_aux *pAux = pVtab->pAux; | |
251 int rc; | |
252 if( pAux->bDisposed ) return SQLITE_ERROR; | |
253 rc = pAux->pMod->xNext(pCur->pChild); | |
254 if( rc!=SQLITE_OK ){ | |
255 VTSHIM_COPY_ERRMSG(); | |
256 } | |
257 return rc; | |
258 } | |
259 | |
260 static int vtshimEof(sqlite3_vtab_cursor *pX){ | |
261 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
262 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
263 vtshim_aux *pAux = pVtab->pAux; | |
264 int rc; | |
265 if( pAux->bDisposed ) return 1; | |
266 rc = pAux->pMod->xEof(pCur->pChild); | |
267 VTSHIM_COPY_ERRMSG(); | |
268 return rc; | |
269 } | |
270 | |
271 static int vtshimColumn(sqlite3_vtab_cursor *pX, sqlite3_context *ctx, int i){ | |
272 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
273 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
274 vtshim_aux *pAux = pVtab->pAux; | |
275 int rc; | |
276 if( pAux->bDisposed ) return SQLITE_ERROR; | |
277 rc = pAux->pMod->xColumn(pCur->pChild, ctx, i); | |
278 if( rc!=SQLITE_OK ){ | |
279 VTSHIM_COPY_ERRMSG(); | |
280 } | |
281 return rc; | |
282 } | |
283 | |
284 static int vtshimRowid(sqlite3_vtab_cursor *pX, sqlite3_int64 *pRowid){ | |
285 vtshim_cursor *pCur = (vtshim_cursor*)pX; | |
286 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; | |
287 vtshim_aux *pAux = pVtab->pAux; | |
288 int rc; | |
289 if( pAux->bDisposed ) return SQLITE_ERROR; | |
290 rc = pAux->pMod->xRowid(pCur->pChild, pRowid); | |
291 if( rc!=SQLITE_OK ){ | |
292 VTSHIM_COPY_ERRMSG(); | |
293 } | |
294 return rc; | |
295 } | |
296 | |
297 static int vtshimUpdate( | |
298 sqlite3_vtab *pBase, | |
299 int argc, | |
300 sqlite3_value **argv, | |
301 sqlite3_int64 *pRowid | |
302 ){ | |
303 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
304 vtshim_aux *pAux = pVtab->pAux; | |
305 int rc; | |
306 if( pAux->bDisposed ) return SQLITE_ERROR; | |
307 rc = pAux->pMod->xUpdate(pVtab->pChild, argc, argv, pRowid); | |
308 if( rc!=SQLITE_OK ){ | |
309 VTSHIM_COPY_ERRMSG(); | |
310 } | |
311 return rc; | |
312 } | |
313 | |
314 static int vtshimBegin(sqlite3_vtab *pBase){ | |
315 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
316 vtshim_aux *pAux = pVtab->pAux; | |
317 int rc; | |
318 if( pAux->bDisposed ) return SQLITE_ERROR; | |
319 rc = pAux->pMod->xBegin(pVtab->pChild); | |
320 if( rc!=SQLITE_OK ){ | |
321 VTSHIM_COPY_ERRMSG(); | |
322 } | |
323 return rc; | |
324 } | |
325 | |
326 static int vtshimSync(sqlite3_vtab *pBase){ | |
327 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
328 vtshim_aux *pAux = pVtab->pAux; | |
329 int rc; | |
330 if( pAux->bDisposed ) return SQLITE_ERROR; | |
331 rc = pAux->pMod->xSync(pVtab->pChild); | |
332 if( rc!=SQLITE_OK ){ | |
333 VTSHIM_COPY_ERRMSG(); | |
334 } | |
335 return rc; | |
336 } | |
337 | |
338 static int vtshimCommit(sqlite3_vtab *pBase){ | |
339 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
340 vtshim_aux *pAux = pVtab->pAux; | |
341 int rc; | |
342 if( pAux->bDisposed ) return SQLITE_ERROR; | |
343 rc = pAux->pMod->xCommit(pVtab->pChild); | |
344 if( rc!=SQLITE_OK ){ | |
345 VTSHIM_COPY_ERRMSG(); | |
346 } | |
347 return rc; | |
348 } | |
349 | |
350 static int vtshimRollback(sqlite3_vtab *pBase){ | |
351 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
352 vtshim_aux *pAux = pVtab->pAux; | |
353 int rc; | |
354 if( pAux->bDisposed ) return SQLITE_ERROR; | |
355 rc = pAux->pMod->xRollback(pVtab->pChild); | |
356 if( rc!=SQLITE_OK ){ | |
357 VTSHIM_COPY_ERRMSG(); | |
358 } | |
359 return rc; | |
360 } | |
361 | |
362 static int vtshimFindFunction( | |
363 sqlite3_vtab *pBase, | |
364 int nArg, | |
365 const char *zName, | |
366 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), | |
367 void **ppArg | |
368 ){ | |
369 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
370 vtshim_aux *pAux = pVtab->pAux; | |
371 int rc; | |
372 if( pAux->bDisposed ) return 0; | |
373 rc = pAux->pMod->xFindFunction(pVtab->pChild, nArg, zName, pxFunc, ppArg); | |
374 VTSHIM_COPY_ERRMSG(); | |
375 return rc; | |
376 } | |
377 | |
378 static int vtshimRename(sqlite3_vtab *pBase, const char *zNewName){ | |
379 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
380 vtshim_aux *pAux = pVtab->pAux; | |
381 int rc; | |
382 if( pAux->bDisposed ) return SQLITE_ERROR; | |
383 rc = pAux->pMod->xRename(pVtab->pChild, zNewName); | |
384 if( rc!=SQLITE_OK ){ | |
385 VTSHIM_COPY_ERRMSG(); | |
386 } | |
387 return rc; | |
388 } | |
389 | |
390 static int vtshimSavepoint(sqlite3_vtab *pBase, int n){ | |
391 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
392 vtshim_aux *pAux = pVtab->pAux; | |
393 int rc; | |
394 if( pAux->bDisposed ) return SQLITE_ERROR; | |
395 rc = pAux->pMod->xSavepoint(pVtab->pChild, n); | |
396 if( rc!=SQLITE_OK ){ | |
397 VTSHIM_COPY_ERRMSG(); | |
398 } | |
399 return rc; | |
400 } | |
401 | |
402 static int vtshimRelease(sqlite3_vtab *pBase, int n){ | |
403 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
404 vtshim_aux *pAux = pVtab->pAux; | |
405 int rc; | |
406 if( pAux->bDisposed ) return SQLITE_ERROR; | |
407 rc = pAux->pMod->xRelease(pVtab->pChild, n); | |
408 if( rc!=SQLITE_OK ){ | |
409 VTSHIM_COPY_ERRMSG(); | |
410 } | |
411 return rc; | |
412 } | |
413 | |
414 static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){ | |
415 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; | |
416 vtshim_aux *pAux = pVtab->pAux; | |
417 int rc; | |
418 if( pAux->bDisposed ) return SQLITE_ERROR; | |
419 rc = pAux->pMod->xRollbackTo(pVtab->pChild, n); | |
420 if( rc!=SQLITE_OK ){ | |
421 VTSHIM_COPY_ERRMSG(); | |
422 } | |
423 return rc; | |
424 } | |
425 | |
426 /* The destructor function for a disposible module */ | |
427 static void vtshimAuxDestructor(void *pXAux){ | |
428 vtshim_aux *pAux = (vtshim_aux*)pXAux; | |
429 assert( pAux->pAllVtab==0 ); | |
430 if( !pAux->bDisposed && pAux->xChildDestroy ){ | |
431 pAux->xChildDestroy(pAux->pChildAux); | |
432 pAux->xChildDestroy = 0; | |
433 } | |
434 sqlite3_free(pAux->zName); | |
435 sqlite3_free(pAux->pMod); | |
436 sqlite3_free(pAux); | |
437 } | |
438 | |
439 static int vtshimCopyModule( | |
440 const sqlite3_module *pMod, /* Source module to be copied */ | |
441 sqlite3_module **ppMod /* Destination for copied module */ | |
442 ){ | |
443 sqlite3_module *p; | |
444 if( !pMod || !ppMod ) return SQLITE_ERROR; | |
445 p = sqlite3_malloc( sizeof(*p) ); | |
446 if( p==0 ) return SQLITE_NOMEM; | |
447 memcpy(p, pMod, sizeof(*p)); | |
448 *ppMod = p; | |
449 return SQLITE_OK; | |
450 } | |
451 | |
452 #ifdef _WIN32 | |
453 __declspec(dllexport) | |
454 #endif | |
455 void *sqlite3_create_disposable_module( | |
456 sqlite3 *db, /* SQLite connection to register module with */ | |
457 const char *zName, /* Name of the module */ | |
458 const sqlite3_module *p, /* Methods for the module */ | |
459 void *pClientData, /* Client data for xCreate/xConnect */ | |
460 void(*xDestroy)(void*) /* Module destructor function */ | |
461 ){ | |
462 vtshim_aux *pAux; | |
463 sqlite3_module *pMod; | |
464 int rc; | |
465 pAux = sqlite3_malloc( sizeof(*pAux) ); | |
466 if( pAux==0 ){ | |
467 if( xDestroy ) xDestroy(pClientData); | |
468 return 0; | |
469 } | |
470 rc = vtshimCopyModule(p, &pMod); | |
471 if( rc!=SQLITE_OK ){ | |
472 sqlite3_free(pAux); | |
473 return 0; | |
474 } | |
475 pAux->pChildAux = pClientData; | |
476 pAux->xChildDestroy = xDestroy; | |
477 pAux->pMod = pMod; | |
478 pAux->db = db; | |
479 pAux->zName = sqlite3_mprintf("%s", zName); | |
480 pAux->bDisposed = 0; | |
481 pAux->pAllVtab = 0; | |
482 pAux->sSelf.iVersion = p->iVersion<=2 ? p->iVersion : 2; | |
483 pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0; | |
484 pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0; | |
485 pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0; | |
486 pAux->sSelf.xDisconnect = p->xDisconnect ? vtshimDisconnect : 0; | |
487 pAux->sSelf.xDestroy = p->xDestroy ? vtshimDestroy : 0; | |
488 pAux->sSelf.xOpen = p->xOpen ? vtshimOpen : 0; | |
489 pAux->sSelf.xClose = p->xClose ? vtshimClose : 0; | |
490 pAux->sSelf.xFilter = p->xFilter ? vtshimFilter : 0; | |
491 pAux->sSelf.xNext = p->xNext ? vtshimNext : 0; | |
492 pAux->sSelf.xEof = p->xEof ? vtshimEof : 0; | |
493 pAux->sSelf.xColumn = p->xColumn ? vtshimColumn : 0; | |
494 pAux->sSelf.xRowid = p->xRowid ? vtshimRowid : 0; | |
495 pAux->sSelf.xUpdate = p->xUpdate ? vtshimUpdate : 0; | |
496 pAux->sSelf.xBegin = p->xBegin ? vtshimBegin : 0; | |
497 pAux->sSelf.xSync = p->xSync ? vtshimSync : 0; | |
498 pAux->sSelf.xCommit = p->xCommit ? vtshimCommit : 0; | |
499 pAux->sSelf.xRollback = p->xRollback ? vtshimRollback : 0; | |
500 pAux->sSelf.xFindFunction = p->xFindFunction ? vtshimFindFunction : 0; | |
501 pAux->sSelf.xRename = p->xRename ? vtshimRename : 0; | |
502 if( p->iVersion>=2 ){ | |
503 pAux->sSelf.xSavepoint = p->xSavepoint ? vtshimSavepoint : 0; | |
504 pAux->sSelf.xRelease = p->xRelease ? vtshimRelease : 0; | |
505 pAux->sSelf.xRollbackTo = p->xRollbackTo ? vtshimRollbackTo : 0; | |
506 }else{ | |
507 pAux->sSelf.xSavepoint = 0; | |
508 pAux->sSelf.xRelease = 0; | |
509 pAux->sSelf.xRollbackTo = 0; | |
510 } | |
511 rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf, | |
512 pAux, vtshimAuxDestructor); | |
513 return rc==SQLITE_OK ? (void*)pAux : 0; | |
514 } | |
515 | |
516 #ifdef _WIN32 | |
517 __declspec(dllexport) | |
518 #endif | |
519 void sqlite3_dispose_module(void *pX){ | |
520 vtshim_aux *pAux = (vtshim_aux*)pX; | |
521 if( !pAux->bDisposed ){ | |
522 vtshim_vtab *pVtab; | |
523 vtshim_cursor *pCur; | |
524 for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){ | |
525 for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){ | |
526 pAux->pMod->xClose(pCur->pChild); | |
527 } | |
528 pAux->pMod->xDisconnect(pVtab->pChild); | |
529 } | |
530 pAux->bDisposed = 1; | |
531 if( pAux->xChildDestroy ){ | |
532 pAux->xChildDestroy(pAux->pChildAux); | |
533 pAux->xChildDestroy = 0; | |
534 } | |
535 } | |
536 } | |
537 | |
538 | |
539 #endif /* SQLITE_OMIT_VIRTUALTABLE */ | |
540 | |
541 #ifdef _WIN32 | |
542 __declspec(dllexport) | |
543 #endif | |
544 int sqlite3_vtshim_init( | |
545 sqlite3 *db, | |
546 char **pzErrMsg, | |
547 const sqlite3_api_routines *pApi | |
548 ){ | |
549 SQLITE_EXTENSION_INIT2(pApi); | |
550 return SQLITE_OK; | |
551 } | |
OLD | NEW |