mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-05 02:28:02 +00:00
bindings/go: Add error propagation from bindings lib
This commit is contained in:
parent
593febd9a4
commit
1493d499e5
8 changed files with 307 additions and 66 deletions
|
@ -13,29 +13,39 @@ type limboStmt struct {
|
|||
mu sync.Mutex
|
||||
ctx uintptr
|
||||
sql string
|
||||
err error
|
||||
}
|
||||
|
||||
func newStmt(ctx uintptr, sql string) *limboStmt {
|
||||
return &limboStmt{
|
||||
ctx: uintptr(ctx),
|
||||
sql: sql,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (ls *limboStmt) NumInput() int {
|
||||
ls.mu.Lock()
|
||||
defer ls.mu.Unlock()
|
||||
return int(stmtParamCount(ls.ctx))
|
||||
res := int(stmtParamCount(ls.ctx))
|
||||
if res < 0 {
|
||||
// set the error from rust
|
||||
_ = ls.getError()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ls *limboStmt) Close() error {
|
||||
ls.mu.Lock()
|
||||
res := closeStmt(ls.ctx)
|
||||
ls.mu.Unlock()
|
||||
defer ls.mu.Unlock()
|
||||
if ls.ctx == 0 {
|
||||
return nil
|
||||
}
|
||||
res := stmtClose(ls.ctx)
|
||||
ls.ctx = 0
|
||||
if ResultCode(res) != Ok {
|
||||
return fmt.Errorf("error closing statement: %s", ResultCode(res).String())
|
||||
}
|
||||
ls.ctx = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -52,8 +62,8 @@ func (ls *limboStmt) Exec(args []driver.Value) (driver.Result, error) {
|
|||
}
|
||||
var changes uint64
|
||||
ls.mu.Lock()
|
||||
defer ls.mu.Unlock()
|
||||
rc := stmtExec(ls.ctx, argPtr, argCount, uintptr(unsafe.Pointer(&changes)))
|
||||
ls.mu.Unlock()
|
||||
switch ResultCode(rc) {
|
||||
case Ok, Done:
|
||||
return driver.RowsAffected(changes), nil
|
||||
|
@ -66,7 +76,7 @@ func (ls *limboStmt) Exec(args []driver.Value) (driver.Result, error) {
|
|||
case Invalid:
|
||||
return nil, errors.New("invalid statement")
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected status: %d", rc)
|
||||
return nil, ls.getError()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,10 +91,10 @@ func (ls *limboStmt) Query(args []driver.Value) (driver.Rows, error) {
|
|||
argPtr = uintptr(unsafe.Pointer(&queryArgs[0]))
|
||||
}
|
||||
ls.mu.Lock()
|
||||
defer ls.mu.Unlock()
|
||||
rowsPtr := stmtQuery(ls.ctx, argPtr, uint64(len(queryArgs)))
|
||||
ls.mu.Unlock()
|
||||
if rowsPtr == 0 {
|
||||
return nil, fmt.Errorf("query failed for: %q", ls.sql)
|
||||
return nil, ls.getError()
|
||||
}
|
||||
return newRows(rowsPtr), nil
|
||||
}
|
||||
|
@ -96,27 +106,26 @@ func (ls *limboStmt) ExecContext(ctx context.Context, query string, args []drive
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ls.mu.Lock()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ls.mu.Unlock()
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
var changes uint64
|
||||
ls.mu.Lock()
|
||||
res := stmtExec(ls.ctx, argArray, uint64(len(args)), uintptr(unsafe.Pointer(&changes)))
|
||||
ls.mu.Unlock()
|
||||
switch ResultCode(res) {
|
||||
case Ok, Done:
|
||||
changes := uint64(changes)
|
||||
return driver.RowsAffected(changes), nil
|
||||
case Error:
|
||||
return nil, errors.New("error executing statement")
|
||||
case Busy:
|
||||
return nil, errors.New("busy")
|
||||
case Interrupt:
|
||||
return nil, errors.New("interrupted")
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected status: %d", res)
|
||||
var changes uint64
|
||||
defer ls.mu.Unlock()
|
||||
res := stmtExec(ls.ctx, argArray, uint64(len(args)), uintptr(unsafe.Pointer(&changes)))
|
||||
switch ResultCode(res) {
|
||||
case Ok, Done:
|
||||
changes := uint64(changes)
|
||||
return driver.RowsAffected(changes), nil
|
||||
case Busy:
|
||||
return nil, errors.New("Database is Busy")
|
||||
case Interrupt:
|
||||
return nil, errors.New("Interrupted")
|
||||
default:
|
||||
return nil, ls.getError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,16 +139,38 @@ func (ls *limboStmt) QueryContext(ctx context.Context, args []driver.NamedValue)
|
|||
if len(queryArgs) > 0 {
|
||||
argsPtr = uintptr(unsafe.Pointer(&queryArgs[0]))
|
||||
}
|
||||
ls.mu.Lock()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ls.mu.Unlock()
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
defer ls.mu.Unlock()
|
||||
rowsPtr := stmtQuery(ls.ctx, argsPtr, uint64(len(queryArgs)))
|
||||
if rowsPtr == 0 {
|
||||
return nil, ls.getError()
|
||||
}
|
||||
return newRows(rowsPtr), nil
|
||||
}
|
||||
ls.mu.Lock()
|
||||
rowsPtr := stmtQuery(ls.ctx, argsPtr, uint64(len(queryArgs)))
|
||||
ls.mu.Unlock()
|
||||
if rowsPtr == 0 {
|
||||
return nil, fmt.Errorf("query failed for: %q", ls.sql)
|
||||
}
|
||||
return newRows(rowsPtr), nil
|
||||
}
|
||||
|
||||
func (ls *limboStmt) Err() error {
|
||||
if ls.err == nil {
|
||||
ls.mu.Lock()
|
||||
defer ls.mu.Unlock()
|
||||
ls.getError()
|
||||
}
|
||||
return ls.err
|
||||
}
|
||||
|
||||
// mutex should always be locked when calling - always called after FFI
|
||||
func (ls *limboStmt) getError() error {
|
||||
err := stmtGetError(ls.ctx)
|
||||
if err == 0 {
|
||||
return nil
|
||||
}
|
||||
defer freeCString(err)
|
||||
cpy := fmt.Sprintf("%s", GoString(err))
|
||||
ls.err = errors.New(cpy)
|
||||
return ls.err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue