diff options
Diffstat (limited to 'vendor/github.com/ncruces/go-sqlite3/vfs/memdb')
3 files changed, 0 insertions, 436 deletions
diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md deleted file mode 100644 index e37db1be6..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Go `memdb` SQLite VFS - -This package implements the [`"memdb"`](https://sqlite.org/src/doc/tip/src/memdb.c) -SQLite VFS in pure Go. - -It has some benefits over the C version: -- the memory backing the database needs not be contiguous, -- the database can grow/shrink incrementally without copying, -- reader-writer concurrency is slightly improved. - -[`memdb.TestDB`](https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb#TestDB) -is the preferred way to setup an in-memory database for testing.
\ No newline at end of file diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go deleted file mode 100644 index a12819855..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/api.go +++ /dev/null @@ -1,117 +0,0 @@ -// Package memdb implements the "memdb" SQLite VFS. -// -// The "memdb" [vfs.VFS] allows the same in-memory database to be shared -// among multiple database connections in the same process, -// as long as the database name begins with "/". -// -// Importing package memdb registers the VFS: -// -// import _ "github.com/ncruces/go-sqlite3/vfs/memdb" -package memdb - -import ( - "crypto/rand" - "fmt" - "net/url" - "sync" - "testing" - - "github.com/ncruces/go-sqlite3/vfs" -) - -func init() { - vfs.Register("memdb", memVFS{}) -} - -var ( - memoryMtx sync.Mutex - // +checklocks:memoryMtx - memoryDBs = map[string]*memDB{} -) - -// Create creates a shared memory database, -// using data as its initial contents. -// The new database takes ownership of data, -// and the caller should not use data after this call. -func Create(name string, data []byte) { - memoryMtx.Lock() - defer memoryMtx.Unlock() - - db := &memDB{ - refs: 1, - name: name, - size: int64(len(data)), - } - - // Convert data from WAL/2 to rollback journal. - if len(data) >= 20 && (false || - data[18] == 2 && data[19] == 2 || - data[18] == 3 && data[19] == 3) { - data[18] = 1 - data[19] = 1 - } - - sectors := divRoundUp(db.size, sectorSize) - db.data = make([]*[sectorSize]byte, sectors) - for i := range db.data { - sector := data[i*sectorSize:] - if len(sector) >= sectorSize { - db.data[i] = (*[sectorSize]byte)(sector) - } else { - db.data[i] = new([sectorSize]byte) - copy((*db.data[i])[:], sector) - } - } - - memoryDBs[name] = db -} - -// Delete deletes a shared memory database. -func Delete(name string) { - memoryMtx.Lock() - defer memoryMtx.Unlock() - delete(memoryDBs, name) -} - -// TestDB creates an empty shared memory database for the test to use. -// The database is automatically deleted when the test and all its subtests complete. -// Returns a URI filename appropriate to call Open with. -// Each subsequent call to TestDB returns a unique database. -// -// func Test_something(t *testing.T) { -// t.Parallel() -// dsn := memdb.TestDB(t, url.Values{ -// "_pragma": {"busy_timeout(1000)"}, -// }) -// -// db, err := sql.Open("sqlite3", dsn) -// if err != nil { -// t.Fatal(err) -// } -// defer db.Close() -// -// // ... -// } -func TestDB(tb testing.TB, params ...url.Values) string { - tb.Helper() - - name := fmt.Sprintf("%s_%s", tb.Name(), rand.Text()) - tb.Cleanup(func() { Delete(name) }) - Create(name, nil) - - p := url.Values{"vfs": {"memdb"}} - for _, v := range params { - for k, v := range v { - for _, v := range v { - p.Add(k, v) - } - } - } - - return (&url.URL{ - Scheme: "file", - OmitHost: true, - Path: "/" + name, - RawQuery: p.Encode(), - }).String() -} diff --git a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go b/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go deleted file mode 100644 index e304f6d58..000000000 --- a/vendor/github.com/ncruces/go-sqlite3/vfs/memdb/memdb.go +++ /dev/null @@ -1,307 +0,0 @@ -package memdb - -import ( - "io" - "strings" - "sync" - "time" - - "github.com/ncruces/go-sqlite3" - "github.com/ncruces/go-sqlite3/util/vfsutil" - "github.com/ncruces/go-sqlite3/vfs" -) - -const sectorSize = 65536 - -type memVFS struct{} - -func (memVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) { - // For simplicity, we do not support reading or writing data - // across "sector" boundaries. - // This is not a problem for SQLite database files. - const databases = vfs.OPEN_MAIN_DB | vfs.OPEN_TEMP_DB | vfs.OPEN_TRANSIENT_DB - - // Temp journals, as used by the sorter, use SliceFile. - if flags&vfs.OPEN_TEMP_JOURNAL != 0 { - return &vfsutil.SliceFile{}, flags | vfs.OPEN_MEMORY, nil - } - - // Refuse to open all other file types. - // Returning OPEN_MEMORY means SQLite won't ask us to. - if flags&databases == 0 { - // notest // OPEN_MEMORY - return nil, flags, sqlite3.CANTOPEN - } - - // A shared database has a name that begins with "/". - shared := strings.HasPrefix(name, "/") - - var db *memDB - if shared { - name = name[1:] - memoryMtx.Lock() - defer memoryMtx.Unlock() - db = memoryDBs[name] - } - if db == nil { - if flags&vfs.OPEN_CREATE == 0 { - return nil, flags, sqlite3.CANTOPEN - } - db = &memDB{name: name} - } - if shared { - db.refs++ // +checklocksforce: memoryMtx is held - memoryDBs[name] = db - } - - return &memFile{ - memDB: db, - readOnly: flags&vfs.OPEN_READONLY != 0, - }, flags | vfs.OPEN_MEMORY, nil -} - -func (memVFS) Delete(name string, dirSync bool) error { - return sqlite3.IOERR_DELETE_NOENT // used to delete journals -} - -func (memVFS) Access(name string, flag vfs.AccessFlag) (bool, error) { - return false, nil // used to check for journals -} - -func (memVFS) FullPathname(name string) (string, error) { - return name, nil -} - -type memDB struct { - name string - - // +checklocks:lockMtx - waiter *sync.Cond - // +checklocks:dataMtx - data []*[sectorSize]byte - - size int64 // +checklocks:dataMtx - refs int32 // +checklocks:memoryMtx - shared int32 // +checklocks:lockMtx - pending bool // +checklocks:lockMtx - reserved bool // +checklocks:lockMtx - - lockMtx sync.Mutex - dataMtx sync.RWMutex -} - -func (m *memDB) release() { - memoryMtx.Lock() - defer memoryMtx.Unlock() - if m.refs--; m.refs == 0 && m == memoryDBs[m.name] { - delete(memoryDBs, m.name) - } -} - -type memFile struct { - *memDB - lock vfs.LockLevel - readOnly bool -} - -var ( - // Ensure these interfaces are implemented: - _ vfs.FileLockState = &memFile{} - _ vfs.FileSizeHint = &memFile{} -) - -func (m *memFile) Close() error { - m.release() - return m.Unlock(vfs.LOCK_NONE) -} - -func (m *memFile) ReadAt(b []byte, off int64) (n int, err error) { - m.dataMtx.RLock() - defer m.dataMtx.RUnlock() - - if off >= m.size { - return 0, io.EOF - } - - base := off / sectorSize - rest := off % sectorSize - have := int64(sectorSize) - if m.size < off+int64(len(b)) { - have = modRoundUp(m.size, sectorSize) - } - n = copy(b, (*m.data[base])[rest:have]) - if n < len(b) { - // notest // assume reads are page aligned - return 0, io.ErrNoProgress - } - return n, nil -} - -func (m *memFile) WriteAt(b []byte, off int64) (n int, err error) { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - - base := off / sectorSize - rest := off % sectorSize - for base >= int64(len(m.data)) { - m.data = append(m.data, new([sectorSize]byte)) - } - n = copy((*m.data[base])[rest:], b) - if size := off + int64(n); size > m.size { - m.size = size - } - if n < len(b) { - // notest // assume writes are page aligned - return n, io.ErrShortWrite - } - return n, nil -} - -func (m *memFile) Size() (int64, error) { - m.dataMtx.RLock() - defer m.dataMtx.RUnlock() - return m.size, nil -} - -func (m *memFile) Truncate(size int64) error { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - return m.truncate(size) -} - -func (m *memFile) SizeHint(size int64) error { - m.dataMtx.Lock() - defer m.dataMtx.Unlock() - if size > m.size { - return m.truncate(size) - } - return nil -} - -// +checklocks:m.dataMtx -func (m *memFile) truncate(size int64) error { - if size < m.size { - base := size / sectorSize - rest := size % sectorSize - if rest != 0 { - clear((*m.data[base])[rest:]) - } - } - sectors := divRoundUp(size, sectorSize) - for sectors > int64(len(m.data)) { - m.data = append(m.data, new([sectorSize]byte)) - } - clear(m.data[sectors:]) - m.data = m.data[:sectors] - m.size = size - return nil -} - -func (m *memFile) Lock(lock vfs.LockLevel) error { - if m.lock >= lock { - return nil - } - - if m.readOnly && lock >= vfs.LOCK_RESERVED { - return sqlite3.IOERR_LOCK - } - - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - - switch lock { - case vfs.LOCK_SHARED: - if m.pending { - return sqlite3.BUSY - } - m.shared++ - - case vfs.LOCK_RESERVED: - if m.reserved { - return sqlite3.BUSY - } - m.reserved = true - - case vfs.LOCK_EXCLUSIVE: - if m.lock < vfs.LOCK_PENDING { - m.lock = vfs.LOCK_PENDING - m.pending = true - } - - if m.shared > 1 { - before := time.Now() - if m.waiter == nil { - m.waiter = sync.NewCond(&m.lockMtx) - } - defer time.AfterFunc(time.Millisecond, m.waiter.Broadcast).Stop() - for m.shared > 1 { - if time.Since(before) > time.Millisecond { - return sqlite3.BUSY - } - m.waiter.Wait() - } - } - } - - m.lock = lock - return nil -} - -func (m *memFile) Unlock(lock vfs.LockLevel) error { - if m.lock <= lock { - return nil - } - - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - - if m.lock >= vfs.LOCK_RESERVED { - m.reserved = false - } - if m.lock >= vfs.LOCK_PENDING { - m.pending = false - } - if lock < vfs.LOCK_SHARED { - if m.shared--; m.pending && m.shared <= 1 && m.waiter != nil { - m.waiter.Broadcast() - } - } - m.lock = lock - return nil -} - -func (m *memFile) CheckReservedLock() (bool, error) { - // notest // OPEN_MEMORY - if m.lock >= vfs.LOCK_RESERVED { - return true, nil - } - m.lockMtx.Lock() - defer m.lockMtx.Unlock() - return m.reserved, nil -} - -func (m *memFile) LockState() vfs.LockLevel { - return m.lock -} - -func (*memFile) Sync(flag vfs.SyncFlag) error { return nil } - -func (*memFile) SectorSize() int { - // notest // IOCAP_POWERSAFE_OVERWRITE - return sectorSize -} - -func (*memFile) DeviceCharacteristics() vfs.DeviceCharacteristic { - return vfs.IOCAP_ATOMIC | - vfs.IOCAP_SEQUENTIAL | - vfs.IOCAP_SAFE_APPEND | - vfs.IOCAP_POWERSAFE_OVERWRITE -} - -func divRoundUp(a, b int64) int64 { - return (a + b - 1) / b -} - -func modRoundUp(a, b int64) int64 { - return b - (b-a%b)%b -} |
