diff --git a/README.md b/README.md index 8c4908f..e947214 100644 --- a/README.md +++ b/README.md @@ -15,5 +15,5 @@ Roadmap: - [x] port [`test_demovfs.c`](https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c) to Go - branch [`wasi`](https://github.com/ncruces/go-sqlite3/tree/wasi) uses `test_demovfs.c` directly - [x] come up with a simple, nice API, enough for simple queries -- [ ] file locking, compatible with SQLite on Windows/Unix -- [ ] ~shared-memory, compatible with SQLite on Windows/Unix~ \ No newline at end of file +- [x] file locking, compatible with SQLite on Unix +- [ ] file locking, compatible with SQLite on Windows \ No newline at end of file diff --git a/const.go b/const.go index 0904b87..a5f2ddf 100644 --- a/const.go +++ b/const.go @@ -47,82 +47,85 @@ const ( WARNING ErrorCode = 28 /* Warnings from sqlite3_log() */ ) -type ExtendedErrorCode uint16 +type ( + ExtendedErrorCode uint16 + xErrorCode = ExtendedErrorCode +) const ( - ERROR_MISSING_COLLSEQ = ExtendedErrorCode(ERROR) | (1 << 8) - ERROR_RETRY = ExtendedErrorCode(ERROR) | (2 << 8) - ERROR_SNAPSHOT = ExtendedErrorCode(ERROR) | (3 << 8) - IOERR_READ = ExtendedErrorCode(IOERR) | (1 << 8) - IOERR_SHORT_READ = ExtendedErrorCode(IOERR) | (2 << 8) - IOERR_WRITE = ExtendedErrorCode(IOERR) | (3 << 8) - IOERR_FSYNC = ExtendedErrorCode(IOERR) | (4 << 8) - IOERR_DIR_FSYNC = ExtendedErrorCode(IOERR) | (5 << 8) - IOERR_TRUNCATE = ExtendedErrorCode(IOERR) | (6 << 8) - IOERR_FSTAT = ExtendedErrorCode(IOERR) | (7 << 8) - IOERR_UNLOCK = ExtendedErrorCode(IOERR) | (8 << 8) - IOERR_RDLOCK = ExtendedErrorCode(IOERR) | (9 << 8) - IOERR_DELETE = ExtendedErrorCode(IOERR) | (10 << 8) - IOERR_BLOCKED = ExtendedErrorCode(IOERR) | (11 << 8) - IOERR_NOMEM = ExtendedErrorCode(IOERR) | (12 << 8) - IOERR_ACCESS = ExtendedErrorCode(IOERR) | (13 << 8) - IOERR_CHECKRESERVEDLOCK = ExtendedErrorCode(IOERR) | (14 << 8) - IOERR_LOCK = ExtendedErrorCode(IOERR) | (15 << 8) - IOERR_CLOSE = ExtendedErrorCode(IOERR) | (16 << 8) - IOERR_DIR_CLOSE = ExtendedErrorCode(IOERR) | (17 << 8) - IOERR_SHMOPEN = ExtendedErrorCode(IOERR) | (18 << 8) - IOERR_SHMSIZE = ExtendedErrorCode(IOERR) | (19 << 8) - IOERR_SHMLOCK = ExtendedErrorCode(IOERR) | (20 << 8) - IOERR_SHMMAP = ExtendedErrorCode(IOERR) | (21 << 8) - IOERR_SEEK = ExtendedErrorCode(IOERR) | (22 << 8) - IOERR_DELETE_NOENT = ExtendedErrorCode(IOERR) | (23 << 8) - IOERR_MMAP = ExtendedErrorCode(IOERR) | (24 << 8) - IOERR_GETTEMPPATH = ExtendedErrorCode(IOERR) | (25 << 8) - IOERR_CONVPATH = ExtendedErrorCode(IOERR) | (26 << 8) - IOERR_VNODE = ExtendedErrorCode(IOERR) | (27 << 8) - IOERR_AUTH = ExtendedErrorCode(IOERR) | (28 << 8) - IOERR_BEGIN_ATOMIC = ExtendedErrorCode(IOERR) | (29 << 8) - IOERR_COMMIT_ATOMIC = ExtendedErrorCode(IOERR) | (30 << 8) - IOERR_ROLLBACK_ATOMIC = ExtendedErrorCode(IOERR) | (31 << 8) - IOERR_DATA = ExtendedErrorCode(IOERR) | (32 << 8) - IOERR_CORRUPTFS = ExtendedErrorCode(IOERR) | (33 << 8) - LOCKED_SHAREDCACHE = ExtendedErrorCode(LOCKED) | (1 << 8) - LOCKED_VTAB = ExtendedErrorCode(LOCKED) | (2 << 8) - BUSY_RECOVERY = ExtendedErrorCode(BUSY) | (1 << 8) - BUSY_SNAPSHOT = ExtendedErrorCode(BUSY) | (2 << 8) - BUSY_TIMEOUT = ExtendedErrorCode(BUSY) | (3 << 8) - CANTOPEN_NOTEMPDIR = ExtendedErrorCode(CANTOPEN) | (1 << 8) - CANTOPEN_ISDIR = ExtendedErrorCode(CANTOPEN) | (2 << 8) - CANTOPEN_FULLPATH = ExtendedErrorCode(CANTOPEN) | (3 << 8) - CANTOPEN_CONVPATH = ExtendedErrorCode(CANTOPEN) | (4 << 8) - CANTOPEN_DIRTYWAL = ExtendedErrorCode(CANTOPEN) | (5 << 8) /* Not Used */ - CANTOPEN_SYMLINK = ExtendedErrorCode(CANTOPEN) | (6 << 8) - CORRUPT_VTAB = ExtendedErrorCode(CORRUPT) | (1 << 8) - CORRUPT_SEQUENCE = ExtendedErrorCode(CORRUPT) | (2 << 8) - CORRUPT_INDEX = ExtendedErrorCode(CORRUPT) | (3 << 8) - READONLY_RECOVERY = ExtendedErrorCode(READONLY) | (1 << 8) - READONLY_CANTLOCK = ExtendedErrorCode(READONLY) | (2 << 8) - READONLY_ROLLBACK = ExtendedErrorCode(READONLY) | (3 << 8) - READONLY_DBMOVED = ExtendedErrorCode(READONLY) | (4 << 8) - READONLY_CANTINIT = ExtendedErrorCode(READONLY) | (5 << 8) - READONLY_DIRECTORY = ExtendedErrorCode(READONLY) | (6 << 8) - ABORT_ROLLBACK = ExtendedErrorCode(ABORT) | (2 << 8) - CONSTRAINT_CHECK = ExtendedErrorCode(CONSTRAINT) | (1 << 8) - CONSTRAINT_COMMITHOOK = ExtendedErrorCode(CONSTRAINT) | (2 << 8) - CONSTRAINT_FOREIGNKEY = ExtendedErrorCode(CONSTRAINT) | (3 << 8) - CONSTRAINT_FUNCTION = ExtendedErrorCode(CONSTRAINT) | (4 << 8) - CONSTRAINT_NOTNULL = ExtendedErrorCode(CONSTRAINT) | (5 << 8) - CONSTRAINT_PRIMARYKEY = ExtendedErrorCode(CONSTRAINT) | (6 << 8) - CONSTRAINT_TRIGGER = ExtendedErrorCode(CONSTRAINT) | (7 << 8) - CONSTRAINT_UNIQUE = ExtendedErrorCode(CONSTRAINT) | (8 << 8) - CONSTRAINT_VTAB = ExtendedErrorCode(CONSTRAINT) | (9 << 8) - CONSTRAINT_ROWID = ExtendedErrorCode(CONSTRAINT) | (10 << 8) - CONSTRAINT_PINNED = ExtendedErrorCode(CONSTRAINT) | (11 << 8) - CONSTRAINT_DATATYPE = ExtendedErrorCode(CONSTRAINT) | (12 << 8) - NOTICE_RECOVER_WAL = ExtendedErrorCode(NOTICE) | (1 << 8) - NOTICE_RECOVER_ROLLBACK = ExtendedErrorCode(NOTICE) | (2 << 8) - WARNING_AUTOINDEX = ExtendedErrorCode(WARNING) | (1 << 8) - AUTH_USER = ExtendedErrorCode(AUTH) | (1 << 8) + ERROR_MISSING_COLLSEQ ExtendedErrorCode = xErrorCode(ERROR) | (1 << 8) + ERROR_RETRY ExtendedErrorCode = xErrorCode(ERROR) | (2 << 8) + ERROR_SNAPSHOT ExtendedErrorCode = xErrorCode(ERROR) | (3 << 8) + IOERR_READ ExtendedErrorCode = xErrorCode(IOERR) | (1 << 8) + IOERR_SHORT_READ ExtendedErrorCode = xErrorCode(IOERR) | (2 << 8) + IOERR_WRITE ExtendedErrorCode = xErrorCode(IOERR) | (3 << 8) + IOERR_FSYNC ExtendedErrorCode = xErrorCode(IOERR) | (4 << 8) + IOERR_DIR_FSYNC ExtendedErrorCode = xErrorCode(IOERR) | (5 << 8) + IOERR_TRUNCATE ExtendedErrorCode = xErrorCode(IOERR) | (6 << 8) + IOERR_FSTAT ExtendedErrorCode = xErrorCode(IOERR) | (7 << 8) + IOERR_UNLOCK ExtendedErrorCode = xErrorCode(IOERR) | (8 << 8) + IOERR_RDLOCK ExtendedErrorCode = xErrorCode(IOERR) | (9 << 8) + IOERR_DELETE ExtendedErrorCode = xErrorCode(IOERR) | (10 << 8) + IOERR_BLOCKED ExtendedErrorCode = xErrorCode(IOERR) | (11 << 8) + IOERR_NOMEM ExtendedErrorCode = xErrorCode(IOERR) | (12 << 8) + IOERR_ACCESS ExtendedErrorCode = xErrorCode(IOERR) | (13 << 8) + IOERR_CHECKRESERVEDLOCK ExtendedErrorCode = xErrorCode(IOERR) | (14 << 8) + IOERR_LOCK ExtendedErrorCode = xErrorCode(IOERR) | (15 << 8) + IOERR_CLOSE ExtendedErrorCode = xErrorCode(IOERR) | (16 << 8) + IOERR_DIR_CLOSE ExtendedErrorCode = xErrorCode(IOERR) | (17 << 8) + IOERR_SHMOPEN ExtendedErrorCode = xErrorCode(IOERR) | (18 << 8) + IOERR_SHMSIZE ExtendedErrorCode = xErrorCode(IOERR) | (19 << 8) + IOERR_SHMLOCK ExtendedErrorCode = xErrorCode(IOERR) | (20 << 8) + IOERR_SHMMAP ExtendedErrorCode = xErrorCode(IOERR) | (21 << 8) + IOERR_SEEK ExtendedErrorCode = xErrorCode(IOERR) | (22 << 8) + IOERR_DELETE_NOENT ExtendedErrorCode = xErrorCode(IOERR) | (23 << 8) + IOERR_MMAP ExtendedErrorCode = xErrorCode(IOERR) | (24 << 8) + IOERR_GETTEMPPATH ExtendedErrorCode = xErrorCode(IOERR) | (25 << 8) + IOERR_CONVPATH ExtendedErrorCode = xErrorCode(IOERR) | (26 << 8) + IOERR_VNODE ExtendedErrorCode = xErrorCode(IOERR) | (27 << 8) + IOERR_AUTH ExtendedErrorCode = xErrorCode(IOERR) | (28 << 8) + IOERR_BEGIN_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (29 << 8) + IOERR_COMMIT_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (30 << 8) + IOERR_ROLLBACK_ATOMIC ExtendedErrorCode = xErrorCode(IOERR) | (31 << 8) + IOERR_DATA ExtendedErrorCode = xErrorCode(IOERR) | (32 << 8) + IOERR_CORRUPTFS ExtendedErrorCode = xErrorCode(IOERR) | (33 << 8) + LOCKED_SHAREDCACHE ExtendedErrorCode = xErrorCode(LOCKED) | (1 << 8) + LOCKED_VTAB ExtendedErrorCode = xErrorCode(LOCKED) | (2 << 8) + BUSY_RECOVERY ExtendedErrorCode = xErrorCode(BUSY) | (1 << 8) + BUSY_SNAPSHOT ExtendedErrorCode = xErrorCode(BUSY) | (2 << 8) + BUSY_TIMEOUT ExtendedErrorCode = xErrorCode(BUSY) | (3 << 8) + CANTOPEN_NOTEMPDIR ExtendedErrorCode = xErrorCode(CANTOPEN) | (1 << 8) + CANTOPEN_ISDIR ExtendedErrorCode = xErrorCode(CANTOPEN) | (2 << 8) + CANTOPEN_FULLPATH ExtendedErrorCode = xErrorCode(CANTOPEN) | (3 << 8) + CANTOPEN_CONVPATH ExtendedErrorCode = xErrorCode(CANTOPEN) | (4 << 8) + CANTOPEN_DIRTYWAL ExtendedErrorCode = xErrorCode(CANTOPEN) | (5 << 8) /* Not Used */ + CANTOPEN_SYMLINK ExtendedErrorCode = xErrorCode(CANTOPEN) | (6 << 8) + CORRUPT_VTAB ExtendedErrorCode = xErrorCode(CORRUPT) | (1 << 8) + CORRUPT_SEQUENCE ExtendedErrorCode = xErrorCode(CORRUPT) | (2 << 8) + CORRUPT_INDEX ExtendedErrorCode = xErrorCode(CORRUPT) | (3 << 8) + READONLY_RECOVERY ExtendedErrorCode = xErrorCode(READONLY) | (1 << 8) + READONLY_CANTLOCK ExtendedErrorCode = xErrorCode(READONLY) | (2 << 8) + READONLY_ROLLBACK ExtendedErrorCode = xErrorCode(READONLY) | (3 << 8) + READONLY_DBMOVED ExtendedErrorCode = xErrorCode(READONLY) | (4 << 8) + READONLY_CANTINIT ExtendedErrorCode = xErrorCode(READONLY) | (5 << 8) + READONLY_DIRECTORY ExtendedErrorCode = xErrorCode(READONLY) | (6 << 8) + ABORT_ROLLBACK ExtendedErrorCode = xErrorCode(ABORT) | (2 << 8) + CONSTRAINT_CHECK ExtendedErrorCode = xErrorCode(CONSTRAINT) | (1 << 8) + CONSTRAINT_COMMITHOOK ExtendedErrorCode = xErrorCode(CONSTRAINT) | (2 << 8) + CONSTRAINT_FOREIGNKEY ExtendedErrorCode = xErrorCode(CONSTRAINT) | (3 << 8) + CONSTRAINT_FUNCTION ExtendedErrorCode = xErrorCode(CONSTRAINT) | (4 << 8) + CONSTRAINT_NOTNULL ExtendedErrorCode = xErrorCode(CONSTRAINT) | (5 << 8) + CONSTRAINT_PRIMARYKEY ExtendedErrorCode = xErrorCode(CONSTRAINT) | (6 << 8) + CONSTRAINT_TRIGGER ExtendedErrorCode = xErrorCode(CONSTRAINT) | (7 << 8) + CONSTRAINT_UNIQUE ExtendedErrorCode = xErrorCode(CONSTRAINT) | (8 << 8) + CONSTRAINT_VTAB ExtendedErrorCode = xErrorCode(CONSTRAINT) | (9 << 8) + CONSTRAINT_ROWID ExtendedErrorCode = xErrorCode(CONSTRAINT) | (10 << 8) + CONSTRAINT_PINNED ExtendedErrorCode = xErrorCode(CONSTRAINT) | (11 << 8) + CONSTRAINT_DATATYPE ExtendedErrorCode = xErrorCode(CONSTRAINT) | (12 << 8) + NOTICE_RECOVER_WAL ExtendedErrorCode = xErrorCode(NOTICE) | (1 << 8) + NOTICE_RECOVER_ROLLBACK ExtendedErrorCode = xErrorCode(NOTICE) | (2 << 8) + WARNING_AUTOINDEX ExtendedErrorCode = xErrorCode(WARNING) | (1 << 8) + AUTH_USER ExtendedErrorCode = xErrorCode(AUTH) | (1 << 8) ) type OpenFlag uint32 @@ -160,7 +163,7 @@ const ( ACCESS_READ AccessFlag = 2 /* Unused */ ) -type PrepareFlag uint +type PrepareFlag uint32 const ( PREPARE_PERSISTENT PrepareFlag = 0x01 @@ -168,7 +171,7 @@ const ( PREPARE_NO_VTAB PrepareFlag = 0x04 ) -type Datatype uint +type Datatype uint32 const ( INTEGER Datatype = 1 diff --git a/vfs_unix.go b/vfs_unix.go index 0d89108..d462e37 100644 --- a/vfs_unix.go +++ b/vfs_unix.go @@ -12,7 +12,7 @@ func deleteOnClose(f *os.File) { _ = os.Remove(f.Name()) } -func (l *vfsFileLocker) GetShared() ExtendedErrorCode { +func (l *vfsFileLocker) GetShared() xErrorCode { // A PENDING lock is needed before acquiring a SHARED lock. if err := l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_RDLCK, @@ -40,7 +40,7 @@ func (l *vfsFileLocker) GetShared() ExtendedErrorCode { return rc } -func (l *vfsFileLocker) GetReserved() ExtendedErrorCode { +func (l *vfsFileLocker) GetReserved() xErrorCode { // Acquire the RESERVED lock. return l.errorCode(l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_WRLCK, @@ -49,7 +49,7 @@ func (l *vfsFileLocker) GetReserved() ExtendedErrorCode { }), IOERR_LOCK) } -func (l *vfsFileLocker) GetPending() ExtendedErrorCode { +func (l *vfsFileLocker) GetPending() xErrorCode { // Acquire the PENDING lock. return l.errorCode(l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_WRLCK, @@ -58,7 +58,7 @@ func (l *vfsFileLocker) GetPending() ExtendedErrorCode { }), IOERR_LOCK) } -func (l *vfsFileLocker) GetExclusive() ExtendedErrorCode { +func (l *vfsFileLocker) GetExclusive() xErrorCode { // Acquire the EXCLUSIVE lock. return l.errorCode(l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_WRLCK, @@ -67,7 +67,7 @@ func (l *vfsFileLocker) GetExclusive() ExtendedErrorCode { }), IOERR_LOCK) } -func (l *vfsFileLocker) Downgrade() ExtendedErrorCode { +func (l *vfsFileLocker) Downgrade() xErrorCode { // Downgrade to a SHARED lock. if err := l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_RDLCK, @@ -93,7 +93,7 @@ func (l *vfsFileLocker) Downgrade() ExtendedErrorCode { return _OK } -func (l *vfsFileLocker) Release() ExtendedErrorCode { +func (l *vfsFileLocker) Release() xErrorCode { // Release all locks. if err := l.fcntlSetLock(&syscall.Flock_t{ Type: syscall.F_UNLCK, @@ -103,7 +103,7 @@ func (l *vfsFileLocker) Release() ExtendedErrorCode { return _OK } -func (l *vfsFileLocker) CheckReserved() (bool, ExtendedErrorCode) { +func (l *vfsFileLocker) CheckReserved() (bool, xErrorCode) { // Test the RESERVED lock. lock := syscall.Flock_t{ Type: syscall.F_RDLCK, @@ -142,7 +142,7 @@ func (l *vfsFileLocker) fcntlSetLock(lock *syscall.Flock_t) error { return syscall.FcntlFlock(l.file.Fd(), F_SETLK, lock) } -func (*vfsFileLocker) errorCode(err error, def ExtendedErrorCode) ExtendedErrorCode { +func (*vfsFileLocker) errorCode(err error, def xErrorCode) xErrorCode { if err == nil { return _OK } @@ -155,9 +155,9 @@ func (*vfsFileLocker) errorCode(err error, def ExtendedErrorCode) ExtendedErrorC case syscall.ENOLCK: case syscall.EDEADLK: case syscall.ETIMEDOUT: - return ExtendedErrorCode(BUSY) + return xErrorCode(BUSY) case syscall.EPERM: - return ExtendedErrorCode(PERM) + return xErrorCode(PERM) } } return def diff --git a/vfs_windows.go b/vfs_windows.go index d4cb3b2..3e0a277 100644 --- a/vfs_windows.go +++ b/vfs_windows.go @@ -4,30 +4,30 @@ import "os" func deleteOnClose(f *os.File) {} -func (l *vfsFileLocker) GetShared() ExtendedErrorCode { +func (l *vfsFileLocker) GetShared() xErrorCode { return _OK } -func (l *vfsFileLocker) GetReserved() ExtendedErrorCode { +func (l *vfsFileLocker) GetReserved() xErrorCode { return _OK } -func (l *vfsFileLocker) GetPending() ExtendedErrorCode { +func (l *vfsFileLocker) GetPending() xErrorCode { return _OK } -func (l *vfsFileLocker) GetExclusive() ExtendedErrorCode { +func (l *vfsFileLocker) GetExclusive() xErrorCode { return _OK } -func (l *vfsFileLocker) Downgrade() ExtendedErrorCode { +func (l *vfsFileLocker) Downgrade() xErrorCode { return _OK } -func (l *vfsFileLocker) Release() ExtendedErrorCode { +func (l *vfsFileLocker) Release() xErrorCode { return _OK } -func (l *vfsFileLocker) CheckReserved() (bool, ExtendedErrorCode) { +func (l *vfsFileLocker) CheckReserved() (bool, xErrorCode) { return false, _OK }