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 return rc; |
| 99 } |
| 100 pNew->pAux = pAux; |
| 101 pNew->ppPrev = &pAux->pAllVtab; |
| 102 pNew->pNext = pAux->pAllVtab; |
| 103 if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; |
| 104 pAux->pAllVtab = pNew; |
| 105 return rc; |
| 106 } |
| 107 |
| 108 static int vtshimConnect( |
| 109 sqlite3 *db, |
| 110 void *ppAux, |
| 111 int argc, |
| 112 const char *const*argv, |
| 113 sqlite3_vtab **ppVtab, |
| 114 char **pzErr |
| 115 ){ |
| 116 vtshim_aux *pAux = (vtshim_aux*)ppAux; |
| 117 vtshim_vtab *pNew; |
| 118 int rc; |
| 119 |
| 120 assert( db==pAux->db ); |
| 121 if( pAux->bDisposed ){ |
| 122 if( pzErr ){ |
| 123 *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"", |
| 124 pAux->zName); |
| 125 } |
| 126 return SQLITE_ERROR; |
| 127 } |
| 128 pNew = sqlite3_malloc( sizeof(*pNew) ); |
| 129 *ppVtab = (sqlite3_vtab*)pNew; |
| 130 if( pNew==0 ) return SQLITE_NOMEM; |
| 131 memset(pNew, 0, sizeof(*pNew)); |
| 132 rc = pAux->pMod->xConnect(db, pAux->pChildAux, argc, argv, |
| 133 &pNew->pChild, pzErr); |
| 134 if( rc ){ |
| 135 sqlite3_free(pNew); |
| 136 *ppVtab = 0; |
| 137 return rc; |
| 138 } |
| 139 pNew->pAux = pAux; |
| 140 pNew->ppPrev = &pAux->pAllVtab; |
| 141 pNew->pNext = pAux->pAllVtab; |
| 142 if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; |
| 143 pAux->pAllVtab = pNew; |
| 144 return rc; |
| 145 } |
| 146 |
| 147 static int vtshimBestIndex( |
| 148 sqlite3_vtab *pBase, |
| 149 sqlite3_index_info *pIdxInfo |
| 150 ){ |
| 151 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 152 vtshim_aux *pAux = pVtab->pAux; |
| 153 int rc; |
| 154 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 155 rc = pAux->pMod->xBestIndex(pVtab->pChild, pIdxInfo); |
| 156 if( rc!=SQLITE_OK ){ |
| 157 VTSHIM_COPY_ERRMSG(); |
| 158 } |
| 159 return rc; |
| 160 } |
| 161 |
| 162 static int vtshimDisconnect(sqlite3_vtab *pBase){ |
| 163 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 164 vtshim_aux *pAux = pVtab->pAux; |
| 165 int rc = SQLITE_OK; |
| 166 if( !pAux->bDisposed ){ |
| 167 rc = pAux->pMod->xDisconnect(pVtab->pChild); |
| 168 } |
| 169 if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; |
| 170 *pVtab->ppPrev = pVtab->pNext; |
| 171 sqlite3_free(pVtab); |
| 172 return rc; |
| 173 } |
| 174 |
| 175 static int vtshimDestroy(sqlite3_vtab *pBase){ |
| 176 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 177 vtshim_aux *pAux = pVtab->pAux; |
| 178 int rc = SQLITE_OK; |
| 179 if( !pAux->bDisposed ){ |
| 180 rc = pAux->pMod->xDestroy(pVtab->pChild); |
| 181 } |
| 182 if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; |
| 183 *pVtab->ppPrev = pVtab->pNext; |
| 184 sqlite3_free(pVtab); |
| 185 return rc; |
| 186 } |
| 187 |
| 188 static int vtshimOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor){ |
| 189 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 190 vtshim_aux *pAux = pVtab->pAux; |
| 191 vtshim_cursor *pCur; |
| 192 int rc; |
| 193 *ppCursor = 0; |
| 194 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 195 pCur = sqlite3_malloc( sizeof(*pCur) ); |
| 196 if( pCur==0 ) return SQLITE_NOMEM; |
| 197 memset(pCur, 0, sizeof(*pCur)); |
| 198 rc = pAux->pMod->xOpen(pVtab->pChild, &pCur->pChild); |
| 199 if( rc ){ |
| 200 sqlite3_free(pCur); |
| 201 VTSHIM_COPY_ERRMSG(); |
| 202 return rc; |
| 203 } |
| 204 pCur->pChild->pVtab = pVtab->pChild; |
| 205 *ppCursor = &pCur->base; |
| 206 pCur->ppPrev = &pVtab->pAllCur; |
| 207 if( pVtab->pAllCur ) pVtab->pAllCur->ppPrev = &pCur->pNext; |
| 208 pCur->pNext = pVtab->pAllCur; |
| 209 pVtab->pAllCur = pCur; |
| 210 return SQLITE_OK; |
| 211 } |
| 212 |
| 213 static int vtshimClose(sqlite3_vtab_cursor *pX){ |
| 214 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 215 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 216 vtshim_aux *pAux = pVtab->pAux; |
| 217 int rc = SQLITE_OK; |
| 218 if( !pAux->bDisposed ){ |
| 219 rc = pAux->pMod->xClose(pCur->pChild); |
| 220 if( rc!=SQLITE_OK ){ |
| 221 VTSHIM_COPY_ERRMSG(); |
| 222 } |
| 223 } |
| 224 if( pCur->pNext ) pCur->pNext->ppPrev = pCur->ppPrev; |
| 225 *pCur->ppPrev = pCur->pNext; |
| 226 sqlite3_free(pCur); |
| 227 return rc; |
| 228 } |
| 229 |
| 230 static int vtshimFilter( |
| 231 sqlite3_vtab_cursor *pX, |
| 232 int idxNum, |
| 233 const char *idxStr, |
| 234 int argc, |
| 235 sqlite3_value **argv |
| 236 ){ |
| 237 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 238 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 239 vtshim_aux *pAux = pVtab->pAux; |
| 240 int rc; |
| 241 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 242 rc = pAux->pMod->xFilter(pCur->pChild, idxNum, idxStr, argc, argv); |
| 243 if( rc!=SQLITE_OK ){ |
| 244 VTSHIM_COPY_ERRMSG(); |
| 245 } |
| 246 return rc; |
| 247 } |
| 248 |
| 249 static int vtshimNext(sqlite3_vtab_cursor *pX){ |
| 250 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 251 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 252 vtshim_aux *pAux = pVtab->pAux; |
| 253 int rc; |
| 254 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 255 rc = pAux->pMod->xNext(pCur->pChild); |
| 256 if( rc!=SQLITE_OK ){ |
| 257 VTSHIM_COPY_ERRMSG(); |
| 258 } |
| 259 return rc; |
| 260 } |
| 261 |
| 262 static int vtshimEof(sqlite3_vtab_cursor *pX){ |
| 263 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 264 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 265 vtshim_aux *pAux = pVtab->pAux; |
| 266 int rc; |
| 267 if( pAux->bDisposed ) return 1; |
| 268 rc = pAux->pMod->xEof(pCur->pChild); |
| 269 VTSHIM_COPY_ERRMSG(); |
| 270 return rc; |
| 271 } |
| 272 |
| 273 static int vtshimColumn(sqlite3_vtab_cursor *pX, sqlite3_context *ctx, int i){ |
| 274 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 275 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 276 vtshim_aux *pAux = pVtab->pAux; |
| 277 int rc; |
| 278 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 279 rc = pAux->pMod->xColumn(pCur->pChild, ctx, i); |
| 280 if( rc!=SQLITE_OK ){ |
| 281 VTSHIM_COPY_ERRMSG(); |
| 282 } |
| 283 return rc; |
| 284 } |
| 285 |
| 286 static int vtshimRowid(sqlite3_vtab_cursor *pX, sqlite3_int64 *pRowid){ |
| 287 vtshim_cursor *pCur = (vtshim_cursor*)pX; |
| 288 vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; |
| 289 vtshim_aux *pAux = pVtab->pAux; |
| 290 int rc; |
| 291 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 292 rc = pAux->pMod->xRowid(pCur->pChild, pRowid); |
| 293 if( rc!=SQLITE_OK ){ |
| 294 VTSHIM_COPY_ERRMSG(); |
| 295 } |
| 296 return rc; |
| 297 } |
| 298 |
| 299 static int vtshimUpdate( |
| 300 sqlite3_vtab *pBase, |
| 301 int argc, |
| 302 sqlite3_value **argv, |
| 303 sqlite3_int64 *pRowid |
| 304 ){ |
| 305 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 306 vtshim_aux *pAux = pVtab->pAux; |
| 307 int rc; |
| 308 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 309 rc = pAux->pMod->xUpdate(pVtab->pChild, argc, argv, pRowid); |
| 310 if( rc!=SQLITE_OK ){ |
| 311 VTSHIM_COPY_ERRMSG(); |
| 312 } |
| 313 return rc; |
| 314 } |
| 315 |
| 316 static int vtshimBegin(sqlite3_vtab *pBase){ |
| 317 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 318 vtshim_aux *pAux = pVtab->pAux; |
| 319 int rc; |
| 320 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 321 rc = pAux->pMod->xBegin(pVtab->pChild); |
| 322 if( rc!=SQLITE_OK ){ |
| 323 VTSHIM_COPY_ERRMSG(); |
| 324 } |
| 325 return rc; |
| 326 } |
| 327 |
| 328 static int vtshimSync(sqlite3_vtab *pBase){ |
| 329 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 330 vtshim_aux *pAux = pVtab->pAux; |
| 331 int rc; |
| 332 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 333 rc = pAux->pMod->xSync(pVtab->pChild); |
| 334 if( rc!=SQLITE_OK ){ |
| 335 VTSHIM_COPY_ERRMSG(); |
| 336 } |
| 337 return rc; |
| 338 } |
| 339 |
| 340 static int vtshimCommit(sqlite3_vtab *pBase){ |
| 341 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 342 vtshim_aux *pAux = pVtab->pAux; |
| 343 int rc; |
| 344 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 345 rc = pAux->pMod->xCommit(pVtab->pChild); |
| 346 if( rc!=SQLITE_OK ){ |
| 347 VTSHIM_COPY_ERRMSG(); |
| 348 } |
| 349 return rc; |
| 350 } |
| 351 |
| 352 static int vtshimRollback(sqlite3_vtab *pBase){ |
| 353 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 354 vtshim_aux *pAux = pVtab->pAux; |
| 355 int rc; |
| 356 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 357 rc = pAux->pMod->xRollback(pVtab->pChild); |
| 358 if( rc!=SQLITE_OK ){ |
| 359 VTSHIM_COPY_ERRMSG(); |
| 360 } |
| 361 return rc; |
| 362 } |
| 363 |
| 364 static int vtshimFindFunction( |
| 365 sqlite3_vtab *pBase, |
| 366 int nArg, |
| 367 const char *zName, |
| 368 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), |
| 369 void **ppArg |
| 370 ){ |
| 371 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 372 vtshim_aux *pAux = pVtab->pAux; |
| 373 int rc; |
| 374 if( pAux->bDisposed ) return 0; |
| 375 rc = pAux->pMod->xFindFunction(pVtab->pChild, nArg, zName, pxFunc, ppArg); |
| 376 VTSHIM_COPY_ERRMSG(); |
| 377 return rc; |
| 378 } |
| 379 |
| 380 static int vtshimRename(sqlite3_vtab *pBase, const char *zNewName){ |
| 381 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 382 vtshim_aux *pAux = pVtab->pAux; |
| 383 int rc; |
| 384 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 385 rc = pAux->pMod->xRename(pVtab->pChild, zNewName); |
| 386 if( rc!=SQLITE_OK ){ |
| 387 VTSHIM_COPY_ERRMSG(); |
| 388 } |
| 389 return rc; |
| 390 } |
| 391 |
| 392 static int vtshimSavepoint(sqlite3_vtab *pBase, int n){ |
| 393 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 394 vtshim_aux *pAux = pVtab->pAux; |
| 395 int rc; |
| 396 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 397 rc = pAux->pMod->xSavepoint(pVtab->pChild, n); |
| 398 if( rc!=SQLITE_OK ){ |
| 399 VTSHIM_COPY_ERRMSG(); |
| 400 } |
| 401 return rc; |
| 402 } |
| 403 |
| 404 static int vtshimRelease(sqlite3_vtab *pBase, int n){ |
| 405 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 406 vtshim_aux *pAux = pVtab->pAux; |
| 407 int rc; |
| 408 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 409 rc = pAux->pMod->xRelease(pVtab->pChild, n); |
| 410 if( rc!=SQLITE_OK ){ |
| 411 VTSHIM_COPY_ERRMSG(); |
| 412 } |
| 413 return rc; |
| 414 } |
| 415 |
| 416 static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){ |
| 417 vtshim_vtab *pVtab = (vtshim_vtab*)pBase; |
| 418 vtshim_aux *pAux = pVtab->pAux; |
| 419 int rc; |
| 420 if( pAux->bDisposed ) return SQLITE_ERROR; |
| 421 rc = pAux->pMod->xRollbackTo(pVtab->pChild, n); |
| 422 if( rc!=SQLITE_OK ){ |
| 423 VTSHIM_COPY_ERRMSG(); |
| 424 } |
| 425 return rc; |
| 426 } |
| 427 |
| 428 /* The destructor function for a disposible module */ |
| 429 static void vtshimAuxDestructor(void *pXAux){ |
| 430 vtshim_aux *pAux = (vtshim_aux*)pXAux; |
| 431 assert( pAux->pAllVtab==0 ); |
| 432 if( !pAux->bDisposed && pAux->xChildDestroy ){ |
| 433 pAux->xChildDestroy(pAux->pChildAux); |
| 434 pAux->xChildDestroy = 0; |
| 435 } |
| 436 sqlite3_free(pAux->zName); |
| 437 sqlite3_free(pAux->pMod); |
| 438 sqlite3_free(pAux); |
| 439 } |
| 440 |
| 441 static int vtshimCopyModule( |
| 442 const sqlite3_module *pMod, /* Source module to be copied */ |
| 443 sqlite3_module **ppMod /* Destination for copied module */ |
| 444 ){ |
| 445 sqlite3_module *p; |
| 446 if( !pMod || !ppMod ) return SQLITE_ERROR; |
| 447 p = sqlite3_malloc( sizeof(*p) ); |
| 448 if( p==0 ) return SQLITE_NOMEM; |
| 449 memcpy(p, pMod, sizeof(*p)); |
| 450 *ppMod = p; |
| 451 return SQLITE_OK; |
| 452 } |
| 453 |
| 454 #ifdef _WIN32 |
| 455 __declspec(dllexport) |
| 456 #endif |
| 457 void *sqlite3_create_disposable_module( |
| 458 sqlite3 *db, /* SQLite connection to register module with */ |
| 459 const char *zName, /* Name of the module */ |
| 460 const sqlite3_module *p, /* Methods for the module */ |
| 461 void *pClientData, /* Client data for xCreate/xConnect */ |
| 462 void(*xDestroy)(void*) /* Module destructor function */ |
| 463 ){ |
| 464 vtshim_aux *pAux; |
| 465 sqlite3_module *pMod; |
| 466 int rc; |
| 467 pAux = sqlite3_malloc( sizeof(*pAux) ); |
| 468 if( pAux==0 ){ |
| 469 if( xDestroy ) xDestroy(pClientData); |
| 470 return 0; |
| 471 } |
| 472 rc = vtshimCopyModule(p, &pMod); |
| 473 if( rc!=SQLITE_OK ){ |
| 474 sqlite3_free(pAux); |
| 475 return 0; |
| 476 } |
| 477 pAux->pChildAux = pClientData; |
| 478 pAux->xChildDestroy = xDestroy; |
| 479 pAux->pMod = pMod; |
| 480 pAux->db = db; |
| 481 pAux->zName = sqlite3_mprintf("%s", zName); |
| 482 pAux->bDisposed = 0; |
| 483 pAux->pAllVtab = 0; |
| 484 pAux->sSelf.iVersion = p->iVersion<=2 ? p->iVersion : 2; |
| 485 pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0; |
| 486 pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0; |
| 487 pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0; |
| 488 pAux->sSelf.xDisconnect = p->xDisconnect ? vtshimDisconnect : 0; |
| 489 pAux->sSelf.xDestroy = p->xDestroy ? vtshimDestroy : 0; |
| 490 pAux->sSelf.xOpen = p->xOpen ? vtshimOpen : 0; |
| 491 pAux->sSelf.xClose = p->xClose ? vtshimClose : 0; |
| 492 pAux->sSelf.xFilter = p->xFilter ? vtshimFilter : 0; |
| 493 pAux->sSelf.xNext = p->xNext ? vtshimNext : 0; |
| 494 pAux->sSelf.xEof = p->xEof ? vtshimEof : 0; |
| 495 pAux->sSelf.xColumn = p->xColumn ? vtshimColumn : 0; |
| 496 pAux->sSelf.xRowid = p->xRowid ? vtshimRowid : 0; |
| 497 pAux->sSelf.xUpdate = p->xUpdate ? vtshimUpdate : 0; |
| 498 pAux->sSelf.xBegin = p->xBegin ? vtshimBegin : 0; |
| 499 pAux->sSelf.xSync = p->xSync ? vtshimSync : 0; |
| 500 pAux->sSelf.xCommit = p->xCommit ? vtshimCommit : 0; |
| 501 pAux->sSelf.xRollback = p->xRollback ? vtshimRollback : 0; |
| 502 pAux->sSelf.xFindFunction = p->xFindFunction ? vtshimFindFunction : 0; |
| 503 pAux->sSelf.xRename = p->xRename ? vtshimRename : 0; |
| 504 if( p->iVersion>=2 ){ |
| 505 pAux->sSelf.xSavepoint = p->xSavepoint ? vtshimSavepoint : 0; |
| 506 pAux->sSelf.xRelease = p->xRelease ? vtshimRelease : 0; |
| 507 pAux->sSelf.xRollbackTo = p->xRollbackTo ? vtshimRollbackTo : 0; |
| 508 }else{ |
| 509 pAux->sSelf.xSavepoint = 0; |
| 510 pAux->sSelf.xRelease = 0; |
| 511 pAux->sSelf.xRollbackTo = 0; |
| 512 } |
| 513 rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf, |
| 514 pAux, vtshimAuxDestructor); |
| 515 return rc==SQLITE_OK ? (void*)pAux : 0; |
| 516 } |
| 517 |
| 518 #ifdef _WIN32 |
| 519 __declspec(dllexport) |
| 520 #endif |
| 521 void sqlite3_dispose_module(void *pX){ |
| 522 vtshim_aux *pAux = (vtshim_aux*)pX; |
| 523 if( !pAux->bDisposed ){ |
| 524 vtshim_vtab *pVtab; |
| 525 vtshim_cursor *pCur; |
| 526 for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){ |
| 527 for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){ |
| 528 pAux->pMod->xClose(pCur->pChild); |
| 529 } |
| 530 pAux->pMod->xDisconnect(pVtab->pChild); |
| 531 } |
| 532 pAux->bDisposed = 1; |
| 533 if( pAux->xChildDestroy ){ |
| 534 pAux->xChildDestroy(pAux->pChildAux); |
| 535 pAux->xChildDestroy = 0; |
| 536 } |
| 537 } |
| 538 } |
| 539 |
| 540 |
| 541 #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
| 542 |
| 543 #ifdef _WIN32 |
| 544 __declspec(dllexport) |
| 545 #endif |
| 546 int sqlite3_vtshim_init( |
| 547 sqlite3 *db, |
| 548 char **pzErrMsg, |
| 549 const sqlite3_api_routines *pApi |
| 550 ){ |
| 551 SQLITE_EXTENSION_INIT2(pApi); |
| 552 return SQLITE_OK; |
| 553 } |
OLD | NEW |