vtshim.c 15 KB

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