backup.go

  1package sqlite3
  2
  3// Backup is an handle to an ongoing online backup operation.
  4//
  5// https://sqlite.org/c3ref/backup.html
  6type Backup struct {
  7	c      *Conn
  8	handle ptr_t
  9	otherc ptr_t
 10}
 11
 12// Backup backs up srcDB on the src connection to the "main" database in dstURI.
 13//
 14// Backup opens the SQLite database file dstURI,
 15// and blocks until the entire backup is complete.
 16// Use [Conn.BackupInit] for incremental backup.
 17//
 18// https://sqlite.org/backup.html
 19func (src *Conn) Backup(srcDB, dstURI string) error {
 20	b, err := src.BackupInit(srcDB, dstURI)
 21	if err != nil {
 22		return err
 23	}
 24	defer b.Close()
 25	_, err = b.Step(-1)
 26	return err
 27}
 28
 29// Restore restores dstDB on the dst connection from the "main" database in srcURI.
 30//
 31// Restore opens the SQLite database file srcURI,
 32// and blocks until the entire restore is complete.
 33//
 34// https://sqlite.org/backup.html
 35func (dst *Conn) Restore(dstDB, srcURI string) error {
 36	src, err := dst.openDB(srcURI, OPEN_READONLY|OPEN_URI)
 37	if err != nil {
 38		return err
 39	}
 40	b, err := dst.backupInit(dst.handle, dstDB, src, "main")
 41	if err != nil {
 42		return err
 43	}
 44	defer b.Close()
 45	_, err = b.Step(-1)
 46	return err
 47}
 48
 49// BackupInit initializes a backup operation to copy the content of one database into another.
 50//
 51// BackupInit opens the SQLite database file dstURI,
 52// then initializes a backup that copies the contents of srcDB on the src connection
 53// to the "main" database in dstURI.
 54//
 55// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
 56func (src *Conn) BackupInit(srcDB, dstURI string) (*Backup, error) {
 57	dst, err := src.openDB(dstURI, OPEN_READWRITE|OPEN_CREATE|OPEN_URI)
 58	if err != nil {
 59		return nil, err
 60	}
 61	return src.backupInit(dst, "main", src.handle, srcDB)
 62}
 63
 64func (c *Conn) backupInit(dst ptr_t, dstName string, src ptr_t, srcName string) (*Backup, error) {
 65	defer c.arena.mark()()
 66	dstPtr := c.arena.string(dstName)
 67	srcPtr := c.arena.string(srcName)
 68
 69	other := dst
 70	if c.handle == dst {
 71		other = src
 72	}
 73
 74	ptr := ptr_t(c.call("sqlite3_backup_init",
 75		stk_t(dst), stk_t(dstPtr),
 76		stk_t(src), stk_t(srcPtr)))
 77	if ptr == 0 {
 78		defer c.closeDB(other)
 79		rc := res_t(c.call("sqlite3_errcode", stk_t(dst)))
 80		return nil, c.sqlite.error(rc, dst)
 81	}
 82
 83	return &Backup{
 84		c:      c,
 85		otherc: other,
 86		handle: ptr,
 87	}, nil
 88}
 89
 90// Close finishes a backup operation.
 91//
 92// It is safe to close a nil, zero or closed Backup.
 93//
 94// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
 95func (b *Backup) Close() error {
 96	if b == nil || b.handle == 0 {
 97		return nil
 98	}
 99
100	rc := res_t(b.c.call("sqlite3_backup_finish", stk_t(b.handle)))
101	b.c.closeDB(b.otherc)
102	b.handle = 0
103	return b.c.error(rc)
104}
105
106// Step copies up to nPage pages between the source and destination databases.
107// If nPage is negative, all remaining source pages are copied.
108//
109// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
110func (b *Backup) Step(nPage int) (done bool, err error) {
111	rc := res_t(b.c.call("sqlite3_backup_step", stk_t(b.handle), stk_t(nPage)))
112	if rc == _DONE {
113		return true, nil
114	}
115	return false, b.c.error(rc)
116}
117
118// Remaining returns the number of pages still to be backed up
119// at the conclusion of the most recent [Backup.Step].
120//
121// https://sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
122func (b *Backup) Remaining() int {
123	n := int32(b.c.call("sqlite3_backup_remaining", stk_t(b.handle)))
124	return int(n)
125}
126
127// PageCount returns the total number of pages in the source database
128// at the conclusion of the most recent [Backup.Step].
129//
130// https://sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
131func (b *Backup) PageCount() int {
132	n := int32(b.c.call("sqlite3_backup_pagecount", stk_t(b.handle)))
133	return int(n)
134}