1
0

vtshim.c 15 KB

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