Files
hanzo-devandClaude Opus 4.8 764539773a feat: canonical Hanzo SQLite — rename module + native encrypted hanzovfs
Fork of ncruces/go-sqlite3 (MIT, retained). Renames module to
github.com/hanzoai/sqlite3 (wasm blob stays upstream ncruces/go-sqlite3-wasm)
and adds the hanzovfs package: a pure-Go, no-FUSE SQLite VFS that seals pages
with ChaCha20-Poly1305 (per-tenant DEK, HIP-0302) for per-tenant SQLite ⇒
hanzoai/vfs ⇒ S3.

Deprecates modernc.org/sqlite (no custom-VFS hook) and direct ncruces use.
Benchmarked 3.6x faster writes / ~92x faster point-reads than FUSE; encryption ~free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 20:32:43 +00:00

219 lines
6.5 KiB
Go

// Package sqlite3 wraps the C SQLite API.
package sqlite3
import (
"context"
"crypto/rand"
"math/bits"
"time"
_ "unsafe"
sqlite3_wasm "github.com/ncruces/go-sqlite3-wasm/v3"
"github.com/hanzoai/sqlite3/internal/errutil"
"github.com/hanzoai/sqlite3/internal/sqlite3_wrap"
"github.com/hanzoai/sqlite3/vfs"
"github.com/ncruces/julianday"
)
type configKey struct{}
// WithMaxMemory returns a derived context that configures
// each SQLite connection not to use more than max amount of memory.
func WithMaxMemory(ctx context.Context, max int64) context.Context {
if max < 0 || max > 65536*65536 {
panic(errutil.OOMErr)
}
return context.WithValue(ctx, configKey{}, max/65536)
}
var _ sqlite3_wasm.Xenv = &env{}
type env struct{ *sqlite3_wrap.Wrapper }
func createWrapper(ctx context.Context) (*sqlite3_wrap.Wrapper, error) {
mem := &sqlite3_wrap.Memory{Max: 4096} // 256MB
if bits.UintSize < 64 {
mem.Max = 512 // 32MB
}
mem.Grow(5, mem.Max) // 320KB
env := &env{&sqlite3_wrap.Wrapper{Memory: mem}}
env.Module = sqlite3_wasm.New(env)
env.X_initialize()
if cfg, ok := ctx.Value(configKey{}).(int64); ok {
mem.Max = max(cfg, int64(len(mem.Buf))/65536)
env.Xsqlite3_soft_heap_limit64((mem.Max - 8) * 65536)
}
return env.Wrapper, nil
}
func (e *env) Xmemory() sqlite3_wasm.Memory { return e.Memory }
// VFS functions.
func (e *env) Xgo_randomness(pVfs, nByte, zByte int32) int32 {
mem := e.Bytes(ptr_t(zByte), int64(nByte))
n, _ := rand.Reader.Read(mem)
return int32(n)
}
func (e *env) Xgo_sleep(pVfs, nMicro int32) int32 {
time.Sleep(time.Duration(nMicro) * time.Microsecond)
return _OK
}
func (e *env) Xgo_current_time_64(pVfs, nMicro int32) int32 {
day, nsec := julianday.Date(time.Now())
msec := day*86_400_000 + nsec/1_000_000
e.Write64(ptr_t(nMicro), uint64(msec))
return int32(_OK)
}
func (e *env) Xgo_vfs_find(zVfsName int32) int32 {
if vfs.Find(e.ReadString(ptr_t(zVfsName), _MAX_NAME)) != nil {
return 1
}
return 0
}
//go:linkname vfsFullPathname github.com/hanzoai/sqlite3/vfs.vfsFullPathname
func vfsFullPathname(_ *sqlite3_wrap.Wrapper, v0, v1, v2, v3 int32) int32
func (e *env) Xgo_full_pathname(v0, v1, v2, v3 int32) int32 {
return vfsFullPathname(e.Wrapper, v0, v1, v2, v3)
}
//go:linkname vfsDelete github.com/hanzoai/sqlite3/vfs.vfsDelete
func vfsDelete(_ *sqlite3_wrap.Wrapper, v0, v1, v2 int32) int32
func (e *env) Xgo_delete(v0, v1, v2 int32) int32 {
return vfsDelete(e.Wrapper, v0, v1, v2)
}
//go:linkname vfsAccess github.com/hanzoai/sqlite3/vfs.vfsAccess
func vfsAccess(_ *sqlite3_wrap.Wrapper, v0, v1, v2, v3 int32) int32
func (e *env) Xgo_access(v0, v1, v2, v3 int32) int32 {
return vfsAccess(e.Wrapper, v0, v1, v2, v3)
}
//go:linkname vfsOpen github.com/hanzoai/sqlite3/vfs.vfsOpen
func vfsOpen(_ *sqlite3_wrap.Wrapper, v0, v1, v2, v3, v4, v5 int32) int32
func (e *env) Xgo_open(v0, v1, v2, v3, v4, v5 int32) int32 {
return vfsOpen(e.Wrapper, v0, v1, v2, v3, v4, v5)
}
//go:linkname vfsClose github.com/hanzoai/sqlite3/vfs.vfsClose
func vfsClose(_ *sqlite3_wrap.Wrapper, v0 int32) int32
func (e *env) Xgo_close(v0 int32) int32 {
return vfsClose(e.Wrapper, v0)
}
//go:linkname vfsRead github.com/hanzoai/sqlite3/vfs.vfsRead
func vfsRead(_ *sqlite3_wrap.Wrapper, v0, v1, v2 int32, v3 int64) int32
func (e *env) Xgo_read(v0, v1, v2 int32, v3 int64) int32 {
return vfsRead(e.Wrapper, v0, v1, v2, v3)
}
//go:linkname vfsWrite github.com/hanzoai/sqlite3/vfs.vfsWrite
func vfsWrite(_ *sqlite3_wrap.Wrapper, v0, v1, v2 int32, v3 int64) int32
func (e *env) Xgo_write(v0, v1, v2 int32, v3 int64) int32 {
return vfsWrite(e.Wrapper, v0, v1, v2, v3)
}
//go:linkname vfsTruncate github.com/hanzoai/sqlite3/vfs.vfsTruncate
func vfsTruncate(_ *sqlite3_wrap.Wrapper, v0 int32, v1 int64) int32
func (e *env) Xgo_truncate(v0 int32, v1 int64) int32 {
return vfsTruncate(e.Wrapper, v0, v1)
}
//go:linkname vfsSync github.com/hanzoai/sqlite3/vfs.vfsSync
func vfsSync(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_sync(v0, v1 int32) int32 {
return vfsSync(e.Wrapper, v0, v1)
}
//go:linkname vfsFileSize github.com/hanzoai/sqlite3/vfs.vfsFileSize
func vfsFileSize(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_file_size(v0, v1 int32) int32 {
return vfsFileSize(e.Wrapper, v0, v1)
}
//go:linkname vfsLock github.com/hanzoai/sqlite3/vfs.vfsLock
func vfsLock(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_lock(v0, v1 int32) int32 {
return vfsLock(e.Wrapper, v0, v1)
}
//go:linkname vfsUnlock github.com/hanzoai/sqlite3/vfs.vfsUnlock
func vfsUnlock(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_unlock(v0, v1 int32) int32 {
return vfsUnlock(e.Wrapper, v0, v1)
}
//go:linkname vfsCheckReservedLock github.com/hanzoai/sqlite3/vfs.vfsCheckReservedLock
func vfsCheckReservedLock(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_check_reserved_lock(v0, v1 int32) int32 {
return vfsCheckReservedLock(e.Wrapper, v0, v1)
}
//go:linkname vfsFileControl github.com/hanzoai/sqlite3/vfs.vfsFileControl
func vfsFileControl(_ *sqlite3_wrap.Wrapper, v0, v1, v2 int32) int32
func (e *env) Xgo_file_control(v0, v1, v2 int32) int32 {
return vfsFileControl(e.Wrapper, v0, v1, v2)
}
//go:linkname vfsSectorSize github.com/hanzoai/sqlite3/vfs.vfsSectorSize
func vfsSectorSize(_ *sqlite3_wrap.Wrapper, v0 int32) int32
func (e *env) Xgo_sector_size(v0 int32) int32 {
return vfsSectorSize(e.Wrapper, v0)
}
//go:linkname vfsDeviceCharacteristics github.com/hanzoai/sqlite3/vfs.vfsDeviceCharacteristics
func vfsDeviceCharacteristics(_ *sqlite3_wrap.Wrapper, v0 int32) int32
func (e *env) Xgo_device_characteristics(v0 int32) int32 {
return vfsDeviceCharacteristics(e.Wrapper, v0)
}
//go:linkname vfsShmBarrier github.com/hanzoai/sqlite3/vfs.vfsShmBarrier
func vfsShmBarrier(_ *sqlite3_wrap.Wrapper, v0 int32)
func (e *env) Xgo_shm_barrier(v0 int32) {
vfsShmBarrier(e.Wrapper, v0)
}
//go:linkname vfsShmMap github.com/hanzoai/sqlite3/vfs.vfsShmMap
func vfsShmMap(_ *sqlite3_wrap.Wrapper, v0, v1, v2, v3, v4 int32) int32
func (e *env) Xgo_shm_map(v0, v1, v2, v3, v4 int32) int32 {
return vfsShmMap(e.Wrapper, v0, v1, v2, v3, v4)
}
//go:linkname vfsShmLock github.com/hanzoai/sqlite3/vfs.vfsShmLock
func vfsShmLock(_ *sqlite3_wrap.Wrapper, v0, v1, v2, v3 int32) int32
func (e *env) Xgo_shm_lock(v0, v1, v2, v3 int32) int32 {
return vfsShmLock(e.Wrapper, v0, v1, v2, v3)
}
//go:linkname vfsShmUnmap github.com/hanzoai/sqlite3/vfs.vfsShmUnmap
func vfsShmUnmap(_ *sqlite3_wrap.Wrapper, v0, v1 int32) int32
func (e *env) Xgo_shm_unmap(v0, v1 int32) int32 {
return vfsShmUnmap(e.Wrapper, v0, v1)
}