Skip to content

Commit cc0b011

Browse files
committed
Readonly WAL.
1 parent 4608691 commit cc0b011

File tree

6 files changed

+55
-17
lines changed

6 files changed

+55
-17
lines changed

internal/util/mmap.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build (darwin || linux || illumos) && (amd64 || arm64) && !sqlite3_flock && !sqlite3_noshm && !sqlite3_nosys
1+
//go:build (darwin || linux || illumos) && (amd64 || arm64 || riscv64) && !sqlite3_flock && !sqlite3_noshm && !sqlite3_nosys
22

33
package util
44

@@ -69,10 +69,10 @@ type MappedRegion struct {
6969
used bool
7070
}
7171

72-
func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32) (*MappedRegion, error) {
72+
func MapRegion(ctx context.Context, mod api.Module, f *os.File, offset int64, size int32, prot int) (*MappedRegion, error) {
7373
s := ctx.Value(moduleKey{}).(*moduleState)
7474
r := s.new(ctx, mod, size)
75-
err := r.mmap(f, offset)
75+
err := r.mmap(f, offset, prot)
7676
if err != nil {
7777
return nil, err
7878
}
@@ -90,9 +90,9 @@ func (r *MappedRegion) Unmap() error {
9090
return err
9191
}
9292

93-
func (r *MappedRegion) mmap(f *os.File, offset int64) error {
93+
func (r *MappedRegion) mmap(f *os.File, offset int64, prot int) error {
9494
_, err := mmap(r.addr, uintptr(r.size),
95-
unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED|unix.MAP_FIXED,
95+
prot, unix.MAP_SHARED|unix.MAP_FIXED,
9696
int(f.Fd()), offset)
9797
r.used = err == nil
9898
return err

internal/util/mmap_other.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !(darwin || linux || illumos) || !(amd64 || arm64) || sqlite3_flock || sqlite3_noshm || sqlite3_nosys
1+
//go:build !(darwin || linux || illumos) || !(amd64 || arm64 || riscv64) || sqlite3_flock || sqlite3_noshm || sqlite3_nosys
22

33
package util
44

tests/wal_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package tests
22

33
import (
4+
"os"
45
"path/filepath"
56
"testing"
67

78
"github.com/ncruces/go-sqlite3"
9+
"github.com/ncruces/go-sqlite3/vfs"
810
)
911

1012
func TestWAL_enter_exit(t *testing.T) {
@@ -32,6 +34,36 @@ func TestWAL_enter_exit(t *testing.T) {
3234
}
3335
}
3436

37+
func TestWAL_readonly(t *testing.T) {
38+
if !vfs.SupportsSharedMemory {
39+
t.Skip("skipping without shared memory")
40+
}
41+
42+
t.Parallel()
43+
44+
tmp := filepath.Join(t.TempDir(), "test.db")
45+
err := os.WriteFile(tmp, waldb, 0666)
46+
if err != nil {
47+
t.Fatal(err)
48+
}
49+
50+
db, err := sqlite3.OpenFlags(tmp, sqlite3.OPEN_READONLY)
51+
if err != nil {
52+
t.Fatal(err)
53+
}
54+
defer db.Close()
55+
56+
stmt, _, err := db.Prepare(`SELECT * FROM sqlite_master`)
57+
if err != nil {
58+
t.Fatal(err)
59+
}
60+
defer stmt.Close()
61+
62+
if stmt.Step() {
63+
t.Error("want no rows")
64+
}
65+
}
66+
3567
func TestConn_WalCheckpoint(t *testing.T) {
3668
t.Parallel()
3769

vfs/README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,18 @@ On 64-bit Linux, macOS and illumos, this module uses `mmap` to implement
4949
[shared-memory for the WAL-index](https://sqlite.org/wal.html#implementation_of_shared_memory_for_the_wal_index),
5050
like SQLite.
5151

52-
To allow `mmap` to work, each connection needs to reserve a lot of address space.\
52+
To allow `mmap` to work, each connection needs to reserve up to 4GB of address space.\
5353
To limit the amount of address space each connection needs,
5454
use [`WithMemoryLimitPages`](../tests/parallel/parallel_test.go#L21).
5555

5656
On all other platforms, [WAL](https://sqlite.org/wal.html) support is
5757
[limited](https://sqlite.org/wal.html#noshm).
5858

59-
To work around that limitation, SQLite is [patched](sqlite3/locking_mode.patch)
59+
To work around this limitation, SQLite is [patched](sqlite3/locking_mode.patch)
6060
to automatically use `EXCLUSIVE` locking mode for WAL databases on such platforms.
6161

62-
Because connection pooling is incompatible with `EXCLUSIVE` locking mode,
63-
to use the [`database/sql`](https://pkg.go.dev/database/sql) driver
64-
with WAL mode databases you should disable connection pooling by calling
62+
To use the [`database/sql`](https://pkg.go.dev/database/sql) driver
63+
with `EXCLUSIVE` locking mode you should disable connection pooling by calling
6564
[`db.SetMaxOpenConns(1)`](https://pkg.go.dev/database/sql#DB.SetMaxOpenConns).
6665

6766
You can use [`vfs.SupportsSharedMemory`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs#SupportsSharedMemory)

vfs/shm.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build (linux || darwin) && (amd64 || arm64) && !sqlite3_flock && !sqlite3_noshm && !sqlite3_nosys
1+
//go:build (darwin || linux || illumos) && (amd64 || arm64 || riscv64) && !sqlite3_flock && !sqlite3_noshm && !sqlite3_nosys
22

33
package vfs
44

@@ -42,11 +42,12 @@ func (f *vfsFile) shmMap(ctx context.Context, mod api.Module, id, size int32, ex
4242
if f.shm.File == nil {
4343
var flag int
4444
if f.readOnly {
45-
flag = unix.O_RDONLY | unix.O_NOFOLLOW
45+
flag = unix.O_RDONLY
4646
} else {
47-
flag = unix.O_RDWR | unix.O_CREAT | unix.O_NOFOLLOW
47+
flag = unix.O_RDWR
4848
}
49-
s, err := os.OpenFile(f.Name()+"-shm", flag, 0666)
49+
s, err := os.OpenFile(f.Name()+"-shm",
50+
flag|unix.O_CREAT|unix.O_NOFOLLOW, 0666)
5051
if err != nil {
5152
return 0, _CANTOPEN
5253
}
@@ -88,7 +89,13 @@ func (f *vfsFile) shmMap(ctx context.Context, mod api.Module, id, size int32, ex
8889
}
8990
}
9091

91-
r, err := util.MapRegion(ctx, mod, f.shm.File, int64(id)*int64(size), size)
92+
var prot int
93+
if f.readOnly {
94+
prot = unix.PROT_READ
95+
} else {
96+
prot = unix.PROT_READ | unix.PROT_WRITE
97+
}
98+
r, err := util.MapRegion(ctx, mod, f.shm.File, int64(id)*int64(size), size, prot)
9299
if err != nil {
93100
return 0, err
94101
}

vfs/shm_other.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !(linux || darwin) || !(amd64 || arm64) || sqlite3_flock || sqlite3_noshm || sqlite3_nosys
1+
//go:build !(darwin || linux || illumos) || !(amd64 || arm64 || riscv64) || sqlite3_flock || sqlite3_noshm || sqlite3_nosys
22

33
package vfs
44

0 commit comments

Comments
 (0)