forked from mirror/go-sqlcipher
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()
|
||||
if len(args) < na {
|
||||
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++ {
|
||||
args[i].Ordinal -= start
|
||||
|
@ -481,7 +481,7 @@ func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue)
|
|||
s.(*SQLiteStmt).cls = true
|
||||
na := s.NumInput()
|
||||
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++ {
|
||||
args[i].Ordinal -= start
|
||||
|
|
|
@ -20,12 +20,199 @@ package sqlite3
|
|||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
|
||||
int goSqlite3CreateModule(sqlite3 *db, const char *zName, uintptr_t pClientData);
|
||||
|
||||
static inline char *my_mprintf(char *zFormat, char *arg) {
|
||||
static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
|
||||
return sqlite3_mprintf(zFormat, arg);
|
||||
}
|
||||
|
||||
typedef struct goVTab goVTab;
|
||||
|
||||
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"
|
||||
|
||||
|
@ -136,11 +323,11 @@ func mPrintf(format, arg string) *C.char {
|
|||
defer C.free(unsafe.Pointer(cf))
|
||||
ca := C.CString(arg)
|
||||
defer C.free(unsafe.Pointer(ca))
|
||||
return C.my_mprintf(cf, ca)
|
||||
return C._sqlite3_mprintf(cf, ca)
|
||||
}
|
||||
|
||||
//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)
|
||||
if m.c.db != (*C.sqlite3)(db) {
|
||||
*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)
|
||||
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()
|
||||
for i, s := range a.([]*C.char) {
|
||||
args[i] = C.GoString(s)
|
||||
|
@ -171,7 +358,7 @@ func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.
|
|||
}
|
||||
|
||||
//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)
|
||||
var err error
|
||||
if isDestroy == 1 {
|
||||
|
@ -254,7 +441,7 @@ func goMDestroy(pClientData unsafe.Pointer) {
|
|||
}
|
||||
|
||||
//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)
|
||||
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc: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())
|
||||
}
|
||||
err := vtc.vTabCursor.Filter(idxNum, C.GoString(idxName), vals)
|
||||
err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
|
@ -293,10 +480,10 @@ func goVEof(pCursor unsafe.Pointer) C.int {
|
|||
}
|
||||
|
||||
//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)
|
||||
c := (*SQLiteContext)(cp)
|
||||
err := vtc.vTabCursor.Column(c, col)
|
||||
err := vtc.vTabCursor.Column(c, int(col))
|
||||
if err != nil {
|
||||
return mPrintf("%s", err.Error())
|
||||
}
|
||||
|
@ -373,7 +560,7 @@ func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
|
|||
mname := C.CString(moduleName)
|
||||
defer C.free(unsafe.Pointer(mname))
|
||||
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 {
|
||||
return c.lastError()
|
||||
}
|
|
@ -133,7 +133,7 @@ func TestCreateModule(t *testing.T) {
|
|||
}
|
||||
_, err = db.Exec("CREATE VIRTUAL TABLE vtab USING test('1', 2, three)")
|
||||
if err != nil {
|
||||
t.Fatal("could not create vtable: %v", err)
|
||||
t.Fatalf("could not create vtable: %v", err)
|
||||
}
|
||||
|
||||
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