Commit da7e25e1 authored by gwenn's avatar gwenn

Add docs for backup and blob API.

parent 7c426872
......@@ -18,10 +18,23 @@ import (
"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
func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, error) {
dname := C.CString(dstTable)
sname := C.CString(srcTable)
func NewBackup(dst *Conn, dstDbName string, src *Conn, srcDbName string) (*Backup, error) {
dname := C.CString(dstDbName)
sname := C.CString(srcDbName)
defer C.free(unsafe.Pointer(dname))
defer C.free(unsafe.Pointer(sname))
......@@ -32,6 +45,7 @@ func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup,
return &Backup{sb, dst, src}, nil
}
// Encapsulates backup API
type Backup struct {
sb *C.sqlite3_backup
dst, src *Conn
......@@ -46,6 +60,7 @@ func (b *Backup) Step(npage int) error {
return Errno(rv)
}
// Backup progression
type BackupStatus struct {
Remaining int
PageCount int
......@@ -67,7 +82,9 @@ func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) error {
if c != nil {
c <- b.Status()
}
time.Sleep(sleepNs)
if sleepNs > 0 {
time.Sleep(sleepNs)
}
}
return b.dst.error(C.sqlite3_errcode(b.dst.db))
}
......
......@@ -18,23 +18,43 @@ import (
)
type BlobReader struct {
c *Conn
bl *C.sqlite3_blob
c *Conn
bl *C.sqlite3_blob
ReadOffset int
}
type BlobReadWriter struct {
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
// 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
func (c *Conn) NewBlobReader(db, table, column string, row int64) (*BlobReader, error) {
bl, err := c.blob_open(db, table, column, row, false)
if err != nil {
return nil, err
}
return &BlobReader{c, bl}, nil
return &BlobReader{c, bl, 0}, nil
}
// Calls http://sqlite.org/c3ref/blob_open.html
......@@ -43,7 +63,7 @@ func (c *Conn) NewBlobReadWriter(db, table, column string, row int64) (*BlobRead
if err != nil {
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) {
......@@ -83,10 +103,11 @@ func (r *BlobReader) Read(v []byte) (int, error) {
if len(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 {
return 0, r.c.error(rv)
}
r.ReadOffset += len(v)
return len(v), nil
}
......@@ -102,10 +123,11 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
if len(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 {
return 0, w.c.error(rv)
}
w.WriteOffset += len(v)
return len(v), nil
}
......@@ -115,5 +137,6 @@ func (r *BlobReader) Reopen(rowid int64) error {
if rv != C.SQLITE_OK {
return r.c.error(rv)
}
r.ReadOffset = 0
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