forked from mirror/go-sqlite3
refactoring
This commit is contained in:
parent
d5ce94296e
commit
32ab0d8730
|
@ -431,7 +431,7 @@ func (c *SQLiteConn) exec(ctx context.Context, query string, args []namedValue)
|
||||||
na := s.NumInput()
|
na := s.NumInput()
|
||||||
if len(args) < na {
|
if len(args) < na {
|
||||||
s.Close()
|
s.Close()
|
||||||
return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
|
return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
|
||||||
}
|
}
|
||||||
for i := 0; i < na; i++ {
|
for i := 0; i < na; i++ {
|
||||||
args[i].Ordinal -= start
|
args[i].Ordinal -= start
|
||||||
|
@ -481,7 +481,7 @@ func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue)
|
||||||
s.(*SQLiteStmt).cls = true
|
s.(*SQLiteStmt).cls = true
|
||||||
na := s.NumInput()
|
na := s.NumInput()
|
||||||
if len(args) < na {
|
if len(args) < na {
|
||||||
return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
|
return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
|
||||||
}
|
}
|
||||||
for i := 0; i < na; i++ {
|
for i := 0; i < na; i++ {
|
||||||
args[i].Ordinal -= start
|
args[i].Ordinal -= start
|
||||||
|
|
|
@ -20,11 +20,198 @@ package sqlite3
|
||||||
#endif
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
int goSqlite3CreateModule(sqlite3 *db, const char *zName, uintptr_t pClientData);
|
static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
|
||||||
|
return sqlite3_mprintf(zFormat, arg);
|
||||||
|
}
|
||||||
|
|
||||||
static inline char *my_mprintf(char *zFormat, char *arg) {
|
typedef struct goVTab goVTab;
|
||||||
return sqlite3_mprintf(zFormat, arg);
|
|
||||||
|
struct goVTab {
|
||||||
|
sqlite3_vtab base;
|
||||||
|
void *vTab;
|
||||||
|
};
|
||||||
|
|
||||||
|
uintptr_t goMInit(void *db, void *pAux, int argc, char **argv, char **pzErr, int isCreate);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVBestIndex(void *pVTab, void *icp);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVRelease(void *pVTab, int isDestroy);
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
uintptr_t goVOpen(void *pVTab, char **pzErr);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVClose(void *pCursor);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVFilter(void *pCursor, int idxNum, char* idxName, int argc, sqlite3_value **argv);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVNext(void *pCursor);
|
||||||
|
|
||||||
|
static int cXNext(sqlite3_vtab_cursor *pCursor) {
|
||||||
|
char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
|
||||||
|
if (pzErr) {
|
||||||
|
return setErrMsg(pCursor, pzErr);
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int goVEof(void *pCursor);
|
||||||
|
|
||||||
|
static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
|
||||||
|
return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVColumn(void *pCursor, void *cp, int col);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* goVRowid(void *pCursor, sqlite3_int64 *pRowid);
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
void goMDestroy(void*);
|
||||||
|
|
||||||
|
static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
|
||||||
|
return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
@ -136,11 +323,11 @@ func mPrintf(format, arg string) *C.char {
|
||||||
defer C.free(unsafe.Pointer(cf))
|
defer C.free(unsafe.Pointer(cf))
|
||||||
ca := C.CString(arg)
|
ca := C.CString(arg)
|
||||||
defer C.free(unsafe.Pointer(ca))
|
defer C.free(unsafe.Pointer(ca))
|
||||||
return C.my_mprintf(cf, ca)
|
return C._sqlite3_mprintf(cf, ca)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export goMInit
|
//export goMInit
|
||||||
func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.char, isCreate int) C.uintptr_t {
|
func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
|
||||||
m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
|
m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
|
||||||
if m.c.db != (*C.sqlite3)(db) {
|
if m.c.db != (*C.sqlite3)(db) {
|
||||||
*pzErr = mPrintf("%s", "Inconsistent db handles")
|
*pzErr = mPrintf("%s", "Inconsistent db handles")
|
||||||
|
@ -148,7 +335,7 @@ func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.
|
||||||
}
|
}
|
||||||
args := make([]string, argc)
|
args := make([]string, argc)
|
||||||
var A []*C.char
|
var A []*C.char
|
||||||
slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: argc, Cap: argc}
|
slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
|
||||||
a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
|
a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
|
||||||
for i, s := range a.([]*C.char) {
|
for i, s := range a.([]*C.char) {
|
||||||
args[i] = C.GoString(s)
|
args[i] = C.GoString(s)
|
||||||
|
@ -171,7 +358,7 @@ func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.
|
||||||
}
|
}
|
||||||
|
|
||||||
//export goVRelease
|
//export goVRelease
|
||||||
func goVRelease(pVTab unsafe.Pointer, isDestroy int) *C.char {
|
func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
|
||||||
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
|
||||||
var err error
|
var err error
|
||||||
if isDestroy == 1 {
|
if isDestroy == 1 {
|
||||||
|
@ -254,7 +441,7 @@ func goMDestroy(pClientData unsafe.Pointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export goVFilter
|
//export goVFilter
|
||||||
func goVFilter(pCursor unsafe.Pointer, idxNum int, idxName *C.char, argc int, argv **C.sqlite3_value) *C.char {
|
func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
||||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
|
||||||
vals := make([]interface{}, 0, argc)
|
vals := make([]interface{}, 0, argc)
|
||||||
|
@ -265,7 +452,7 @@ func goVFilter(pCursor unsafe.Pointer, idxNum int, idxName *C.char, argc int, ar
|
||||||
}
|
}
|
||||||
vals = append(vals, conv.Interface())
|
vals = append(vals, conv.Interface())
|
||||||
}
|
}
|
||||||
err := vtc.vTabCursor.Filter(idxNum, C.GoString(idxName), vals)
|
err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mPrintf("%s", err.Error())
|
return mPrintf("%s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -293,10 +480,10 @@ func goVEof(pCursor unsafe.Pointer) C.int {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export goVColumn
|
//export goVColumn
|
||||||
func goVColumn(pCursor, cp unsafe.Pointer, col int) *C.char {
|
func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
|
||||||
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
|
||||||
c := (*SQLiteContext)(cp)
|
c := (*SQLiteContext)(cp)
|
||||||
err := vtc.vTabCursor.Column(c, col)
|
err := vtc.vTabCursor.Column(c, int(col))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mPrintf("%s", err.Error())
|
return mPrintf("%s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -373,7 +560,7 @@ func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
|
||||||
mname := C.CString(moduleName)
|
mname := C.CString(moduleName)
|
||||||
defer C.free(unsafe.Pointer(mname))
|
defer C.free(unsafe.Pointer(mname))
|
||||||
udm := sqliteModule{c, moduleName, module}
|
udm := sqliteModule{c, moduleName, module}
|
||||||
rv := C.goSqlite3CreateModule(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
|
rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
|
||||||
if rv != C.SQLITE_OK {
|
if rv != C.SQLITE_OK {
|
||||||
return c.lastError()
|
return c.lastError()
|
||||||
}
|
}
|
|
@ -133,7 +133,7 @@ func TestCreateModule(t *testing.T) {
|
||||||
}
|
}
|
||||||
_, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)")
|
_, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("could not create vtable: %v", err)
|
t.Fatalf("could not create vtable: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var i, value int
|
var i, value int
|
182
vtable.c
182
vtable.c
|
@ -1,182 +0,0 @@
|
||||||
// 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);
|
|
||||||
}
|
|
Loading…
Reference in New Issue