mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Internal API tweaks.
This commit is contained in:
@@ -46,6 +46,13 @@ https://sqlite.org/lang_aggfunc.html
|
||||
|
||||
https://sqlite.org/windowfunctions.html#builtins
|
||||
|
||||
## Boolean aggregates
|
||||
|
||||
- [ ] `ALL(boolean)`
|
||||
- [ ] `ANY(boolean)`
|
||||
- [ ] `EVERY(boolean)`
|
||||
- [ ] `SOME(boolean)`
|
||||
|
||||
## Additional aggregates
|
||||
|
||||
- [X] `MEDIAN(expression)`
|
||||
|
||||
@@ -22,9 +22,9 @@ func newQuantile(kind int) func() sqlite3.AggregateFunction {
|
||||
}
|
||||
|
||||
type quantile struct {
|
||||
kind int
|
||||
nums []float64
|
||||
arg1 []byte
|
||||
kind int
|
||||
}
|
||||
|
||||
func (q *quantile) Step(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package util
|
||||
|
||||
// https://sqlite.com/matrix/rescode.html
|
||||
// https://sqlite.com/rescode.html
|
||||
const (
|
||||
OK = 0 /* Successful result */
|
||||
|
||||
|
||||
@@ -54,6 +54,11 @@ To allow `mmap` to work, each connection needs to reserve up to 4GB of address s
|
||||
To limit the address space each connection reserves,
|
||||
use [`WithMemoryLimitPages`](../tests/testcfg/testcfg.go).
|
||||
|
||||
With [BSD locks](https://man.freebsd.org/cgi/man.cgi?query=flock&sektion=2)
|
||||
a WAL database can only be accessed by a single proccess.
|
||||
Other processes that attempt to access a database locked with BSD locks,
|
||||
will fail with the `SQLITE_PROTOCOL` error code.
|
||||
|
||||
Otherwise, [WAL support is limited](https://sqlite.org/wal.html#noshm),
|
||||
and `EXCLUSIVE` locking mode must be set to create, read, and write WAL databases.
|
||||
To use `EXCLUSIVE` locking mode with the
|
||||
@@ -79,8 +84,9 @@ The VFS can be customized with a few build tags:
|
||||
- `sqlite3_noshm` disables shared memory on all platforms.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The default configuration of this package is compatible with
|
||||
> the standard [Unix and Windows SQLite VFSes](https://sqlite.org/vfs.html#multiple_vfses);
|
||||
> `sqlite3_flock` is compatible with the [`unix-flock` VFS](https://sqlite.org/compile.html#enable_locking_style).
|
||||
> If incompatible file locking is used, accessing databases concurrently with _other_ SQLite libraries
|
||||
> will eventually corrupt data.
|
||||
> The default configuration of this package is compatible with the standard
|
||||
> [Unix and Windows SQLite VFSes](https://sqlite.org/vfs.html#multiple_vfses);
|
||||
> `sqlite3_flock` builds are compatible with the
|
||||
> [`unix-flock` VFS](https://sqlite.org/compile.html#enable_locking_style).
|
||||
> If incompatible file locking is used, accessing databases concurrently with
|
||||
> _other_ SQLite libraries will eventually corrupt data.
|
||||
|
||||
@@ -168,8 +168,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) (uint32, error)
|
||||
shmLock(int32, int32, _ShmFlag) error
|
||||
shmMap(context.Context, api.Module, int32, int32, bool) (uint32, _ErrorCode)
|
||||
shmLock(int32, int32, _ShmFlag) _ErrorCode
|
||||
shmUnmap(bool)
|
||||
io.Closer
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ const (
|
||||
_IOERR_SHMMAP _ErrorCode = util.IOERR_SHMMAP
|
||||
_IOERR_SEEK _ErrorCode = util.IOERR_SEEK
|
||||
_IOERR_DELETE_NOENT _ErrorCode = util.IOERR_DELETE_NOENT
|
||||
_IOERR_GETTEMPPATH _ErrorCode = util.IOERR_GETTEMPPATH
|
||||
_IOERR_BEGIN_ATOMIC _ErrorCode = util.IOERR_BEGIN_ATOMIC
|
||||
_IOERR_COMMIT_ATOMIC _ErrorCode = util.IOERR_COMMIT_ATOMIC
|
||||
_IOERR_ROLLBACK_ATOMIC _ErrorCode = util.IOERR_ROLLBACK_ATOMIC
|
||||
|
||||
@@ -95,6 +95,9 @@ func (vfsOS) OpenFilename(name *Filename, flags OpenFlag) (File, OpenFlag, error
|
||||
f, err = osutil.OpenFile(name.String(), oflags, 0666)
|
||||
}
|
||||
if err != nil {
|
||||
if name == nil {
|
||||
return nil, flags, _IOERR_GETTEMPPATH
|
||||
}
|
||||
if errors.Is(err, syscall.EISDIR) {
|
||||
return nil, flags, _CANTOPEN_ISDIR
|
||||
}
|
||||
|
||||
18
vfs/shm.go
18
vfs/shm.go
@@ -51,7 +51,7 @@ type vfsShm struct {
|
||||
readOnly bool
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmOpen() error {
|
||||
func (s *vfsShm) shmOpen() _ErrorCode {
|
||||
if s.File == nil {
|
||||
var flag int
|
||||
if s.readOnly {
|
||||
@@ -86,17 +86,17 @@ func (s *vfsShm) shmOpen() error {
|
||||
if rc := osReadLock(s.File, _SHM_DMS, 1, 0); rc != _OK {
|
||||
return rc
|
||||
}
|
||||
return nil
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, error) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if int(size)&(unix.Getpagesize()-1) != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
}
|
||||
|
||||
if err := s.shmOpen(); err != nil {
|
||||
return 0, err
|
||||
if rc := s.shmOpen(); rc != _OK {
|
||||
return 0, rc
|
||||
}
|
||||
|
||||
// Check if file is big enough.
|
||||
@@ -106,7 +106,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
if n := (int64(id) + 1) * int64(size); n > o {
|
||||
if !extend {
|
||||
return 0, nil
|
||||
return 0, _OK
|
||||
}
|
||||
err := osAllocate(s.File, n)
|
||||
if err != nil {
|
||||
@@ -122,13 +122,13 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, prot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, _IOERR_SHMMAP
|
||||
}
|
||||
s.regions = append(s.regions, r)
|
||||
return r.Ptr, nil
|
||||
return r.Ptr, _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
// Argument check.
|
||||
if n <= 0 || offset < 0 || offset+n > _SHM_NLOCK {
|
||||
panic(util.AssertErr())
|
||||
|
||||
@@ -96,9 +96,9 @@ func (s *vfsShm) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmOpen() (err error) {
|
||||
func (s *vfsShm) shmOpen() (rc _ErrorCode) {
|
||||
if s.vfsShmFile != nil {
|
||||
return nil
|
||||
return _OK
|
||||
}
|
||||
|
||||
// Open file read-write, as it will be shared.
|
||||
@@ -123,13 +123,13 @@ func (s *vfsShm) shmOpen() (err error) {
|
||||
if g != nil && os.SameFile(fi, g.info) {
|
||||
g.refs++
|
||||
s.vfsShmFile = g
|
||||
return nil
|
||||
return _OK
|
||||
}
|
||||
}
|
||||
|
||||
// Lock and truncate the file, if not readonly.
|
||||
if s.readOnly {
|
||||
err = _READONLY_CANTINIT
|
||||
rc = _READONLY_CANTINIT
|
||||
} else {
|
||||
if rc := osWriteLock(f, 0, 0, 0); rc != _OK {
|
||||
return rc
|
||||
@@ -156,17 +156,17 @@ func (s *vfsShm) shmOpen() (err error) {
|
||||
if add {
|
||||
vfsShmFiles = append(vfsShmFiles, s.vfsShmFile)
|
||||
}
|
||||
return err
|
||||
return rc
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, error) {
|
||||
func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, extend bool) (uint32, _ErrorCode) {
|
||||
// Ensure size is a multiple of the OS page size.
|
||||
if int(size)&(unix.Getpagesize()-1) != 0 {
|
||||
return 0, _IOERR_SHMMAP
|
||||
}
|
||||
|
||||
if err := s.shmOpen(); err != nil {
|
||||
return 0, err
|
||||
if rc := s.shmOpen(); rc != _OK {
|
||||
return 0, rc
|
||||
}
|
||||
|
||||
// Check if file is big enough.
|
||||
@@ -176,7 +176,7 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
if n := (int64(id) + 1) * int64(size); n > o {
|
||||
if !extend {
|
||||
return 0, nil
|
||||
return 0, _OK
|
||||
}
|
||||
err := osAllocate(s.File, n)
|
||||
if err != nil {
|
||||
@@ -192,13 +192,13 @@ func (s *vfsShm) shmMap(ctx context.Context, mod api.Module, id, size int32, ext
|
||||
}
|
||||
r, err := util.MapRegion(ctx, mod, s.File, int64(id)*int64(size), size, prot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, _IOERR_SHMMAP
|
||||
}
|
||||
s.regions = append(s.regions, r)
|
||||
return r.Ptr, nil
|
||||
return r.Ptr, _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
|
||||
func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
s.lockMtx.Lock()
|
||||
defer s.lockMtx.Unlock()
|
||||
|
||||
@@ -235,7 +235,7 @@ func (s *vfsShm) shmLock(offset, n int32, flags _ShmFlag) error {
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return _OK
|
||||
}
|
||||
|
||||
func (s *vfsShm) shmUnmap(delete bool) {
|
||||
|
||||
10
vfs/vfs.go
10
vfs/vfs.go
@@ -397,18 +397,14 @@ func vfsShmBarrier(ctx context.Context, mod api.Module, pFile uint32) {
|
||||
|
||||
func vfsShmMap(ctx context.Context, mod api.Module, pFile uint32, iRegion, szRegion int32, bExtend, pp uint32) _ErrorCode {
|
||||
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
|
||||
p, err := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
|
||||
if err != nil {
|
||||
return vfsErrorCode(err, _IOERR_SHMMAP)
|
||||
}
|
||||
p, rc := shm.shmMap(ctx, mod, iRegion, szRegion, bExtend != 0)
|
||||
util.WriteUint32(mod, pp, p)
|
||||
return _OK
|
||||
return rc
|
||||
}
|
||||
|
||||
func vfsShmLock(ctx context.Context, mod api.Module, pFile uint32, offset, n int32, flags _ShmFlag) _ErrorCode {
|
||||
shm := vfsFileGet(ctx, mod, pFile).(FileSharedMemory).SharedMemory()
|
||||
err := shm.shmLock(offset, n, flags)
|
||||
return vfsErrorCode(err, _IOERR_SHMLOCK)
|
||||
return shm.shmLock(offset, n, flags)
|
||||
}
|
||||
|
||||
func vfsShmUnmap(ctx context.Context, mod api.Module, pFile, bDelete uint32) _ErrorCode {
|
||||
|
||||
Reference in New Issue
Block a user