mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
VFS error handling.
This commit is contained in:
@@ -265,7 +265,7 @@ func traceCallback(ctx context.Context, mod api.Module, evt TraceEvent, pDB, pAr
|
||||
}
|
||||
}
|
||||
if arg1 != nil {
|
||||
_, rc = errorCode(c.trace(evt, arg1, arg2), ERROR)
|
||||
_ = c.trace(evt, arg1, arg2)
|
||||
}
|
||||
}
|
||||
return rc
|
||||
|
||||
@@ -198,14 +198,14 @@ func (ctx Context) ResultError(err error) {
|
||||
return
|
||||
}
|
||||
|
||||
msg, code := errorCode(err, _OK)
|
||||
msg, code := errorCode(err, ERROR)
|
||||
if msg != "" {
|
||||
defer ctx.c.arena.mark()()
|
||||
ptr := ctx.c.arena.string(msg)
|
||||
ctx.c.call("sqlite3_result_error",
|
||||
stk_t(ctx.handle), stk_t(ptr), stk_t(len(msg)))
|
||||
}
|
||||
if code != _OK {
|
||||
if code != res_t(ERROR) {
|
||||
ctx.c.call("sqlite3_result_error_code",
|
||||
stk_t(ctx.handle), stk_t(code))
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ func Test_Open_dir(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("want error")
|
||||
}
|
||||
if !errors.Is(err, sqlite3.CANTOPEN) {
|
||||
t.Errorf("got %v, want sqlite3.CANTOPEN", err)
|
||||
if !errors.Is(err, sqlite3.CANTOPEN_ISDIR) {
|
||||
t.Errorf("got %v, want sqlite3.CANTOPEN_ISDIR", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
32
error.go
32
error.go
@@ -11,6 +11,7 @@ import (
|
||||
//
|
||||
// https://sqlite.org/c3ref/errcode.html
|
||||
type Error struct {
|
||||
sys error
|
||||
msg string
|
||||
sql string
|
||||
code res_t
|
||||
@@ -33,7 +34,7 @@ func (e *Error) ExtendedCode() ExtendedErrorCode {
|
||||
// Error implements the error interface.
|
||||
func (e *Error) Error() string {
|
||||
var b strings.Builder
|
||||
b.WriteString(util.ErrorCodeString(uint32(e.code)))
|
||||
b.WriteString(util.ErrorCodeString(e.code))
|
||||
|
||||
if e.msg != "" {
|
||||
b.WriteString(": ")
|
||||
@@ -43,6 +44,14 @@ func (e *Error) Error() string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying operating system error
|
||||
// that caused the I/O error or failure to open a file.
|
||||
//
|
||||
// https://sqlite.org/c3ref/system_errno.html
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.sys
|
||||
}
|
||||
|
||||
// Is tests whether this error matches a given [ErrorCode] or [ExtendedErrorCode].
|
||||
//
|
||||
// It makes it possible to do:
|
||||
@@ -90,7 +99,16 @@ func (e *Error) SQL() string {
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e ErrorCode) Error() string {
|
||||
return util.ErrorCodeString(uint32(e))
|
||||
return util.ErrorCodeString(e)
|
||||
}
|
||||
|
||||
// As converts this error to an [ExtendedErrorCode].
|
||||
func (e ErrorCode) As(err any) bool {
|
||||
c, ok := err.(*xErrorCode)
|
||||
if ok {
|
||||
*c = xErrorCode(e)
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// Temporary returns true for [BUSY] errors.
|
||||
@@ -105,7 +123,7 @@ func (e ErrorCode) ExtendedCode() ExtendedErrorCode {
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e ExtendedErrorCode) Error() string {
|
||||
return util.ErrorCodeString(uint32(e))
|
||||
return util.ErrorCodeString(e)
|
||||
}
|
||||
|
||||
// Is tests whether this error matches a given [ErrorCode].
|
||||
@@ -150,14 +168,10 @@ func errorCode(err error, def ErrorCode) (msg string, code res_t) {
|
||||
return code.msg, res_t(code.code)
|
||||
}
|
||||
|
||||
var ecode ErrorCode
|
||||
var xcode xErrorCode
|
||||
switch {
|
||||
case errors.As(err, &xcode):
|
||||
if errors.As(err, &xcode) {
|
||||
code = res_t(xcode)
|
||||
case errors.As(err, &ecode):
|
||||
code = res_t(ecode)
|
||||
default:
|
||||
} else {
|
||||
code = res_t(def)
|
||||
}
|
||||
return err.Error(), code
|
||||
|
||||
@@ -33,8 +33,12 @@ func AssertErr() ErrorString {
|
||||
return ErrorString(msg)
|
||||
}
|
||||
|
||||
func ErrorCodeString(rc uint32) string {
|
||||
switch rc {
|
||||
type errorCode interface {
|
||||
~uint8 | ~uint16 | ~uint32 | ~int32
|
||||
}
|
||||
|
||||
func ErrorCodeString[T errorCode](rc T) string {
|
||||
switch uint32(rc) {
|
||||
case ABORT_ROLLBACK:
|
||||
return "sqlite3: abort due to ROLLBACK"
|
||||
case ROW:
|
||||
@@ -42,7 +46,7 @@ func ErrorCodeString(rc uint32) string {
|
||||
case DONE:
|
||||
return "sqlite3: no more rows available"
|
||||
}
|
||||
switch rc & 0xff {
|
||||
switch uint8(rc) {
|
||||
case OK:
|
||||
return "sqlite3: not an error"
|
||||
case ERROR:
|
||||
|
||||
@@ -12,6 +12,7 @@ type ConnKey struct{}
|
||||
|
||||
type moduleKey struct{}
|
||||
type moduleState struct {
|
||||
sysError error
|
||||
mmapState
|
||||
handleState
|
||||
}
|
||||
@@ -23,3 +24,15 @@ func NewContext(ctx context.Context) context.Context {
|
||||
ctx = context.WithValue(ctx, moduleKey{}, state)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func GetSystemError(ctx context.Context) error {
|
||||
s := ctx.Value(moduleKey{}).(*moduleState)
|
||||
return s.sysError
|
||||
}
|
||||
|
||||
func SetSystemError(ctx context.Context, err error) {
|
||||
s, ok := ctx.Value(moduleKey{}).(*moduleState)
|
||||
if ok {
|
||||
s.sysError = err
|
||||
}
|
||||
}
|
||||
|
||||
19
sqlite.go
19
sqlite.go
@@ -125,14 +125,15 @@ func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error {
|
||||
panic(util.OOMErr)
|
||||
}
|
||||
|
||||
var msg, query string
|
||||
if handle != 0 {
|
||||
var msg, query string
|
||||
if ptr := ptr_t(sqlt.call("sqlite3_errmsg", stk_t(handle))); ptr != 0 {
|
||||
msg = util.ReadString(sqlt.mod, ptr, _MAX_LENGTH)
|
||||
msg = strings.TrimPrefix(msg, "sqlite3: ")
|
||||
msg = strings.TrimPrefix(msg, util.ErrorCodeString(rc)[len("sqlite3: "):])
|
||||
msg = strings.TrimPrefix(msg, ": ")
|
||||
if msg == "not an error" {
|
||||
msg = ""
|
||||
} else {
|
||||
msg = strings.TrimPrefix(msg, util.ErrorCodeString(uint32(rc))[len("sqlite3: "):])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +142,16 @@ func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error {
|
||||
query = sql[0][i:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if msg != "" || query != "" {
|
||||
return &Error{code: rc, msg: msg, sql: query}
|
||||
}
|
||||
var sys error
|
||||
switch ErrorCode(rc) {
|
||||
case CANTOPEN, IOERR:
|
||||
sys = util.GetSystemError(sqlt.ctx)
|
||||
}
|
||||
|
||||
if sys != nil || msg != "" || query != "" {
|
||||
return &Error{code: rc, sys: sys, msg: msg, sql: query}
|
||||
}
|
||||
return xErrorCode(rc)
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ func TestConn_Open_dir(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("want error")
|
||||
}
|
||||
if !errors.Is(err, sqlite3.CANTOPEN) {
|
||||
t.Errorf("got %v, want sqlite3.CANTOPEN", err)
|
||||
if !errors.Is(err, sqlite3.CANTOPEN_ISDIR) {
|
||||
t.Errorf("got %v, want sqlite3.CANTOPEN_ISDIR", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ to check if your build supports shared memory.
|
||||
|
||||
### Blocking Locks
|
||||
|
||||
On Windows and macOS, this package implements
|
||||
On macOS, this package implements
|
||||
[Wal-mode blocking locks](https://sqlite.org/src/doc/tip/doc/wal-lock.md).
|
||||
|
||||
### Batch-Atomic Write
|
||||
|
||||
@@ -193,8 +193,8 @@ type FileSharedMemory interface {
|
||||
// SharedMemory is a shared-memory WAL-index implementation.
|
||||
// Use [NewSharedMemory] to create a shared-memory.
|
||||
type SharedMemory interface {
|
||||
shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, _ErrorCode)
|
||||
shmLock(int32, int32, _ShmFlag) _ErrorCode
|
||||
shmMap(context.Context, api.Module, int32, int32, bool) (ptr_t, error)
|
||||
shmLock(int32, int32, _ShmFlag) error
|
||||
shmUnmap(bool)
|
||||
shmBarrier()
|
||||
io.Closer
|
||||
|
||||
@@ -20,7 +20,7 @@ type (
|
||||
type _ErrorCode uint32
|
||||
|
||||
func (e _ErrorCode) Error() string {
|
||||
return util.ErrorCodeString(uint32(e))
|
||||
return util.ErrorCodeString(e)
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
14
vfs/file.go
14
vfs/file.go
@@ -40,7 +40,7 @@ func evalSymlinks(path string) (string, error) {
|
||||
func (vfsOS) Delete(path string, syncDir bool) error {
|
||||
err := os.Remove(path)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return _IOERR_DELETE_NOENT
|
||||
return sysError{err, _IOERR_DELETE_NOENT}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -53,7 +53,7 @@ func (vfsOS) Delete(path string, syncDir bool) error {
|
||||
defer f.Close()
|
||||
err = osSync(f, 0, SYNC_FULL)
|
||||
if err != nil {
|
||||
return _IOERR_DIR_FSYNC
|
||||
return sysError{err, _IOERR_DIR_FSYNC}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -108,14 +108,14 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
}
|
||||
if err != nil {
|
||||
if name == nil {
|
||||
return nil, flags, _IOERR_GETTEMPPATH
|
||||
return nil, flags, sysError{err, _IOERR_GETTEMPPATH}
|
||||
}
|
||||
if errors.Is(err, syscall.EISDIR) {
|
||||
return nil, flags, _CANTOPEN_ISDIR
|
||||
return nil, flags, sysError{err, _CANTOPEN_ISDIR}
|
||||
}
|
||||
if isCreate && isJournl && errors.Is(err, fs.ErrPermission) &&
|
||||
osAccess(name.String(), ACCESS_EXISTS) != nil {
|
||||
return nil, flags, _READONLY_DIRECTORY
|
||||
return nil, flags, sysError{err, _READONLY_DIRECTORY}
|
||||
}
|
||||
return nil, flags, err
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
if modeof := name.URIParameter("modeof"); modeof != "" {
|
||||
if err = osSetMode(f, modeof); err != nil {
|
||||
f.Close()
|
||||
return nil, flags, _IOERR_FSTAT
|
||||
return nil, flags, sysError{err, _IOERR_FSTAT}
|
||||
}
|
||||
}
|
||||
if isUnix && flags&OPEN_DELETEONCLOSE != 0 {
|
||||
@@ -193,7 +193,7 @@ func (f *vfsFile) Sync(flags SyncFlag) error {
|
||||
defer d.Close()
|
||||
err = osSync(f.File, f.flags, flags)
|
||||
if err != nil {
|
||||
return _IOERR_DIR_FSYNC
|
||||
return sysError{err, _IOERR_DIR_FSYNC}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -33,7 +33,7 @@ func osReadAt(file *os.File, p []byte, off int64) (int, error) {
|
||||
unix.ERANGE,
|
||||
unix.EIO,
|
||||
unix.ENXIO:
|
||||
return n, _IOERR_CORRUPTFS
|
||||
return n, sysError{err, _IOERR_CORRUPTFS}
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
@@ -42,7 +42,7 @@ func osReadAt(file *os.File, p []byte, off int64) (int, error) {
|
||||
func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
|
||||
n, err := file.WriteAt(p, off)
|
||||
if errno, ok := err.(unix.Errno); ok && errno == unix.ENOSPC {
|
||||
return n, _FULL
|
||||
return n, sysError{err, _FULL}
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func osWriteAt(file *os.File, p []byte, off int64) (int, error) {
|
||||
case
|
||||
windows.ERROR_HANDLE_DISK_FULL,
|
||||
windows.ERROR_DISK_FULL:
|
||||
return n, _FULL
|
||||
return n, sysError{err, _FULL}
|
||||
}
|
||||
}
|
||||
return n, err
|
||||
|
||||
@@ -141,7 +141,7 @@ func (s *vfsShm) shmOpen() (rc _ErrorCode) {
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if int(size)&(unix.Getpagesize()-1) != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
@@ -154,26 +154,30 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
// Check if file is big enough.
|
||||
o, err := s.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
if n := (int64(id) + 1) * int64(size); n > o {
|
||||
if !extend {
|
||||
return 0, _OK
|
||||
return 0, nil
|
||||
}
|
||||
if osAllocate(s.File, n) != nil {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
if err := osAllocate(s.File, n); err != nil {
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
}
|
||||
|
||||
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, false)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMMAP
|
||||
return 0, err
|
||||
}
|
||||
s.regions = append(s.regions, r)
|
||||
return r.Ptr, _OK
|
||||
return r.Ptr, nil
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
|
||||
if s.vfsShmParent == nil {
|
||||
return _IOERR_SHMLOCK
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ const (
|
||||
//
|
||||
// https://sqlite.org/walformat.html#the_wal_index_file_format
|
||||
|
||||
func (s *vfsShm) shmAcquire(ptr *_ErrorCode) {
|
||||
if ptr != nil && *ptr != _OK {
|
||||
func (s *vfsShm) shmAcquire(errp *error) {
|
||||
if errp != nil && *errp != _OK {
|
||||
return
|
||||
}
|
||||
if len(s.ptrs) == 0 || shmEqual(s.shadow[0][:], s.shared[0][:]) {
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *vfsShm) Close() error {
|
||||
}
|
||||
|
||||
if err := dotlk.Unlock(s.path); err != nil {
|
||||
return _IOERR_UNLOCK
|
||||
return sysError{err, _IOERR_UNLOCK}
|
||||
}
|
||||
delete(vfsShmList, s.path)
|
||||
s.vfsShmParent = nil
|
||||
@@ -96,7 +96,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) {
|
||||
if size != _WALINDEX_PGSZ {
|
||||
return 0, _IOERR_SHMMAP
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
// Extend shared memory.
|
||||
if int(id) >= len(s.shared) {
|
||||
if !extend {
|
||||
return 0, _OK
|
||||
return 0, nil
|
||||
}
|
||||
s.shared = append(s.shared, make([][_WALINDEX_PGSZ]byte, int(id)-len(s.shared)+1)...)
|
||||
}
|
||||
@@ -140,16 +140,20 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
|
||||
s.shadow[0][4] = 1
|
||||
return s.ptrs[id], _OK
|
||||
return s.ptrs[id], nil
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (err error) {
|
||||
if s.vfsShmParent == nil {
|
||||
return _IOERR_SHMLOCK
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
switch {
|
||||
case flags&_SHM_LOCK != 0:
|
||||
defer s.shmAcquire(&rc)
|
||||
defer s.shmAcquire(&err)
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
s.shmRelease()
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
return rc
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, _ErrorCode) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (ptr_t, error) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if int(size)&(unix.Getpagesize()-1) != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
@@ -86,29 +86,32 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
// Check if file is big enough.
|
||||
o, err := s.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
if n := (int64(id) + 1) * int64(size); n > o {
|
||||
if !extend {
|
||||
return 0, _OK
|
||||
return 0, nil
|
||||
}
|
||||
if s.readOnly || osAllocate(s.File, n) != nil {
|
||||
if s.readOnly {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
}
|
||||
if err := osAllocate(s.File, n); err != nil {
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
}
|
||||
|
||||
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, s.readOnly)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMMAP
|
||||
return 0, err
|
||||
}
|
||||
s.regions = append(s.regions, r)
|
||||
if s.readOnly {
|
||||
return r.Ptr, _READONLY
|
||||
}
|
||||
return r.Ptr, _OK
|
||||
return r.Ptr, nil
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
|
||||
// Argument check.
|
||||
switch {
|
||||
case n <= 0:
|
||||
@@ -129,6 +132,10 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
panic(util.AssertErr())
|
||||
}
|
||||
|
||||
if s.File == nil {
|
||||
return _IOERR_SHMLOCK
|
||||
}
|
||||
|
||||
var timeout time.Duration
|
||||
if s.blocking {
|
||||
timeout = time.Millisecond
|
||||
|
||||
@@ -65,7 +65,7 @@ func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
return rc
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ ptr_t, rc _ErrorCode) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (_ ptr_t, err error) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if size != _WALINDEX_PGSZ || (windows.Getpagesize()-1)&_WALINDEX_PGSZ != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
@@ -79,19 +79,19 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
return 0, rc
|
||||
}
|
||||
|
||||
defer s.shmAcquire(&rc)
|
||||
defer s.shmAcquire(&err)
|
||||
|
||||
// Check if file is big enough.
|
||||
o, err := s.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
if n := (int64(id) + 1) * int64(size); n > o {
|
||||
if !extend {
|
||||
return 0, _OK
|
||||
return 0, nil
|
||||
}
|
||||
if osAllocate(s.File, n) != nil {
|
||||
return 0, _IOERR_SHMSIZE
|
||||
if err := osAllocate(s.File, n); err != nil {
|
||||
return 0, sysError{err, _IOERR_SHMSIZE}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
for int(id) >= len(s.shared) {
|
||||
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size)
|
||||
if err != nil {
|
||||
return 0, _IOERR_SHMMAP
|
||||
return 0, err
|
||||
}
|
||||
s.regions = append(s.regions, r)
|
||||
s.shared = append(s.shared, r.Data)
|
||||
@@ -124,13 +124,17 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
|
||||
s.shadow[0][4] = 1
|
||||
return s.ptrs[id], _OK
|
||||
return s.ptrs[id], nil
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (rc _ErrorCode) {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) (err error) {
|
||||
if s.File == nil {
|
||||
return _IOERR_SHMLOCK
|
||||
}
|
||||
|
||||
switch {
|
||||
case flags&_SHM_LOCK != 0:
|
||||
defer s.shmAcquire(&rc)
|
||||
defer s.shmAcquire(&err)
|
||||
case flags&_SHM_EXCLUSIVE != 0:
|
||||
s.shmRelease()
|
||||
}
|
||||
|
||||
90
vfs/vfs.go
90
vfs/vfs.go
@@ -102,7 +102,7 @@ func vfsFullPathname(ctx context.Context, mod api.Module, pVfs, zRelative ptr_t,
|
||||
}
|
||||
util.WriteString(mod, zFull, path)
|
||||
|
||||
return vfsErrorCode(err, _CANTOPEN_FULLPATH)
|
||||
return vfsErrorCode(ctx, err, _CANTOPEN_FULLPATH)
|
||||
}
|
||||
|
||||
func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir int32) _ErrorCode {
|
||||
@@ -110,7 +110,7 @@ func vfsDelete(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, syncDir i
|
||||
path := util.ReadString(mod, zPath, _MAX_PATHNAME)
|
||||
|
||||
err := vfs.Delete(path, syncDir != 0)
|
||||
return vfsErrorCode(err, _IOERR_DELETE)
|
||||
return vfsErrorCode(ctx, err, _IOERR_DELETE)
|
||||
}
|
||||
|
||||
func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags AccessFlag, pResOut ptr_t) _ErrorCode {
|
||||
@@ -119,7 +119,7 @@ func vfsAccess(ctx context.Context, mod api.Module, pVfs, zPath ptr_t, flags Acc
|
||||
|
||||
ok, err := vfs.Access(path, flags)
|
||||
util.WriteBool(mod, pResOut, ok)
|
||||
return vfsErrorCode(err, _IOERR_ACCESS)
|
||||
return vfsErrorCode(ctx, err, _IOERR_ACCESS)
|
||||
}
|
||||
|
||||
func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flags OpenFlag, pOutFlags, pOutVFS ptr_t) _ErrorCode {
|
||||
@@ -134,7 +134,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag
|
||||
file, flags, err = vfs.Open(name.String(), flags)
|
||||
}
|
||||
if err != nil {
|
||||
return vfsErrorCode(err, _CANTOPEN)
|
||||
return vfsErrorCode(ctx, err, _CANTOPEN)
|
||||
}
|
||||
|
||||
if file, ok := file.(FilePowersafeOverwrite); ok {
|
||||
@@ -155,7 +155,7 @@ func vfsOpen(ctx context.Context, mod api.Module, pVfs, zPath, pFile ptr_t, flag
|
||||
|
||||
func vfsClose(ctx context.Context, mod api.Module, pFile ptr_t) _ErrorCode {
|
||||
err := vfsFileClose(ctx, mod, pFile)
|
||||
return vfsErrorCode(err, _IOERR_CLOSE)
|
||||
return vfsErrorCode(ctx, err, _IOERR_CLOSE)
|
||||
}
|
||||
|
||||
func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32, iOfst int64) _ErrorCode {
|
||||
@@ -167,7 +167,7 @@ func vfsRead(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32,
|
||||
return _OK
|
||||
}
|
||||
if err != io.EOF {
|
||||
return vfsErrorCode(err, _IOERR_READ)
|
||||
return vfsErrorCode(ctx, err, _IOERR_READ)
|
||||
}
|
||||
clear(buf[n:])
|
||||
return _IOERR_SHORT_READ
|
||||
@@ -178,45 +178,45 @@ func vfsWrite(ctx context.Context, mod api.Module, pFile, zBuf ptr_t, iAmt int32
|
||||
buf := util.View(mod, zBuf, int64(iAmt))
|
||||
|
||||
_, err := file.WriteAt(buf, iOfst)
|
||||
return vfsErrorCode(err, _IOERR_WRITE)
|
||||
return vfsErrorCode(ctx, err, _IOERR_WRITE)
|
||||
}
|
||||
|
||||
func vfsTruncate(ctx context.Context, mod api.Module, pFile ptr_t, nByte int64) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
err := file.Truncate(nByte)
|
||||
return vfsErrorCode(err, _IOERR_TRUNCATE)
|
||||
return vfsErrorCode(ctx, err, _IOERR_TRUNCATE)
|
||||
}
|
||||
|
||||
func vfsSync(ctx context.Context, mod api.Module, pFile ptr_t, flags SyncFlag) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
err := file.Sync(flags)
|
||||
return vfsErrorCode(err, _IOERR_FSYNC)
|
||||
return vfsErrorCode(ctx, err, _IOERR_FSYNC)
|
||||
}
|
||||
|
||||
func vfsFileSize(ctx context.Context, mod api.Module, pFile, pSize ptr_t) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
size, err := file.Size()
|
||||
util.Write64(mod, pSize, size)
|
||||
return vfsErrorCode(err, _IOERR_SEEK)
|
||||
return vfsErrorCode(ctx, err, _IOERR_SEEK)
|
||||
}
|
||||
|
||||
func vfsLock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
err := file.Lock(eLock)
|
||||
return vfsErrorCode(err, _IOERR_LOCK)
|
||||
return vfsErrorCode(ctx, err, _IOERR_LOCK)
|
||||
}
|
||||
|
||||
func vfsUnlock(ctx context.Context, mod api.Module, pFile ptr_t, eLock LockLevel) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
err := file.Unlock(eLock)
|
||||
return vfsErrorCode(err, _IOERR_UNLOCK)
|
||||
return vfsErrorCode(ctx, err, _IOERR_UNLOCK)
|
||||
}
|
||||
|
||||
func vfsCheckReservedLock(ctx context.Context, mod api.Module, pFile, pResOut ptr_t) _ErrorCode {
|
||||
file := vfsFileGet(ctx, mod, pFile).(File)
|
||||
locked, err := file.CheckReservedLock()
|
||||
util.WriteBool(mod, pResOut, locked)
|
||||
return vfsErrorCode(err, _IOERR_CHECKRESERVEDLOCK)
|
||||
return vfsErrorCode(ctx, err, _IOERR_CHECKRESERVEDLOCK)
|
||||
}
|
||||
|
||||
func vfsFileControl(ctx context.Context, mod api.Module, pFile ptr_t, op _FcntlOpcode, pArg ptr_t) _ErrorCode {
|
||||
@@ -268,20 +268,20 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
|
||||
if file, ok := file.(FileSizeHint); ok {
|
||||
size := util.Read64[int64](mod, pArg)
|
||||
err := file.SizeHint(size)
|
||||
return vfsErrorCode(err, _IOERR_TRUNCATE)
|
||||
return vfsErrorCode(ctx, err, _IOERR_TRUNCATE)
|
||||
}
|
||||
|
||||
case _FCNTL_HAS_MOVED:
|
||||
if file, ok := file.(FileHasMoved); ok {
|
||||
moved, err := file.HasMoved()
|
||||
util.WriteBool(mod, pArg, moved)
|
||||
return vfsErrorCode(err, _IOERR_FSTAT)
|
||||
return vfsErrorCode(ctx, err, _IOERR_FSTAT)
|
||||
}
|
||||
|
||||
case _FCNTL_OVERWRITE:
|
||||
if file, ok := file.(FileOverwrite); ok {
|
||||
err := file.Overwrite()
|
||||
return vfsErrorCode(err, _IOERR)
|
||||
return vfsErrorCode(ctx, err, _IOERR)
|
||||
}
|
||||
|
||||
case _FCNTL_SYNC:
|
||||
@@ -291,29 +291,29 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
|
||||
name = util.ReadString(mod, pArg, _MAX_PATHNAME)
|
||||
}
|
||||
err := file.SyncSuper(name)
|
||||
return vfsErrorCode(err, _IOERR)
|
||||
return vfsErrorCode(ctx, err, _IOERR)
|
||||
}
|
||||
|
||||
case _FCNTL_COMMIT_PHASETWO:
|
||||
if file, ok := file.(FileCommitPhaseTwo); ok {
|
||||
err := file.CommitPhaseTwo()
|
||||
return vfsErrorCode(err, _IOERR)
|
||||
return vfsErrorCode(ctx, err, _IOERR)
|
||||
}
|
||||
|
||||
case _FCNTL_BEGIN_ATOMIC_WRITE:
|
||||
if file, ok := file.(FileBatchAtomicWrite); ok {
|
||||
err := file.BeginAtomicWrite()
|
||||
return vfsErrorCode(err, _IOERR_BEGIN_ATOMIC)
|
||||
return vfsErrorCode(ctx, err, _IOERR_BEGIN_ATOMIC)
|
||||
}
|
||||
case _FCNTL_COMMIT_ATOMIC_WRITE:
|
||||
if file, ok := file.(FileBatchAtomicWrite); ok {
|
||||
err := file.CommitAtomicWrite()
|
||||
return vfsErrorCode(err, _IOERR_COMMIT_ATOMIC)
|
||||
return vfsErrorCode(ctx, err, _IOERR_COMMIT_ATOMIC)
|
||||
}
|
||||
case _FCNTL_ROLLBACK_ATOMIC_WRITE:
|
||||
if file, ok := file.(FileBatchAtomicWrite); ok {
|
||||
err := file.RollbackAtomicWrite()
|
||||
return vfsErrorCode(err, _IOERR_ROLLBACK_ATOMIC)
|
||||
return vfsErrorCode(ctx, err, _IOERR_ROLLBACK_ATOMIC)
|
||||
}
|
||||
|
||||
case _FCNTL_CKPT_START:
|
||||
@@ -338,7 +338,7 @@ func vfsFileControlImpl(ctx context.Context, mod api.Module, file File, op _Fcnt
|
||||
|
||||
out, err := file.Pragma(strings.ToLower(name), value)
|
||||
|
||||
ret := vfsErrorCode(err, _ERROR)
|
||||
ret := vfsErrorCode(ctx, err, _ERROR)
|
||||
if ret == _ERROR {
|
||||
out = err.Error()
|
||||
}
|
||||
@@ -407,14 +407,15 @@ func vfsShmBarrier(ctx context.Context, mod api.Module, pFile ptr_t) {
|
||||
|
||||
func vfsShmMap(ctx context.Context, mod api.Module, pFile ptr_t, iRegion, szRegion, bExtend int32, pp ptr_t) _ErrorCode {
|
||||
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
|
||||
p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
|
||||
p, err := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
|
||||
util.Write32(mod, pp, p)
|
||||
return rc
|
||||
return vfsErrorCode(ctx, err, _IOERR_SHMMAP)
|
||||
}
|
||||
|
||||
func vfsShmLock(ctx context.Context, mod api.Module, pFile ptr_t, offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
|
||||
return shm.shmLock(offset, n, flags)
|
||||
err := shm.shmLock(offset, n, flags)
|
||||
return vfsErrorCode(ctx, err, _IOERR_SHMLOCK)
|
||||
}
|
||||
|
||||
func vfsShmUnmap(ctx context.Context, mod api.Module, pFile ptr_t, bDelete int32) _ErrorCode {
|
||||
@@ -454,13 +455,36 @@ func vfsFileClose(ctx context.Context, mod api.Module, pFile ptr_t) error {
|
||||
return util.DelHandle(ctx, id)
|
||||
}
|
||||
|
||||
func vfsErrorCode(err error, def _ErrorCode) _ErrorCode {
|
||||
if err == nil {
|
||||
return _OK
|
||||
func vfsErrorCode(ctx context.Context, err error, code _ErrorCode) _ErrorCode {
|
||||
var sys error
|
||||
|
||||
switch err := err.(type) {
|
||||
case nil:
|
||||
code = _OK
|
||||
case _ErrorCode:
|
||||
code = err
|
||||
case sysError:
|
||||
code = err.code
|
||||
sys = err.error
|
||||
default:
|
||||
switch v := reflect.ValueOf(err); v.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16:
|
||||
code = _ErrorCode(v.Uint())
|
||||
}
|
||||
}
|
||||
switch v := reflect.ValueOf(err); v.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
||||
return _ErrorCode(v.Uint())
|
||||
}
|
||||
return def
|
||||
|
||||
util.SetSystemError(ctx, sys)
|
||||
return code
|
||||
}
|
||||
|
||||
func SystemError[T interface{ ~uint8 | ~uint16 }](err error, code T) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return sysError{error: err, code: _ErrorCode(code)}
|
||||
}
|
||||
|
||||
type sysError struct {
|
||||
error
|
||||
code _ErrorCode
|
||||
}
|
||||
|
||||
48
vtab.go
48
vtab.go
@@ -465,19 +465,19 @@ func vtabModuleCallback(i vtabConstructor) func(_ context.Context, _ api.Module,
|
||||
vtabPutHandle(ctx, mod, ppVTab, val[0].Interface())
|
||||
}
|
||||
|
||||
return vtabError(ctx, mod, pzErr, _PTR_ERROR, err)
|
||||
return vtabError(ctx, mod, pzErr, _PTR_ERROR, err, ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
func vtabDisconnectCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
err := vtabDelHandle(ctx, mod, pVTab)
|
||||
return vtabError(ctx, mod, 0, _PTR_ERROR, err)
|
||||
return vtabError(ctx, mod, 0, _PTR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabDestroyCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabDestroyer)
|
||||
err := errors.Join(vtab.Destroy(), vtabDelHandle(ctx, mod, pVTab))
|
||||
return vtabError(ctx, mod, 0, _PTR_ERROR, err)
|
||||
return vtabError(ctx, mod, 0, _PTR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo ptr_t) res_t {
|
||||
@@ -490,7 +490,7 @@ func vtabBestIndexCallback(ctx context.Context, mod api.Module, pVTab, pIdxInfo
|
||||
err := vtab.BestIndex(&info)
|
||||
|
||||
info.save()
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, pArg, pRowID ptr_t) res_t {
|
||||
@@ -504,13 +504,13 @@ func vtabUpdateCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg i
|
||||
util.Write64(mod, pRowID, rowID)
|
||||
}
|
||||
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabRenameCallback(ctx context.Context, mod api.Module, pVTab, zNew ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabRenamer)
|
||||
err := vtab.Rename(util.ReadString(mod, zNew, _MAX_NAME))
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabFindFuncCallback(ctx context.Context, mod api.Module, pVTab ptr_t, nArg int32, zName, pxFunc ptr_t) int32 {
|
||||
@@ -534,51 +534,49 @@ func vtabIntegrityCallback(ctx context.Context, mod api.Module, pVTab, zSchema,
|
||||
err := vtab.Integrity(schema, table, int(mFlags))
|
||||
// xIntegrity should return OK - even if it finds problems in the content of the virtual table.
|
||||
// https://sqlite.org/vtab.html#xintegrity
|
||||
vtabError(ctx, mod, pzErr, _PTR_ERROR, err)
|
||||
_, code := errorCode(err, _OK)
|
||||
return code
|
||||
return vtabError(ctx, mod, pzErr, _PTR_ERROR, err, _OK)
|
||||
}
|
||||
|
||||
func vtabBeginCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
|
||||
err := vtab.Begin()
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabSyncCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
|
||||
err := vtab.Sync()
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabCommitCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
|
||||
err := vtab.Commit()
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabRollbackCallback(ctx context.Context, mod api.Module, pVTab ptr_t) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabTxn)
|
||||
err := vtab.Rollback()
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabSavepointCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
|
||||
err := vtab.Savepoint(int(id))
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabReleaseCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
|
||||
err := vtab.Release(int(id))
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func vtabRollbackToCallback(ctx context.Context, mod api.Module, pVTab ptr_t, id int32) res_t {
|
||||
vtab := vtabGetHandle(ctx, mod, pVTab).(VTabSavepointer)
|
||||
err := vtab.RollbackTo(int(id))
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur ptr_t) res_t {
|
||||
@@ -589,12 +587,12 @@ func cursorOpenCallback(ctx context.Context, mod api.Module, pVTab, ppCur ptr_t)
|
||||
vtabPutHandle(ctx, mod, ppCur, cursor)
|
||||
}
|
||||
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, pVTab, _VTAB_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorCloseCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t {
|
||||
err := vtabDelHandle(ctx, mod, pCur)
|
||||
return vtabError(ctx, mod, 0, _VTAB_ERROR, err)
|
||||
return vtabError(ctx, mod, 0, _PTR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorFilterCallback(ctx context.Context, mod api.Module, pCur ptr_t, idxNum int32, idxStr ptr_t, nArg int32, pArg ptr_t) res_t {
|
||||
@@ -609,7 +607,7 @@ func cursorFilterCallback(ctx context.Context, mod api.Module, pCur ptr_t, idxNu
|
||||
|
||||
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
|
||||
err := cursor.Filter(int(idxNum), idxName, *args...)
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorEOFCallback(ctx context.Context, mod api.Module, pCur ptr_t) int32 {
|
||||
@@ -623,14 +621,14 @@ func cursorEOFCallback(ctx context.Context, mod api.Module, pCur ptr_t) int32 {
|
||||
func cursorNextCallback(ctx context.Context, mod api.Module, pCur ptr_t) res_t {
|
||||
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
|
||||
err := cursor.Next()
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorColumnCallback(ctx context.Context, mod api.Module, pCur, pCtx ptr_t, n int32) res_t {
|
||||
cursor := vtabGetHandle(ctx, mod, pCur).(VTabCursor)
|
||||
db := ctx.Value(connKey{}).(*Conn)
|
||||
err := cursor.Column(Context{db, pCtx}, int(n))
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID ptr_t) res_t {
|
||||
@@ -641,7 +639,7 @@ func cursorRowIDCallback(ctx context.Context, mod api.Module, pCur, pRowID ptr_t
|
||||
util.Write64(mod, pRowID, rowID)
|
||||
}
|
||||
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err)
|
||||
return vtabError(ctx, mod, pCur, _CURSOR_ERROR, err, ERROR)
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -650,10 +648,10 @@ const (
|
||||
_CURSOR_ERROR
|
||||
)
|
||||
|
||||
func vtabError(ctx context.Context, mod api.Module, ptr ptr_t, kind uint32, err error) res_t {
|
||||
func vtabError(ctx context.Context, mod api.Module, ptr ptr_t, kind uint32, err error, def ErrorCode) res_t {
|
||||
const zErrMsgOffset = 8
|
||||
msg, code := errorCode(err, ERROR)
|
||||
if msg != "" && ptr != 0 {
|
||||
msg, code := errorCode(err, def)
|
||||
if ptr != 0 && msg != "" {
|
||||
switch kind {
|
||||
case _VTAB_ERROR:
|
||||
ptr = ptr + zErrMsgOffset // zErrMsg
|
||||
|
||||
Reference in New Issue
Block a user