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 :).


![[ Celebrate 40 years of GNU! ]](https://www.gnu.org/gnu40/GNU40_badge-sm.png)