aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattn <mattn.jp@gmail.com>2020-08-26 09:36:43 +0900
committerGitHub <noreply@github.com>2020-08-26 09:36:43 +0900
commit6a8b30186d28277f09a0ba6df3d3fa3859c5c499 (patch)
tree99068cf0d123b5c63476eed68f49f273a2a4e98b
parenttreat vtable C arrays as Go slices rather than giant Go arrays (#840) (diff)
downloadgolite-6a8b30186d28277f09a0ba6df3d3fa3859c5c499.tar.gz
golite-6a8b30186d28277f09a0ba6df3d3fa3859c5c499.tar.xz
Use go-pointer instead of uintptr hacks. (#814)
* Use go-pointer instead of uintptr hacks. Fixes #791 * Do same of go-pointer * Drop older verion of Go * Fix build * Fix build
-rw-r--r--callback.go50
-rw-r--r--sqlite3.go20
-rw-r--r--sqlite3_opt_vtable.go30
3 files changed, 47 insertions, 53 deletions
diff --git a/callback.go b/callback.go
index 6450575..c3ce752 100644
--- a/callback.go
+++ b/callback.go
@@ -35,56 +35,55 @@ import (
//export callbackTrampoline
func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
- fi := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*functionInfo)
+ fi := lookupHandle(C.sqlite3_user_data(ctx)).(*functionInfo)
fi.Call(ctx, args)
}
//export stepTrampoline
func stepTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
- ai := lookupHandle(uintptr(C.sqlite3_user_data(ctx))).(*aggInfo)
+ ai := lookupHandle(C.sqlite3_user_data(ctx)).(*aggInfo)
ai.Step(ctx, args)
}
//export doneTrampoline
func doneTrampoline(ctx *C.sqlite3_context) {
- handle := uintptr(C.sqlite3_user_data(ctx))
- ai := lookupHandle(handle).(*aggInfo)
+ ai := lookupHandle(C.sqlite3_user_data(ctx)).(*aggInfo)
ai.Done(ctx)
}
//export compareTrampoline
-func compareTrampoline(handlePtr uintptr, la C.int, a *C.char, lb C.int, b *C.char) C.int {
+func compareTrampoline(handlePtr unsafe.Pointer, la C.int, a *C.char, lb C.int, b *C.char) C.int {
cmp := lookupHandle(handlePtr).(func(string, string) int)
return C.int(cmp(C.GoStringN(a, la), C.GoStringN(b, lb)))
}
//export commitHookTrampoline
-func commitHookTrampoline(handle uintptr) int {
+func commitHookTrampoline(handle unsafe.Pointer) int {
callback := lookupHandle(handle).(func() int)
return callback()
}
//export rollbackHookTrampoline
-func rollbackHookTrampoline(handle uintptr) {
+func rollbackHookTrampoline(handle unsafe.Pointer) {
callback := lookupHandle(handle).(func())
callback()
}
//export updateHookTrampoline
-func updateHookTrampoline(handle uintptr, op int, db *C.char, table *C.char, rowid int64) {
+func updateHookTrampoline(handle unsafe.Pointer, op int, db *C.char, table *C.char, rowid int64) {
callback := lookupHandle(handle).(func(int, string, string, int64))
callback(op, C.GoString(db), C.GoString(table), rowid)
}
//export authorizerTrampoline
-func authorizerTrampoline(handle uintptr, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
+func authorizerTrampoline(handle unsafe.Pointer, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
callback := lookupHandle(handle).(func(int, string, string, string) int)
return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
}
//export preUpdateHookTrampoline
-func preUpdateHookTrampoline(handle uintptr, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
+func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
hval := lookupHandleVal(handle)
data := SQLitePreUpdateData{
Conn: hval.db,
@@ -105,33 +104,27 @@ type handleVal struct {
}
var handleLock sync.Mutex
-var handleVals = make(map[uintptr]handleVal)
-var handleIndex uintptr = 100
+var handleVals = make(map[unsafe.Pointer]handleVal)
-func newHandle(db *SQLiteConn, v interface{}) uintptr {
+func newHandle(db *SQLiteConn, v interface{}) unsafe.Pointer {
handleLock.Lock()
defer handleLock.Unlock()
- i := handleIndex
- handleIndex++
- handleVals[i] = handleVal{db, v}
- return i
+ val := handleVal{db: db, val: v}
+ var p unsafe.Pointer = C.malloc(C.size_t(1))
+ if p == nil {
+ panic("can't allocate 'cgo-pointer hack index pointer': ptr == nil")
+ }
+ handleVals[p] = val
+ return p
}
-func lookupHandleVal(handle uintptr) handleVal {
+func lookupHandleVal(handle unsafe.Pointer) handleVal {
handleLock.Lock()
defer handleLock.Unlock()
- r, ok := handleVals[handle]
- if !ok {
- if handle >= 100 && handle < handleIndex {
- panic("deleted handle")
- } else {
- panic("invalid handle")
- }
- }
- return r
+ return handleVals[handle]
}
-func lookupHandle(handle uintptr) interface{} {
+func lookupHandle(handle unsafe.Pointer) interface{} {
return lookupHandleVal(handle).val
}
@@ -141,6 +134,7 @@ func deleteHandles(db *SQLiteConn) {
for handle, val := range handleVals {
if val.db == db {
delete(handleVals, handle)
+ C.free(handle)
}
}
}
diff --git a/sqlite3.go b/sqlite3.go
index 86c0f64..ababcfd 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -473,7 +473,7 @@ func (c *SQLiteConn) RegisterCollation(name string, cmp func(string, string) int
handle := newHandle(c, cmp)
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
- rv := C.sqlite3_create_collation(c.db, cname, C.SQLITE_UTF8, unsafe.Pointer(handle), (*[0]byte)(unsafe.Pointer(C.compareTrampoline)))
+ rv := C.sqlite3_create_collation(c.db, cname, C.SQLITE_UTF8, handle, (*[0]byte)(unsafe.Pointer(C.compareTrampoline)))
if rv != C.SQLITE_OK {
return c.lastError()
}
@@ -491,7 +491,7 @@ func (c *SQLiteConn) RegisterCommitHook(callback func() int) {
if callback == nil {
C.sqlite3_commit_hook(c.db, nil, nil)
} else {
- C.sqlite3_commit_hook(c.db, (*[0]byte)(C.commitHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
+ C.sqlite3_commit_hook(c.db, (*[0]byte)(C.commitHookTrampoline), newHandle(c, callback))
}
}
@@ -504,7 +504,7 @@ func (c *SQLiteConn) RegisterRollbackHook(callback func()) {
if callback == nil {
C.sqlite3_rollback_hook(c.db, nil, nil)
} else {
- C.sqlite3_rollback_hook(c.db, (*[0]byte)(C.rollbackHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
+ C.sqlite3_rollback_hook(c.db, (*[0]byte)(C.rollbackHookTrampoline), newHandle(c, callback))
}
}
@@ -521,7 +521,7 @@ func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64
if callback == nil {
C.sqlite3_update_hook(c.db, nil, nil)
} else {
- C.sqlite3_update_hook(c.db, (*[0]byte)(C.updateHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
+ C.sqlite3_update_hook(c.db, (*[0]byte)(C.updateHookTrampoline), newHandle(c, callback))
}
}
@@ -535,7 +535,7 @@ func (c *SQLiteConn) RegisterAuthorizer(callback func(int, string, string, strin
if callback == nil {
C.sqlite3_set_authorizer(c.db, nil, nil)
} else {
- C.sqlite3_set_authorizer(c.db, (*[0]byte)(C.authorizerTrampoline), unsafe.Pointer(newHandle(c, callback)))
+ C.sqlite3_set_authorizer(c.db, (*[0]byte)(C.authorizerTrampoline), newHandle(c, callback))
}
}
@@ -616,8 +616,8 @@ func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) erro
return nil
}
-func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
- return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(xFunc), (*[0]byte)(xStep), (*[0]byte)(xFinal))
+func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp unsafe.Pointer, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
+ return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(uintptr(pApp)), (*[0]byte)(xFunc), (*[0]byte)(xStep), (*[0]byte)(xFinal))
}
// RegisterAggregator makes a Go type available as a SQLite aggregation function.
@@ -804,7 +804,7 @@ func (c *SQLiteConn) exec(ctx context.Context, query string, args []namedValue)
if s.(*SQLiteStmt).s != nil {
stmtArgs := make([]namedValue, 0, len(args))
na := s.NumInput()
- if len(args) - start < na {
+ if len(args)-start < na {
s.Close()
return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
}
@@ -864,8 +864,8 @@ func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue)
}
s.(*SQLiteStmt).cls = true
na := s.NumInput()
- if len(args) - start < na {
- return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args) - start)
+ if len(args)-start < na {
+ return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args)-start)
}
// consume the number of arguments used in the current
// statement and append all named arguments not contained
diff --git a/sqlite3_opt_vtable.go b/sqlite3_opt_vtable.go
index 1af1c60..c0a6214 100644
--- a/sqlite3_opt_vtable.go
+++ b/sqlite3_opt_vtable.go
@@ -353,7 +353,7 @@ func mPrintf(format, arg string) *C.char {
//export goMInit
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(pClientData).(*sqliteModule)
if m.c.db != (*C.sqlite3)(db) {
*pzErr = mPrintf("%s", "Inconsistent db handles")
return 0
@@ -379,12 +379,12 @@ func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **
}
vt := sqliteVTab{m, vTab}
*pzErr = nil
- return C.uintptr_t(newHandle(m.c, &vt))
+ return C.uintptr_t(uintptr(newHandle(m.c, &vt)))
}
//export goVRelease
func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
- vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
+ vt := lookupHandle(pVTab).(*sqliteVTab)
var err error
if isDestroy == 1 {
err = vt.vTab.Destroy()
@@ -399,7 +399,7 @@ func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
//export goVOpen
func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
- vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
+ vt := lookupHandle(pVTab).(*sqliteVTab)
vTabCursor, err := vt.vTab.Open()
if err != nil {
*pzErr = mPrintf("%s", err.Error())
@@ -407,12 +407,12 @@ func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
}
vtc := sqliteVTabCursor{vt, vTabCursor}
*pzErr = nil
- return C.uintptr_t(newHandle(vt.module.c, &vtc))
+ return C.uintptr_t(uintptr(newHandle(vt.module.c, &vtc)))
}
//export goVBestIndex
func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
- vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
+ vt := lookupHandle(pVTab).(*sqliteVTab)
info := (*C.sqlite3_index_info)(icp)
csts := constraints(info)
res, err := vt.vTab.BestIndex(csts, orderBys(info))
@@ -455,7 +455,7 @@ func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
//export goVClose
func goVClose(pCursor unsafe.Pointer) *C.char {
- vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
+ vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
err := vtc.vTabCursor.Close()
if err != nil {
return mPrintf("%s", err.Error())
@@ -465,13 +465,13 @@ func goVClose(pCursor unsafe.Pointer) *C.char {
//export goMDestroy
func goMDestroy(pClientData unsafe.Pointer) {
- m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
+ m := lookupHandle(pClientData).(*sqliteModule)
m.module.DestroyModule()
}
//export goVFilter
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(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)
for _, v := range args {
@@ -490,7 +490,7 @@ func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int
//export goVNext
func goVNext(pCursor unsafe.Pointer) *C.char {
- vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
+ vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
err := vtc.vTabCursor.Next()
if err != nil {
return mPrintf("%s", err.Error())
@@ -500,7 +500,7 @@ func goVNext(pCursor unsafe.Pointer) *C.char {
//export goVEof
func goVEof(pCursor unsafe.Pointer) C.int {
- vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
+ vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
err := vtc.vTabCursor.EOF()
if err {
return 1
@@ -510,7 +510,7 @@ func goVEof(pCursor unsafe.Pointer) C.int {
//export goVColumn
func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
- vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
+ vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
c := (*SQLiteContext)(cp)
err := vtc.vTabCursor.Column(c, int(col))
if err != nil {
@@ -521,7 +521,7 @@ func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
//export goVRowid
func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
- vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
+ vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
rowid, err := vtc.vTabCursor.Rowid()
if err != nil {
return mPrintf("%s", err.Error())
@@ -532,7 +532,7 @@ func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
//export goVUpdate
func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
- vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
+ vt := lookupHandle(pVTab).(*sqliteVTab)
var tname string
if n, ok := vt.vTab.(interface {
@@ -652,7 +652,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._sqlite3_create_module(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
+ rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
if rv != C.SQLITE_OK {
return c.lastError()
}