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}