modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/vtshim.c (about)

     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  }