diff --git a/embed/bcw2/bcw2.wasm b/embed/bcw2/bcw2.wasm index 7e5edbfb..e87b2d59 100755 Binary files a/embed/bcw2/bcw2.wasm and b/embed/bcw2/bcw2.wasm differ diff --git a/embed/bcw2/build.sh b/embed/bcw2/build.sh index bd931c46..e1c46f63 100755 --- a/embed/bcw2/build.sh +++ b/embed/bcw2/build.sh @@ -59,6 +59,7 @@ cd ~- -D_HAVE_SQLITE_CONFIG_H \ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT \ -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES \ + -DSQLITE_EXPERIMENTAL_PRAGMA_20251114 \ -DSQLITE_CUSTOM_INCLUDE=sqlite_opt.h \ $(awk '{print "-Wl,--export="$0}' ../exports.txt) diff --git a/vfs/mvcc/mvcc.go b/vfs/mvcc/mvcc.go index 09649ac2..dd69a7e0 100644 --- a/vfs/mvcc/mvcc.go +++ b/vfs/mvcc/mvcc.go @@ -90,6 +90,7 @@ type mvccFile struct { data *wbt.Tree[int64, string] lock vfs.LockLevel readOnly bool + wrflag bool } var ( @@ -212,6 +213,14 @@ func (m *mvccFile) Truncate(size int64) error { return nil } +func (m *mvccFile) Pragma(name, value string) (string, error) { + // notest // https://sqlite.org/forum/forumpost/c4ca8e7f4a887aa4 + if name == "experimental_pragma_20251114" { + m.wrflag = true + } + return "", sqlite3.NOTFOUND +} + func (m *mvccFile) Lock(lock vfs.LockLevel) error { if m.lock >= lock { return nil @@ -225,7 +234,7 @@ func (m *mvccFile) Lock(lock vfs.LockLevel) error { defer m.mtx.Unlock() // Take a snapshot of the database. - if lock == vfs.LOCK_SHARED { + if lock == vfs.LOCK_SHARED && !m.wrflag { m.data = m.mvccDB.data m.lock = lock return nil @@ -244,7 +253,7 @@ func (m *mvccFile) Lock(lock vfs.LockLevel) error { defer time.AfterFunc(time.Millisecond, m.waiter.Broadcast).Stop() for m.owner != nil { // Our snapshot is invalid. - if m.data != m.mvccDB.data { + if m.data != nil && m.data != m.mvccDB.data { return sqlite3.BUSY_SNAPSHOT } if time.Since(before) > time.Millisecond { @@ -253,11 +262,15 @@ func (m *mvccFile) Lock(lock vfs.LockLevel) error { m.waiter.Wait() } } - // Our snapshot is invalid. - if m.data != m.mvccDB.data { + switch { + case m.data == nil: + m.data = m.mvccDB.data + case m.data != m.mvccDB.data: + // Our snapshot is invalid. return sqlite3.BUSY_SNAPSHOT } // Take ownership. + m.wrflag = false m.lock = lock m.owner = m return nil