Files
2026-06-08 12:59:01 +01:00

133 lines
3.6 KiB
Go

package sqlite3
// Backup is an handle to an ongoing online backup operation.
//
// https://sqlite.org/c3ref/backup.html
type Backup struct {
c *Conn
handle ptr_t
otherc ptr_t
}
// Backup backs up srcDB on the src connection to the "main" database in dstURI.
//
// Backup opens the SQLite database file dstURI,
// and blocks until the entire backup is complete.
// Use [Conn.BackupInit] for incremental backup.
//
// https://sqlite.org/backup.html
func (src *Conn) Backup(srcDB, dstURI string) error {
b, err := src.BackupInit(srcDB, dstURI)
if err != nil {
return err
}
defer b.Close()
_, err = b.Step(-1)
return err
}
// Restore restores dstDB on the dst connection from the "main" database in srcURI.
//
// Restore opens the SQLite database file srcURI,
// and blocks until the entire restore is complete.
//
// https://sqlite.org/backup.html
func (dst *Conn) Restore(dstDB, srcURI string) error {
src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI)
if err != nil {
return err
}
b, err := dst.backupInit(dst.handle, dstDB, src, "main")
if err != nil {
return err
}
defer b.Close()
_, err = b.Step(-1)
return err
}
// BackupInit initializes a backup operation to copy the content of one database into another.
//
// BackupInit opens the SQLite database file dstURI,
// then initializes a backup that copies the contents of srcDB on the src connection
// to the "main" database in dstURI.
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) {
dst, err := src.openDB(dstURI, OPEN_READWRITE|OPEN_CREATE|OPEN_URI)
if err != nil {
return nil, err
}
return src.backupInit(dst, "main", src.handle, srcDB)
}
func (c *Conn) backupInit(dst ptr_t, dstName string, src ptr_t, srcName string) (*Backup, error) {
defer c.arena.Mark()()
dstPtr := c.arena.String(dstName)
srcPtr := c.arena.String(srcName)
other := dst
if c.handle == dst {
other = src
}
ptr := ptr_t(c.wrp.Xsqlite3_backup_init(
int32(dst), int32(dstPtr),
int32(src), int32(srcPtr)))
if ptr == 0 {
defer c.closeDB(other)
rc := res_t(c.wrp.Xsqlite3_errcode(int32(dst)))
return nil, c.errorFor(dst, rc)
}
return &Backup{
c: c,
otherc: other,
handle: ptr,
}, nil
}
// Close finishes a backup operation.
//
// It is safe to close a nil, zero or closed Backup.
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
func (b *Backup) Close() error {
if b == nil || b.handle == 0 {
return nil
}
rc := res_t(b.c.wrp.Xsqlite3_backup_finish(int32(b.handle)))
b.c.closeDB(b.otherc)
b.handle = 0
return b.c.error(rc)
}
// Step copies up to nPage pages between the source and destination databases.
// If nPage is negative, all remaining source pages are copied.
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
func (b *Backup) Step(nPage int) (done bool, err error) {
rc := res_t(b.c.wrp.Xsqlite3_backup_step(int32(b.handle), int32(nPage)))
if rc == _DONE {
return true, nil
}
return false, b.c.error(rc)
}
// Remaining returns the number of pages still to be backed up
// at the conclusion of the most recent [Backup.Step].
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
func (b *Backup) Remaining() int {
return int(b.c.wrp.Xsqlite3_backup_remaining(int32(b.handle)))
}
// PageCount returns the total number of pages in the source database
// at the conclusion of the most recent [Backup.Step].
//
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
func (b *Backup) PageCount() int {
return int(b.c.wrp.Xsqlite3_backup_pagecount(int32(b.handle)))
}