]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a prototype for an extension that sits in between the SQLite native code
authordrh <drh@noemail.net>
Thu, 13 Jun 2013 00:32:29 +0000 (00:32 +0000)
committerdrh <drh@noemail.net>
Thu, 13 Jun 2013 00:32:29 +0000 (00:32 +0000)
virtual table interface and a CLR IDisposable object.

FossilOrigin-Name: 10bba8d0821159a45c6a0d6c3cef897cb4d4e9a6

ext/misc/vtshim.c [new file with mode: 0644]
manifest
manifest.uuid

diff --git a/ext/misc/vtshim.c b/ext/misc/vtshim.c
new file mode 100644 (file)
index 0000000..aea7a08
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+** 2013-06-12
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** A shim that sits between the SQLite virtual table interface and
+** managed memory of .NET
+*/
+#include "sqlite3ext.h"
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/* Forward references */
+typedef struct vtshim_aux vtshim_aux;
+typedef struct vtshim_vtab vtshim_vtab;
+typedef struct vtshim_cursor vtshim_cursor;
+
+
+/* The vtshim_aux argument is the auxiliary parameter that is passed
+** into sqlite3_create_module_v2().
+*/
+struct vtshim_aux {
+  void *pChildAux;              /* pAux for child virtual tables */
+  void (*xChildDestroy)(void*); /* Destructor for pChildAux */
+  const sqlite3_module *pMod;   /* Methods for child virtual tables */
+  sqlite3 *db;                  /* The database to which we are attached */
+  const char *zName;            /* Name of the module */
+  int bDisposed;                /* True if disposed */
+  vtshim_vtab *pAllVtab;        /* List of all vtshim_vtab objects */
+  sqlite3_module sSelf;         /* Methods used by this shim */
+};
+
+/* A vtshim virtual table object */
+struct vtshim_vtab {
+  sqlite3_vtab base;       /* Base class - must be first */
+  sqlite3_vtab *pChild;    /* Child virtual table */
+  vtshim_aux *pAux;        /* Pointer to vtshim_aux object */
+  vtshim_cursor *pAllCur;  /* List of all cursors */
+  vtshim_vtab **ppPrev;    /* Previous on list */
+  vtshim_vtab *pNext;      /* Next on list */
+};
+
+/* A vtshim cursor object */
+struct vtshim_cursor {
+  sqlite3_vtab_cursor base;    /* Base class - must be first */
+  sqlite3_vtab_cursor *pChild; /* Cursor generated by the managed subclass */
+  vtshim_cursor **ppPrev;      /* Previous on list of all cursors */
+  vtshim_cursor *pNext;        /* Next on list of all cursors */
+};
+
+/* Methods for the vtshim module */
+static int vtshimCreate(
+  sqlite3 *db,
+  void *pPAux,
+  int argc, const char *const*argv,
+  sqlite3_vtab **ppVtab,
+  char **pzErr
+){
+  vtshim_aux *pAux = (vtshim_aux*)pPAux;
+  vtshim_vtab *pNew;
+  int rc; 
+
+  assert( db==pAux->db );
+  pNew = sqlite3_malloc( sizeof(*pNew) );
+  *ppVtab = (sqlite3_vtab*)pNew;
+  if( pNew==0 ) return SQLITE_NOMEM;
+  memset(pNew, 0, sizeof(*pNew));
+  rc = pAux->pMod->xCreate(db, pAux->pChildAux, argc, argv,
+                           &pNew->pChild, pzErr);
+  if( rc ){
+    sqlite3_free(pNew);
+    *ppVtab = 0;
+  }
+  pNew->ppPrev = &pAux->pAllVtab;
+  pNew->pNext = pAux->pAllVtab;
+  if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext;
+  pAux->pAllVtab = pNew;
+  return rc;
+}
+
+static int vtshimConnect(
+  sqlite3 *db,
+  void *pPAux,
+  int argc, const char *const*argv,
+  sqlite3_vtab **ppVtab,
+  char **pzErr
+){
+  vtshim_aux *pAux = (vtshim_aux*)pPAux;
+  vtshim_vtab *pNew;
+  int rc; 
+
+  assert( db==pAux->db );
+  pNew = sqlite3_malloc( sizeof(*pNew) );
+  *ppVtab = (sqlite3_vtab*)pNew;
+  if( pNew==0 ) return SQLITE_NOMEM;
+  memset(pNew, 0, sizeof(*pNew));
+  rc = pAux->pMod->xConnect(db, pAux->pChildAux, argc, argv,
+                            &pNew->pChild, pzErr);
+  if( rc ){
+    sqlite3_free(pNew);
+    *ppVtab = 0;
+  }
+  pNew->ppPrev = &pAux->pAllVtab;
+  pNew->pNext = pAux->pAllVtab;
+  if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext;
+  pAux->pAllVtab = pNew;
+  return rc;
+}
+
+static int vtshimBestIndex(
+  sqlite3_vtab *pBase,
+  sqlite3_index_info *pIdxInfo
+){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xBestIndex(pVtab->pChild, pIdxInfo);
+}
+
+
+static int vtshimDisconnect(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  int rc = SQLITE_OK;
+  if( !pAux->bDisposed ){
+    rc = pAux->pMod->xDisconnect(pVtab->pChild);
+  }
+  if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev;
+  *pVtab->ppPrev = pVtab->pNext;
+  sqlite3_free(pVtab);
+  return rc;
+}
+
+static int vtshimDestroy(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  int rc = SQLITE_OK;
+  if( !pAux->bDisposed ){
+    rc = pAux->pMod->xDestroy(pVtab->pChild);
+  }
+  if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev;
+  *pVtab->ppPrev = pVtab->pNext;
+  sqlite3_free(pVtab);
+  return rc;
+}
+
+static int vtshimOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  vtshim_cursor *pCur;
+  int rc;
+  *ppCursor = 0;
+  if( pAux->bDisposed )  return SQLITE_ERROR;
+  pCur = sqlite3_malloc( sizeof(*pCur) );
+  if( pCur==0 ) return SQLITE_NOMEM;
+  memset(pCur, 0, sizeof(*pCur));
+  rc = pAux->pMod->xOpen(pVtab->pChild, &pCur->pChild);
+  if( rc ){
+    sqlite3_free(pCur);
+    return rc;
+  }
+  pCur->pChild->pVtab = pVtab->pChild;
+  *ppCursor = &pCur->base;
+  pCur->ppPrev = &pVtab->pAllCur;
+  if( pVtab->pAllCur ) pVtab->pAllCur->ppPrev = &pCur->pNext;
+  pCur->pNext = pVtab->pAllCur;
+  pVtab->pAllCur = pCur;
+  return SQLITE_OK;
+}
+
+static int vtshimClose(sqlite3_vtab_cursor *pX){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  int rc = SQLITE_OK;
+  if( !pAux->bDisposed ){
+    rc = pAux->pMod->xClose(pCur->pChild);
+  }
+  if( pCur->pNext ) pCur->pNext->ppPrev = pCur->ppPrev;
+  *pCur->ppPrev = pCur->pNext;
+  sqlite3_free(pCur);
+  return rc;
+}
+
+static int vtshimFilter(
+  sqlite3_vtab_cursor *pX,
+  int idxNum, const char *idxStr,
+  int argc, sqlite3_value **argv
+){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xFilter(pCur->pChild, idxNum, idxStr, argc, argv);
+}
+
+static int vtshimNext(sqlite3_vtab_cursor *pX){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xNext(pCur->pChild);
+}
+
+static int vtshimEof(sqlite3_vtab_cursor *pX){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xEof(pCur->pChild);
+}
+
+static int vtshimColumn(sqlite3_vtab_cursor *pX, sqlite3_context *ctx, int i){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xColumn(pCur->pChild, ctx, i);
+}
+
+static int vtshimRowid(sqlite3_vtab_cursor *pX, sqlite3_int64 *pRowid){
+  vtshim_cursor *pCur = (vtshim_cursor*)pX;
+  vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xRowid(pCur->pChild, pRowid);
+}
+
+static int vtshimUpdate(
+  sqlite3_vtab *pBase,
+  int argc,
+  sqlite3_value **argv,
+  sqlite3_int64 *pRowid
+){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xUpdate(pVtab->pChild, argc, argv, pRowid);
+}
+
+static int vtshimBegin(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xBegin(pVtab->pChild);
+}
+
+static int vtshimSync(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xSync(pVtab->pChild);
+}
+
+static int vtshimCommit(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xCommit(pVtab->pChild);
+}
+
+static int vtshimRollback(sqlite3_vtab *pBase){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xRollback(pVtab->pChild);
+}
+
+static int vtshimFindFunction(
+  sqlite3_vtab *pBase,
+  int nArg,
+  const char *zName,
+  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+  void **ppArg
+){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xFindFunction(pVtab->pChild, nArg, zName, pxFunc, ppArg);
+}
+
+static int vtshimRename(sqlite3_vtab *pBase, const char *zNewName){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xRename(pVtab->pChild, zNewName);
+}
+
+static int vtshimSavepoint(sqlite3_vtab *pBase, int n){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xSavepoint(pVtab->pChild, n);
+}
+
+static int vtshimRelease(sqlite3_vtab *pBase, int n){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xRelease(pVtab->pChild, n);
+}
+
+static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){
+  vtshim_vtab *pVtab = (vtshim_vtab*)pBase;
+  vtshim_aux *pAux = pVtab->pAux;
+  if( pAux->bDisposed ) return SQLITE_ERROR;
+  return pAux->pMod->xRollbackTo(pVtab->pChild, n);
+}
+
+/* The destructor function for a disposible module */
+static void vtshimAuxDestructor(void *pXAux){
+  vtshim_aux *pAux = (vtshim_aux*)pXAux;
+  assert( pAux->pAllVtab==0 );
+  if( !pAux->bDisposed && pAux->xChildDestroy ){
+    pAux->xChildDestroy(pAux->pChildAux);
+  }
+  sqlite3_free(pAux);
+}
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void *sqlite3_create_disposable_module(
+  sqlite3 *db,               /* SQLite connection to register module with */
+  const char *zName,         /* Name of the module */
+  const sqlite3_module *p,   /* Methods for the module */
+  void *pClientData,         /* Client data for xCreate/xConnect */
+  void(*xDestroy)(void*)     /* Module destructor function */
+){
+  vtshim_aux *pAux;
+  int rc;
+  pAux = sqlite3_malloc( sizeof(*pAux) );
+  if( pAux==0 ){
+    if( xDestroy ) xDestroy(pClientData);
+    return 0;
+  }
+  pAux->pChildAux = pClientData;
+  pAux->xChildDestroy = xDestroy;
+  pAux->pMod = p;
+  pAux->db = db;
+  pAux->zName = zName;
+  pAux->bDisposed = 0;
+  pAux->pAllVtab = 0;
+  pAux->sSelf.iVersion = p->iVersion<=1 ? p->iVersion : 1;
+  pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0;
+  pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0;
+  pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0;
+  pAux->sSelf.xDisconnect = p->xDisconnect ? vtshimDisconnect : 0;
+  pAux->sSelf.xDestroy = p->xDestroy ? vtshimDestroy : 0;
+  pAux->sSelf.xOpen = p->xOpen ? vtshimOpen : 0;
+  pAux->sSelf.xClose = p->xClose ? vtshimClose : 0;
+  pAux->sSelf.xFilter = p->xFilter ? vtshimFilter : 0;
+  pAux->sSelf.xNext = p->xNext ? vtshimNext : 0;
+  pAux->sSelf.xEof = p->xEof ? vtshimEof : 0;
+  pAux->sSelf.xColumn = p->xColumn ? vtshimColumn : 0;
+  pAux->sSelf.xRowid = p->xRowid ? vtshimRowid : 0;
+  pAux->sSelf.xUpdate = p->xUpdate ? vtshimUpdate : 0;
+  pAux->sSelf.xBegin = p->xBegin ? vtshimBegin : 0;
+  pAux->sSelf.xSync = p->xSync ? vtshimSync : 0;
+  pAux->sSelf.xCommit = p->xCommit ? vtshimCommit : 0;
+  pAux->sSelf.xRollback = p->xRollback ? vtshimRollback : 0;
+  pAux->sSelf.xFindFunction = p->xFindFunction ? vtshimFindFunction : 0;
+  pAux->sSelf.xRename = p->xRename ? vtshimRename : 0;
+  if( p->iVersion>=1 ){
+    pAux->sSelf.xSavepoint = p->xSavepoint ? vtshimSavepoint : 0;
+    pAux->sSelf.xRelease = p->xRelease ? vtshimRelease : 0;
+    pAux->sSelf.xRollbackTo = p->xRollbackTo ? vtshimRollbackTo : 0;
+  }else{
+    pAux->sSelf.xSavepoint = 0;
+    pAux->sSelf.xRelease = 0;
+    pAux->sSelf.xRollbackTo = 0;
+  }
+  rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf,
+                                pAux, vtshimAuxDestructor);
+  return rc==SQLITE_OK ? (void*)pAux : 0;
+}
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+void sqlite3_dispose_module(void *pX){
+  vtshim_aux *pAux = (vtshim_aux*)pX;
+  if( !pAux->bDisposed ){
+    vtshim_vtab *pVtab;
+    vtshim_cursor *pCur;
+    for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){
+      for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){
+        pAux->pMod->xClose(pCur->pChild);
+      }
+      pAux->pMod->xDisconnect(pVtab->pChild);
+    }
+    pAux->bDisposed = 1;
+    if( pAux->xChildDestroy ) pAux->xChildDestroy(pAux->pChildAux);
+  }
+}
+
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_vtshim_init(
+  sqlite3 *db, 
+  char **pzErrMsg, 
+  const sqlite3_api_routines *pApi
+){
+  SQLITE_EXTENSION_INIT2(pApi);
+  return SQLITE_OK;
+}
index b3d0bc075d766ce35e9b05ce652b0964a2d1cc1a..56a52aafa816587a077cfcf350b5d23f6badffda 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Activate\sthe\sone-pass\soptimization.\s\sUpdate\scomments,\sespecially\sthe\ndescriptions\sof\sthe\svarious\sobjects.
-D 2013-06-12T20:18:16.225
+C Add\sa\sprototype\sfor\san\sextension\sthat\ssits\sin\sbetween\sthe\sSQLite\snative\scode\nvirtual\stable\sinterface\sand\sa\sCLR\sIDisposable\sobject.
+D 2013-06-13T00:32:29.814
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -115,6 +115,7 @@ F ext/misc/percentile.c 4fb5e46c4312b0be74e8e497ac18f805f0e3e6c5
 F ext/misc/regexp.c c25c65fe775f5d9801fb8573e36ebe73f2c0c2e0
 F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
 F ext/misc/spellfix.c 6d7ce6105a4b7729f6c44ccdf1ab7e80d9707c02
