Skip to content

Commit b65e894

Browse files
authored
Improve error reporting. (#327)
1 parent 0b040d3 commit b65e894

22 files changed

+203
-191
lines changed

.github/workflows/libc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
test:
1111
strategy:
1212
matrix:
13-
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-13, macos-15]
13+
os: [ubuntu-24.04, ubuntu-24.04-arm, macos-15, macos-15-intel]
1414
runs-on: ${{ matrix.os }}
1515

1616
steps:

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ jobs:
224224
run: go test -v ./...
225225

226226
test-macintel:
227-
runs-on: macos-13
227+
runs-on: macos-15-intel
228228
needs: test
229229

230230
steps:

error.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ func (e *Error) Error() string {
4040
b.WriteString(": ")
4141
b.WriteString(e.msg)
4242
}
43+
if e.sys != nil {
44+
b.WriteString(": ")
45+
b.WriteString(e.sys.Error())
46+
}
4347

4448
return b.String()
4549
}

sqlite.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func (sqlt *sqlite) error(rc res_t, handle ptr_t, sql ...string) error {
132132
msg = strings.TrimPrefix(msg, "sqlite3: ")
133133
msg = strings.TrimPrefix(msg, util.ErrorCodeString(rc)[len("sqlite3: "):])
134134
msg = strings.TrimPrefix(msg, ": ")
135-
if msg == "not an error" {
135+
if msg == "" || msg == "not an error" {
136136
msg = ""
137137
}
138138
}

vfs/api.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import (
1010

1111
// A VFS defines the interface between the SQLite core and the underlying operating system.
1212
//
13-
// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite.
13+
// Use [SystemError], sqlite3.ErrorCode, or sqlite3.ExtendedErrorCode
14+
// to return specific error codes to SQLite.
1415
//
1516
// https://sqlite.org/c3ref/vfs.html
1617
type VFS interface {
@@ -31,8 +32,9 @@ type VFSFilename interface {
3132

3233
// A File represents an open file in the OS interface layer.
3334
//
34-
// Use sqlite3.ErrorCode or sqlite3.ExtendedErrorCode to return specific error codes to SQLite.
35-
// In particular, sqlite3.BUSY is necessary to correctly implement lock methods.
35+
// Use [SystemError], sqlite3.ErrorCode, or sqlite3.ExtendedErrorCode
36+
// to return specific error codes to SQLite.
37+
// In particular, sqlite3.BUSY is needed to correctly implement lock methods.
3638
//
3739
// https://sqlite.org/c3ref/io_methods.html
3840
type File interface {

vfs/const.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (e _ErrorCode) Error() string {
2424
}
2525

2626
const (
27-
_OK _ErrorCode = util.OK
27+
_OK = util.OK
2828
_ERROR _ErrorCode = util.ERROR
2929
_PERM _ErrorCode = util.PERM
3030
_BUSY _ErrorCode = util.BUSY

vfs/file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func (vfsOS) Delete(path string, syncDir bool) error {
4848
if isUnix && syncDir {
4949
f, err := os.Open(filepath.Dir(path))
5050
if err != nil {
51-
return _OK
51+
return nil
5252
}
5353
defer f.Close()
5454
err = osSync(f, 0, SYNC_FULL)

vfs/lock.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ func (f *vfsFile) Lock(lock LockLevel) error {
5151
if f.lock != LOCK_NONE {
5252
panic(util.AssertErr())
5353
}
54-
if rc := osGetSharedLock(f.File); rc != _OK {
55-
return rc
54+
if err := osGetSharedLock(f.File); err != nil {
55+
return err
5656
}
5757
f.lock = LOCK_SHARED
5858
return nil
@@ -62,8 +62,8 @@ func (f *vfsFile) Lock(lock LockLevel) error {
6262
if f.lock != LOCK_SHARED {
6363
panic(util.AssertErr())
6464
}
65-
if rc := osGetReservedLock(f.File); rc != _OK {
66-
return rc
65+
if err := osGetReservedLock(f.File); err != nil {
66+
return err
6767
}
6868
f.lock = LOCK_RESERVED
6969
return nil
@@ -73,8 +73,8 @@ func (f *vfsFile) Lock(lock LockLevel) error {
7373
if f.lock <= LOCK_NONE || f.lock >= LOCK_EXCLUSIVE {
7474
panic(util.AssertErr())
7575
}
76-
if rc := osGetExclusiveLock(f.File, &f.lock); rc != _OK {
77-
return rc
76+
if err := osGetExclusiveLock(f.File, &f.lock); err != nil {
77+
return err
7878
}
7979
f.lock = LOCK_EXCLUSIVE
8080
return nil
@@ -101,14 +101,14 @@ func (f *vfsFile) Unlock(lock LockLevel) error {
101101

102102
switch lock {
103103
case LOCK_SHARED:
104-
rc := osDowngradeLock(f.File, f.lock)
104+
err := osDowngradeLock(f.File, f.lock)
105105
f.lock = LOCK_SHARED
106-
return rc
106+
return err
107107

108108
case LOCK_NONE:
109-
rc := osReleaseLock(f.File, f.lock)
109+
err := osReleaseLock(f.File, f.lock)
110110
f.lock = LOCK_NONE
111-
return rc
111+
return err
112112

113113
default:
114114
panic(util.AssertErr())

vfs/os_bsd.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import (
88
"golang.org/x/sys/unix"
99
)
1010

11-
func osGetSharedLock(file *os.File) _ErrorCode {
11+
func osGetSharedLock(file *os.File) error {
1212
return osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
1313
}
1414

15-
func osGetReservedLock(file *os.File) _ErrorCode {
16-
rc := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
17-
if rc == _BUSY {
15+
func osGetReservedLock(file *os.File) error {
16+
err := osFlock(file, unix.LOCK_EX|unix.LOCK_NB, _IOERR_LOCK)
17+
if err == _BUSY {
1818
// The documentation states that a lock is upgraded by
1919
// releasing the previous lock, then acquiring the new lock.
2020
// Going over the source code of various BSDs, though,
@@ -26,64 +26,64 @@ func osGetReservedLock(file *os.File) _ErrorCode {
2626
// and invoke the busy handler if appropriate.
2727
return _BUSY_SNAPSHOT
2828
}
29-
return rc
29+
return err
3030
}
3131

32-
func osGetExclusiveLock(file *os.File, state *LockLevel) _ErrorCode {
32+
func osGetExclusiveLock(file *os.File, state *LockLevel) error {
3333
if *state >= LOCK_RESERVED {
34-
return _OK
34+
return nil
3535
}
3636
return osGetReservedLock(file)
3737
}
3838

39-
func osDowngradeLock(file *os.File, _ LockLevel) _ErrorCode {
40-
rc := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
41-
if rc == _BUSY {
39+
func osDowngradeLock(file *os.File, _ LockLevel) error {
40+
err := osFlock(file, unix.LOCK_SH|unix.LOCK_NB, _IOERR_RDLOCK)
41+
if err == _BUSY {
4242
// The documentation states that a lock is downgraded by
4343
// releasing the previous lock then acquiring the new lock.
4444
// Going over the source code of various BSDs, though,
4545
// with LOCK_SH|LOCK_NB this should never happen.
4646
// Return IOERR_RDLOCK, as BUSY would cause an assert to fail.
4747
return _IOERR_RDLOCK
4848
}
49-
return _OK
49+
return err
5050
}
5151

52-
func osReleaseLock(file *os.File, _ LockLevel) _ErrorCode {
52+
func osReleaseLock(file *os.File, _ LockLevel) error {
5353
for {
5454
err := unix.Flock(int(file.Fd()), unix.LOCK_UN)
5555
if err == nil {
56-
return _OK
56+
return nil
5757
}
5858
if err != unix.EINTR {
59-
return _IOERR_UNLOCK
59+
return sysError{err, _IOERR_UNLOCK}
6060
}
6161
}
6262
}
6363

64-
func osCheckReservedLock(file *os.File) (bool, _ErrorCode) {
64+
func osCheckReservedLock(file *os.File) (bool, error) {
6565
// Test the RESERVED lock with fcntl(F_GETLK).
6666
// This only works on systems where fcntl and flock are compatible.
6767
// However, SQLite only calls this while holding a shared lock,
6868
// so the difference is immaterial.
69-
lock, rc := osTestLock(file, _RESERVED_BYTE, 1)
70-
return lock == unix.F_WRLCK, rc
69+
lock, err := osTestLock(file, _RESERVED_BYTE, 1, _IOERR_CHECKRESERVEDLOCK)
70+
return lock == unix.F_WRLCK, err
7171
}
7272

73-
func osFlock(file *os.File, how int, def _ErrorCode) _ErrorCode {
73+
func osFlock(file *os.File, how int, def _ErrorCode) error {
7474
err := unix.Flock(int(file.Fd()), how)
7575
return osLockErrorCode(err, def)
7676
}
7777

78-
func osReadLock(file *os.File, start, len int64) _ErrorCode {
78+
func osReadLock(file *os.File, start, len int64) error {
7979
return osLock(file, unix.F_RDLCK, start, len, _IOERR_RDLOCK)
8080
}
8181

82-
func osWriteLock(file *os.File, start, len int64) _ErrorCode {
82+
func osWriteLock(file *os.File, start, len int64) error {
8383
return osLock(file, unix.F_WRLCK, start, len, _IOERR_LOCK)
8484
}
8585

86-
func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCode {
86+
func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) error {
8787
err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &unix.Flock_t{
8888
Type: typ,
8989
Start: start,
@@ -92,7 +92,7 @@ func osLock(file *os.File, typ int16, start, len int64, def _ErrorCode) _ErrorCo
9292
return osLockErrorCode(err, def)
9393
}
9494

95-
func osUnlock(file *os.File, start, len int64) _ErrorCode {
95+
func osUnlock(file *os.File, start, len int64) error {
9696
lock := unix.Flock_t{
9797
Type: unix.F_UNLCK,
9898
Start: start,
@@ -101,10 +101,10 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode {
101101
for {
102102
err := unix.FcntlFlock(file.Fd(), unix.F_SETLK, &lock)
103103
if err == nil {
104-
return _OK
104+
return nil
105105
}
106106
if err != unix.EINTR {
107-
return _IOERR_UNLOCK
107+
return sysError{err, _IOERR_UNLOCK}
108108
}
109109
}
110110
}

vfs/os_darwin.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ func osAllocate(file *os.File, size int64) error {
7575
return file.Truncate(size)
7676
}
7777

78-
func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode {
78+
func osReadLock(file *os.File, start, len int64, timeout time.Duration) error {
7979
return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK)
8080
}
8181

82-
func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode {
82+
func osWriteLock(file *os.File, start, len int64, timeout time.Duration) error {
8383
return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK)
8484
}
8585

86-
func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode {
86+
func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) error {
8787
lock := &flocktimeout_t{fl: unix.Flock_t{
8888
Type: typ,
8989
Start: start,
@@ -103,7 +103,7 @@ func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, d
103103
return osLockErrorCode(err, def)
104104
}
105105

106-
func osUnlock(file *os.File, start, len int64) _ErrorCode {
106+
func osUnlock(file *os.File, start, len int64) error {
107107
lock := unix.Flock_t{
108108
Type: unix.F_UNLCK,
109109
Start: start,
@@ -112,10 +112,10 @@ func osUnlock(file *os.File, start, len int64) _ErrorCode {
112112
for {
113113
err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &lock)
114114
if err == nil {
115-
return _OK
115+
return nil
116116
}
117117
if err != unix.EINTR {
118-
return _IOERR_UNLOCK
118+
return sysError{err, _IOERR_UNLOCK}
119119
}
120120
}
121121
}

0 commit comments

Comments
 (0)