Commit da7e25e1 authored by gwenn's avatar gwenn

Add docs for backup and blob API.

parent 7c426872
...@@ -18,10 +18,23 @@ import ( ...@@ -18,10 +18,23 @@ import (
"unsafe" "unsafe"
) )
// Backup/Copy the content of one database (source) to another (destination).
// Example:
// bck, err := sqlite.NewBackup(dst, "main", src, "main")
// // check err
// defer bck.Close()
// cbs := make(chan sqlite.BackupStatus)
// go func() {
// s := <- cbs
// // report progress
// }()
// err = bck.Run(100, 250000, cbs)
// check(err)
//
// Calls http://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit // Calls http://sqlite.org/c3ref/backup_finish.html#sqlite3backupinit
func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, error) { func NewBackup(dst *Conn, dstDbName string, src *Conn, srcDbName string) (*Backup, error) {
dname := C.CString(dstTable) dname := C.CString(dstDbName)
sname := C.CString(srcTable) sname := C.CString(srcDbName)
defer C.free(unsafe.Pointer(dname)) defer C.free(unsafe.Pointer(dname))
defer C.free(unsafe.Pointer(sname)) defer C.free(unsafe.Pointer(sname))
...@@ -32,6 +45,7 @@ func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, ...@@ -32,6 +45,7 @@ func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup,
return &Backup{sb, dst, src}, nil return &Backup{sb, dst, src}, nil
} }
// Encapsulates backup API
type Backup struct { type Backup struct {
sb *C.sqlite3_backup sb *C.sqlite3_backup
dst, src *Conn dst, src *Conn
...@@ -46,6 +60,7 @@ func (b *Backup) Step(npage int) error { ...@@ -46,6 +60,7 @@ func (b *Backup) Step(npage int) error {
return Errno(rv) return Errno(rv)
} }
// Backup progression
type BackupStatus struct { type BackupStatus struct {
Remaining int Remaining int
PageCount int PageCount int
...@@ -67,8 +82,10 @@ func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) error { ...@@ -67,8 +82,10 @@ func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) error {
if c != nil { if c != nil {
c <- b.Status() c <- b.Status()
} }
if sleepNs > 0 {
time.Sleep(sleepNs) time.Sleep(sleepNs)
} }
}
return b.dst.error(C.sqlite3_errcode(b.dst.db)) return b.dst.error(C.sqlite3_errcode(b.dst.db))
} }
......
...@@ -20,21 +20,41 @@ import ( ...@@ -20,21 +20,41 @@ import (
type BlobReader struct { type BlobReader struct {
c *Conn c *Conn
bl *C.sqlite3_blob bl *C.sqlite3_blob
ReadOffset int
} }
type BlobReadWriter struct { type BlobReadWriter struct {
BlobReader BlobReader
WriteOffset int
} }
// Zeroblobs are used to reserve space for a BLOB that is later written.
//
// Example:
// s, err := db.Prepare("INSERT INTO test VALUES (?)")
// // check err
// defer s.Finalize()
// err = s.Exec(ZeroBlobLength(10))
// // check err
type ZeroBlobLength int type ZeroBlobLength int
// Example:
// br, err := db.NewBlobReader("db_name", "table_name", "column_name", rowid)
// // check err
// defer br.Close()
// size, err := br.Size()
// // check err
// content = make([]byte, size)
// n, err = br.Read(content)
// // check err
//
// Calls http://sqlite.org/c3ref/blob_open.html // Calls http://sqlite.org/c3ref/blob_open.html
func (c *Conn) NewBlobReader(db, table, column string, row int64) (*BlobReader, error) { func (c *Conn) NewBlobReader(db, table, column string, row int64) (*BlobReader, error) {
bl, err := c.blob_open(db, table, column, row, false) bl, err := c.blob_open(db, table, column, row, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &BlobReader{c, bl}, nil return &BlobReader{c, bl, 0}, nil
} }
// Calls http://sqlite.org/c3ref/blob_open.html // Calls http://sqlite.org/c3ref/blob_open.html
...@@ -43,7 +63,7 @@ func (c *Conn) NewBlobReadWriter(db, table, column string, row int64) (*BlobRead ...@@ -43,7 +63,7 @@ func (c *Conn) NewBlobReadWriter(db, table, column string, row int64) (*BlobRead
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &BlobReadWriter{BlobReader{c, bl}}, nil return &BlobReadWriter{BlobReader{c, bl, 0}, 0}, nil
} }
func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sqlite3_blob, error) { func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sqlite3_blob, error) {
...@@ -83,10 +103,11 @@ func (r *BlobReader) Read(v []byte) (int, error) { ...@@ -83,10 +103,11 @@ func (r *BlobReader) Read(v []byte) (int, error) {
if len(v) > 0 { if len(v) > 0 {
p = &v[0] p = &v[0]
} }
rv := C.sqlite3_blob_read(r.bl, unsafe.Pointer(p), C.int(len(v)), 0) // TODO offset rv := C.sqlite3_blob_read(r.bl, unsafe.Pointer(p), C.int(len(v)), C.int(r.ReadOffset))
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return 0, r.c.error(rv) return 0, r.c.error(rv)
} }
r.ReadOffset += len(v)
return len(v), nil return len(v), nil
} }
...@@ -102,10 +123,11 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) { ...@@ -102,10 +123,11 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
if len(v) > 0 { if len(v) > 0 {
p = &v[0] p = &v[0]
} }
rv := C.sqlite3_blob_write(w.bl, unsafe.Pointer(p), C.int(len(v)), 0) // TODO offset rv := C.sqlite3_blob_write(w.bl, unsafe.Pointer(p), C.int(len(v)), C.int(w.WriteOffset))
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return 0, w.c.error(rv) return 0, w.c.error(rv)
} }
w.WriteOffset += len(v)
return len(v), nil return len(v), nil
} }
...@@ -115,5 +137,6 @@ func (r *BlobReader) Reopen(rowid int64) error { ...@@ -115,5 +137,6 @@ func (r *BlobReader) Reopen(rowid int64) error {
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return r.c.error(rv) return r.c.error(rv)
} }
r.ReadOffset = 0
return nil return nil
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment