backup.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (c) 2018 David Crawshaw <david@zentus.com>
  2. //
  3. // Permission to use, copy, modify, and distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. package sqlite
  15. // #include <sqlite3.h>
  16. // #include <stdlib.h>
  17. import "C"
  18. import (
  19. "runtime"
  20. "unsafe"
  21. )
  22. // A Backup copies data between two databases.
  23. //
  24. // It is used to backup file based or in-memory databases.
  25. //
  26. // Equivalent to the sqlite3_backup* C object.
  27. //
  28. // https://www.sqlite.org/c3ref/backup_finish.html
  29. type Backup struct {
  30. ptr *C.sqlite3_backup
  31. }
  32. // BackupToDB creates a complete backup of the srcDB on the src Conn to a new
  33. // database Conn at dstPath. The resulting dst connection is returned. This
  34. // will block until the entire backup is complete.
  35. //
  36. // If srcDB is "", then a default of "main" is used.
  37. //
  38. // This is very similar to the first example function implemented on the
  39. // following page.
  40. //
  41. // https://www.sqlite.org/backup.html
  42. func (src *Conn) BackupToDB(srcDB, dstPath string) (dst *Conn, err error) {
  43. if dst, err = OpenConn(dstPath, 0); err != nil {
  44. return
  45. }
  46. defer func() {
  47. if err != nil {
  48. dst.Close()
  49. }
  50. }()
  51. b, err := src.BackupInit(srcDB, "", dst)
  52. if err != nil {
  53. return
  54. }
  55. defer b.Finish()
  56. err = b.Step(-1)
  57. return
  58. }
  59. // BackupInit initializes a new Backup object to copy from src to dst.
  60. //
  61. // If srcDB or dstDB is "", then a default of "main" is used.
  62. //
  63. // https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
  64. func (src *Conn) BackupInit(srcDB, dstDB string, dst *Conn) (*Backup, error) {
  65. var srcCDB, dstCDB *C.char
  66. defer setCDB(dstDB, &dstCDB)()
  67. defer setCDB(srcDB, &srcCDB)()
  68. var b Backup
  69. b.ptr = C.sqlite3_backup_init(dst.conn, dstCDB, src.conn, srcCDB)
  70. if b.ptr == nil {
  71. res := C.sqlite3_errcode(dst.conn)
  72. return nil, dst.extreserr("Conn.BackupInit", "", res)
  73. }
  74. runtime.SetFinalizer(&b, func(b *Backup) {
  75. if b.ptr != nil {
  76. panic("open *sqlite.Backup garbage collected, call Finish method")
  77. }
  78. })
  79. return &b, nil
  80. }
  81. func setCDB(db string, cdb **C.char) func() {
  82. if db == "" || db == "main" {
  83. *cdb = cmain
  84. return func() {}
  85. }
  86. *cdb = C.CString(db)
  87. return func() { C.free(unsafe.Pointer(cdb)) }
  88. }
  89. // Step is called one or more times to transfer nPage pages at a time between
  90. // databases.
  91. //
  92. // Use -1 to transfer the entire database at once.
  93. //
  94. // https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep
  95. func (b *Backup) Step(nPage int) error {
  96. res := C.sqlite3_backup_step(b.ptr, C.int(nPage))
  97. if res != C.SQLITE_DONE {
  98. return reserr("Backup.Step", "", "", res)
  99. }
  100. return nil
  101. }
  102. // Finish is called to clean up the resources allocated by BackupInit.
  103. //
  104. // https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish
  105. func (b *Backup) Finish() error {
  106. res := C.sqlite3_backup_finish(b.ptr)
  107. b.ptr = nil
  108. return reserr("Backup.Finish", "", "", res)
  109. }
  110. // Remaining returns the number of pages still to be backed up at the
  111. // conclusion of the most recent b.Step().
  112. //
  113. // https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupremaining
  114. func (b *Backup) Remaining() int {
  115. return int(C.sqlite3_backup_remaining(b.ptr))
  116. }
  117. // PageCount returns the total number of pages in the source database at the
  118. // conclusion of the most recent b.Step().
  119. //
  120. // https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backuppagecount
  121. func (b *Backup) PageCount() int {
  122. return int(C.sqlite3_backup_pagecount(b.ptr))
  123. }