+F ext/misc/vtshim.c 43a4f04d932f558a1d99c9ec275463e66dd14dfc
 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
 F ext/rtree/rtree.c 757abea591d4ff67c0ff4e8f9776aeda86b18c14
@@ -1095,7 +1096,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/wherecosttest.c 4d0393bdbe7230adb712e925863744dd2b7ffc5b
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 25c0f7292a20c0db6ef176966d9987f29c7d73e5
-R abdb63c5ef041b9c2f729e7a4c7abdae
+P e120c558a5bafc0f0d2cc12ee5c9d36e20cc642d
+R cebd45a542cce51f8d9efaf858e2a635
+T *branch * disposable-vtable
+T *sym-disposable-vtable *
+T -sym-nextgen-query-plan-exp *
 U drh
-Z 9e2bd249132b4bdcba34d19dbfd465f2
+Z 5aa82f98e9ac53c787753e9130a0c71d
index f1e38ab6d5cad32d42ee7760182cbdc160298b70..22caf63f4e441a156dcc1154777f43ee591d1e06 100644 (file)
@@ -1 +1 @@
-e120c558a5bafc0f0d2cc12ee5c9d36e20cc642d
\ No newline at end of file
+10bba8d0821159a45c6a0d6c3cef897cb4d4e9a6
\ No newline at end of file