aboutsummaryrefslogtreecommitdiff
path: root/vtable.c
diff options
context:
space:
mode:
authormattn <mattn.jp@gmail.com>2017-03-05 20:44:09 +0900
committerGitHub <noreply@github.com>2017-03-05 20:44:09 +0900
commit55cd56d7edb233f4a251a8821232e4cc6084e3d2 (patch)
tree6c075e6971ff66ff98a6c6e8e31f5509de68aeb6 /vtable.c
parentfix test (diff)
parent[vtable] Rename Context to SQLiteContext (diff)
downloadgolite-55cd56d7edb233f4a251a8821232e4cc6084e3d2.tar.gz
golite-55cd56d7edb233f4a251a8821232e4cc6084e3d2.tar.xz
Merge pull request #347 from DataDog/dd/vtable
Add Go API for virtual tables
Diffstat (limited to 'vtable.c')
-rw-r--r--vtable.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/vtable.c b/vtable.c
new file mode 100644
index 0000000..e1d7575
--- /dev/null
+++ b/vtable.c
@@ -0,0 +1,182 @@
+// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
+//
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file.
+
+#ifndef USE_LIBSQLITE3
+#include <sqlite3-binding.h>
+#else
+#include <sqlite3.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "_cgo_export.h"
+
+
+typedef struct goVTab goVTab;
+
+struct goVTab {
+ sqlite3_vtab base;
+ void *vTab;
+};
+
+static int cXInit(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr, int isCreate) {
+ void *vTab = (void *)goMInit(db, pAux, argc, (char**)argv, pzErr, isCreate);
+ if (!vTab || *pzErr) {
+ return SQLITE_ERROR;
+ }
+ goVTab *pvTab = (goVTab *)sqlite3_malloc(sizeof(goVTab));
+ if (!pvTab) {
+ *pzErr = sqlite3_mprintf("%s", "Out of memory");
+ return SQLITE_NOMEM;
+ }
+ memset(pvTab, 0, sizeof(goVTab));
+ pvTab->vTab = vTab;
+
+ *ppVTab = (sqlite3_vtab *)pvTab;
+ *pzErr = 0;
+ return SQLITE_OK;
+}
+
+static inline int cXCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
+ return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 1);
+}
+static inline int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
+ return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 0);
+}
+
+static inline int cXBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *info) {
+ char *pzErr = goVBestIndex(((goVTab*)pVTab)->vTab, info);
+ if (pzErr) {
+ if (pVTab->zErrMsg)
+ sqlite3_free(pVTab->zErrMsg);
+ pVTab->zErrMsg = pzErr;
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+static int cXRelease(sqlite3_vtab *pVTab, int isDestroy) {
+ char *pzErr = goVRelease(((goVTab*)pVTab)->vTab, isDestroy);
+ if (pzErr) {
+ if (pVTab->zErrMsg)
+ sqlite3_free(pVTab->zErrMsg);
+ pVTab->zErrMsg = pzErr;
+ return SQLITE_ERROR;
+ }
+ if (pVTab->zErrMsg)
+ sqlite3_free(pVTab->zErrMsg);
+ sqlite3_free(pVTab);
+ return SQLITE_OK;
+}
+
+static inline int cXDisconnect(sqlite3_vtab *pVTab) {
+ return cXRelease(pVTab, 0);
+}
+static inline int cXDestroy(sqlite3_vtab *pVTab) {
+ return cXRelease(pVTab, 1);
+}
+
+typedef struct goVTabCursor goVTabCursor;
+
+struct goVTabCursor {
+ sqlite3_vtab_cursor base;
+ void *vTabCursor;
+};
+
+static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
+ void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
+ goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
+ if (!pCursor) {
+ return SQLITE_NOMEM;
+ }
+ memset(pCursor, 0, sizeof(goVTabCursor));
+ pCursor->vTabCursor = vTabCursor;
+ *ppCursor = (sqlite3_vtab_cursor *)pCursor;
+ return SQLITE_OK;
+}
+
+static int setErrMsg(sqlite3_vtab_cursor *pCursor, char *pzErr) {
+ if (pCursor->pVtab->zErrMsg)
+ sqlite3_free(pCursor->pVtab->zErrMsg);
+ pCursor->pVtab->zErrMsg = pzErr;
+ return SQLITE_ERROR;
+}
+
+static int cXClose(sqlite3_vtab_cursor *pCursor) {
+ char *pzErr = goVClose(((goVTabCursor*)pCursor)->vTabCursor);
+ if (pzErr) {
+ return setErrMsg(pCursor, pzErr);
+ }
+ sqlite3_free(pCursor);
+ return SQLITE_OK;
+}
+
+static int cXFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
+ char *pzErr = goVFilter(((goVTabCursor*)pCursor)->vTabCursor, idxNum, (char*)idxStr, argc, argv);
+ if (pzErr) {
+ return setErrMsg(pCursor, pzErr);
+ }
+ return SQLITE_OK;
+}
+
+static int cXNext(sqlite3_vtab_cursor *pCursor) {
+ char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
+ if (pzErr) {
+ return setErrMsg(pCursor, pzErr);
+ }
+ return SQLITE_OK;
+}
+
+static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
+ return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
+}
+
+static int cXColumn(sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i) {
+ char *pzErr = goVColumn(((goVTabCursor*)pCursor)->vTabCursor, ctx, i);
+ if (pzErr) {
+ return setErrMsg(pCursor, pzErr);
+ }
+ return SQLITE_OK;
+}
+
+static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
+ char *pzErr = goVRowid(((goVTabCursor*)pCursor)->vTabCursor, pRowid);
+ if (pzErr) {
+ return setErrMsg(pCursor, pzErr);
+ }
+ return SQLITE_OK;
+}
+
+static sqlite3_module goModule = {
+ 0, /* iVersion */
+ cXCreate, /* xCreate - create a table */
+ cXConnect, /* xConnect - connect to an existing table */
+ cXBestIndex, /* xBestIndex - Determine search strategy */
+ cXDisconnect, /* xDisconnect - Disconnect from a table */
+ cXDestroy, /* xDestroy - Drop a table */
+ cXOpen, /* xOpen - open a cursor */
+ cXClose, /* xClose - close a cursor */
+ cXFilter, /* xFilter - configure scan constraints */
+ cXNext, /* xNext - advance a cursor */
+ cXEof, /* xEof */
+ cXColumn, /* xColumn - read data */
+ cXRowid, /* xRowid - read data */
+// Not implemented
+ 0, /* xUpdate - write data */
+ 0, /* xBegin - begin transaction */
+ 0, /* xSync - sync transaction */
+ 0, /* xCommit - commit transaction */
+ 0, /* xRollback - rollback transaction */
+ 0, /* xFindFunction - function overloading */
+ 0, /* xRename - rename the table */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+
+
+int goSqlite3CreateModule(sqlite3 *db, const char *zName, uintptr_t pClientData) {
+ return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
+} \ No newline at end of file