Files
sqlite3/ext/serdes/serdes.go

73 lines
2.0 KiB
Go
Raw Permalink Normal View History

2025-01-08 16:36:41 +00:00
// Package serdes provides functions to (de)serialize databases.
package serdes
import (
"github.com/ncruces/go-sqlite3"
2025-07-22 22:41:29 +01:00
"github.com/ncruces/go-sqlite3/util/vfsutil"
2025-01-08 16:36:41 +00:00
"github.com/ncruces/go-sqlite3/vfs"
)
2025-02-12 00:41:16 +00:00
const vfsName = "github.com/ncruces/go-sqlite3/ext/serdes.sliceVFS"
2025-01-08 16:36:41 +00:00
func init() {
vfs.Register(vfsName, sliceVFS{})
}
2025-07-22 22:41:29 +01:00
var fileToOpen = make(chan *[]byte, 1)
2025-02-12 00:41:16 +00:00
2025-01-08 16:36:41 +00:00
// Serialize backs up a database into a byte slice.
//
// https://sqlite.org/c3ref/serialize.html
func Serialize(db *sqlite3.Conn, schema string) ([]byte, error) {
2025-07-22 22:41:29 +01:00
var file []byte
2025-01-09 11:19:40 +00:00
fileToOpen <- &file
2025-08-02 11:48:37 +01:00
err := db.Backup(schema, "file:serdes.db?nolock=1&vfs="+vfsName)
2025-07-22 22:41:29 +01:00
return file, err
2025-01-08 16:36:41 +00:00
}
// Deserialize restores a database from a byte slice,
// DESTROYING any contents previously stored in schema.
//
// To non-destructively open a database from a byte slice,
// consider alternatives like the ["reader"] or ["memdb"] VFSes.
//
// This differs from the similarly named SQLite API
// in that it DOES NOT disconnect from schema
// to reopen as an in-memory database.
//
// https://sqlite.org/c3ref/deserialize.html
//
// ["memdb"]: https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/memdb
// ["reader"]: https://pkg.go.dev/github.com/ncruces/go-sqlite3/vfs/readervfs
func Deserialize(db *sqlite3.Conn, schema string, data []byte) error {
2025-07-22 22:41:29 +01:00
fileToOpen <- &data
2025-08-02 11:48:37 +01:00
return db.Restore(schema, "file:serdes.db?immutable=1&vfs="+vfsName)
2025-01-08 16:36:41 +00:00
}
type sliceVFS struct{}
func (sliceVFS) Open(name string, flags vfs.OpenFlag) (vfs.File, vfs.OpenFlag, error) {
2025-02-12 00:41:16 +00:00
if flags&vfs.OPEN_MAIN_DB == 0 || name != "serdes.db" {
2025-01-08 16:36:41 +00:00
return nil, flags, sqlite3.CANTOPEN
}
2025-02-12 00:41:16 +00:00
select {
case file := <-fileToOpen:
2025-07-22 22:41:29 +01:00
return (*vfsutil.SliceFile)(file), flags | vfs.OPEN_MEMORY, nil
2025-02-12 00:41:16 +00:00
default:
return nil, flags, sqlite3.MISUSE
}
2025-01-08 16:36:41 +00:00
}
func (sliceVFS) Delete(name string, dirSync bool) error {
2025-08-05 14:15:21 +01:00
// notest // no journals to delete
2025-01-08 16:36:41 +00:00
return sqlite3.IOERR_DELETE
}
func (sliceVFS) Access(name string, flag vfs.AccessFlag) (bool, error) {
2025-02-12 00:41:16 +00:00
return name == "serdes.db", nil
2025-01-08 16:36:41 +00:00
}
func (sliceVFS) FullPathname(name string) (string, error) {
return name, nil
}