Files
sqlite3/backup.go

135 lines
3.6 KiB
Go
Raw Permalink Normal View History

2023-03-03 14:48:56 +00:00
package sqlite3
2023-05-11 15:19:57 +01:00
// Backup is an handle to an ongoing online backup operation.
2023-03-03 14:48:56 +00:00
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup.html
2023-03-03 14:48:56 +00:00
type Backup struct {
c *Conn
handle uint32
2023-03-07 12:12:48 +00:00
otherc uint32
}
// Backup backs up srcDB on the src connection to the "main" database in dstURI.
//
2023-05-19 13:47:12 +01:00
// Backup opens the SQLite database file dstURI,
2023-03-07 12:12:48 +00:00
// and blocks until the entire backup is complete.
// Use [Conn.BackupInit] for incremental backup.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/backup.html
2023-03-07 12:12:48 +00:00
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.
//
2023-05-19 13:47:12 +01:00
// Restore opens the SQLite database file srcURI,
2023-03-07 12:12:48 +00:00
// and blocks until the entire restore is complete.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/backup.html
2023-03-07 12:12:48 +00:00
func (dst *Conn) Restore(dstDB, srcURI string) error {
2023-03-16 12:27:44 +00:00
src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI)
2023-03-07 12:12:48 +00:00
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
2023-03-03 14:48:56 +00:00
}
// BackupInit initializes a backup operation to copy the content of one database into another.
//
2023-05-19 13:47:12 +01:00
// BackupInit opens the SQLite database file dstURI,
2023-03-07 12:12:48 +00:00
// then initializes a backup that copies the contents of srcDB on the src connection
// to the "main" database in dstURI.
2023-03-03 14:48:56 +00:00
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
2023-03-07 12:12:48 +00:00
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)
2023-03-03 14:48:56 +00:00
}
2023-03-07 12:12:48 +00:00
func (c *Conn) backupInit(dst uint32, dstName string, src uint32, srcName string) (*Backup, error) {
2023-11-29 10:38:03 +00:00
defer c.arena.mark()()
2023-03-07 12:12:48 +00:00
dstPtr := c.arena.string(dstName)
srcPtr := c.arena.string(srcName)
2023-03-07 14:19:22 +00:00
other := dst
if c.handle == dst {
other = src
}
2023-11-30 17:52:35 +00:00
r := c.call("sqlite3_backup_init",
2023-03-07 12:12:48 +00:00
uint64(dst), uint64(dstPtr),
uint64(src), uint64(srcPtr))
2023-05-25 13:17:44 +01:00
if r == 0 {
2023-03-07 14:19:22 +00:00
defer c.closeDB(other)
2023-11-30 17:52:35 +00:00
r = c.call("sqlite3_errcode", uint64(dst))
2023-07-03 17:21:35 +01:00
return nil, c.sqlite.error(r, dst)
2023-03-07 12:12:48 +00:00
}
return &Backup{
c: c,
otherc: other,
2023-05-25 13:17:44 +01:00
handle: uint32(r),
2023-03-07 12:12:48 +00:00
}, nil
2023-03-03 14:48:56 +00:00
}
// Close finishes a backup operation.
//
// It is safe to close a nil, zero or closed Backup.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
2023-03-03 14:48:56 +00:00
func (b *Backup) Close() error {
if b == nil || b.handle == 0 {
return nil
}
2023-11-30 17:52:35 +00:00
r := b.c.call("sqlite3_backup_finish", uint64(b.handle))
2023-03-07 12:12:48 +00:00
b.c.closeDB(b.otherc)
2023-03-03 14:48:56 +00:00
b.handle = 0
2023-05-25 13:17:44 +01:00
return b.c.error(r)
2023-03-03 14:48:56 +00:00
}
// Step copies up to nPage pages between the source and destination databases.
// If nPage is negative, all remaining source pages are copied.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
2023-03-03 14:48:56 +00:00
func (b *Backup) Step(nPage int) (done bool, err error) {
2023-11-30 17:52:35 +00:00
r := b.c.call("sqlite3_backup_step", uint64(b.handle), uint64(nPage))
2023-05-25 13:17:44 +01:00
if r == _DONE {
2023-03-03 14:48:56 +00:00
return true, nil
}
2023-05-25 13:17:44 +01:00
return false, b.c.error(r)
2023-03-03 14:48:56 +00:00
}
// Remaining returns the number of pages still to be backed up
// at the conclusion of the most recent [Backup.Step].
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
2023-03-03 14:48:56 +00:00
func (b *Backup) Remaining() int {
2023-11-30 17:52:35 +00:00
r := b.c.call("sqlite3_backup_remaining", uint64(b.handle))
2024-01-18 15:53:00 +00:00
return int(int32(r))
2023-03-03 14:48:56 +00:00
}
// PageCount returns the total number of pages in the source database
// at the conclusion of the most recent [Backup.Step].
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
2023-03-03 14:48:56 +00:00
func (b *Backup) PageCount() int {
2023-11-30 17:52:35 +00:00
r := b.c.call("sqlite3_backup_pagecount", uint64(b.handle))
2024-01-18 15:53:00 +00:00
return int(int32(r))
2023-03-03 14:48:56 +00:00
}