backing up a SQLite database with Go
open SQLite databases can't just be copied to back them up.
while you can use the sqlite3 shell .backup
builtin for this,
it may be preferrable to do it from inside your Go program.
the way to do this feels a bit hacky, but works nonetheless.
given that destDb
and srcDb
are opened SQLite databases, you
can do the following:
func backup(destDb, srcDb *sql.DB) error {
destConn, err := destDb.Conn(context.Background())
if err != nil {
return err
}
srcConn, err := srcDb.Conn(context.Background())
if err != nil {
return err
}
return destConn.Raw(func (destConn interface{}) error {
return srcConn.Raw(func (srcConn interface{}) error {
destSQLiteConn, ok := destConn.(*sqlite3.SQLiteConn)
if !ok {
return fmt.Errorf("can't convert destination connection to SQLiteConn")
}
srcSQLiteConn, ok := srcConn.(*sqlite3.SQLiteConn)
if !ok {
return fmt.Errorf("can't convert source connection to SQLiteConn")
}
b, err := destSQLiteConn.Backup("main", srcSQLiteConn, "main")
if err != nil {
return fmt.Errorf("error initializing SQLite backup: %w", err)
}
done, err := b.Step(-1)
if !done {
return fmt.Errorf("step of -1, but not done")
}
if err != nil {
return fmt.Errorf("error in stepping backup: %w", err)
}
err = b.Finish()
if err != nil {
return fmt.Errorf("error finishing backup: %w", err)
}
return err
})
})
}
the relevant parts of documentation for this are
func (*DB) Conn
and
func (*Conn) Raw
from
database/sql
and
func (*SQLiteConn) Backup
,
func (*SQLiteBackup) Step
and
func (*SQLiteBackup) Finish
from github.com/mattn/go-sqlite3
.
lastly, SQLite documentations description of how the C-backup-API is used to find out what goes into the ominous dest
and src
string parameters of func (*SQLiteConn) Backup
(it's main
for both, they select the schema inside the SQLite database :).