package sqlrite
import "C"
import (
"database/sql/driver"
"fmt"
"io"
)
type rows struct {
conn *conn
handle *C.SqlriteStatement
cols []string
closed bool
}
var _ driver.Rows = (*rows)(nil)
func (r *rows) Columns() []string {
return r.cols
}
func (r *rows) Close() error {
if r.closed {
return nil
}
r.closed = true
if r.handle != nil {
C.sqlrite_finalize(r.handle)
r.handle = nil
}
return nil
}
func (r *rows) Next(dest []driver.Value) error {
if r.closed || r.handle == nil {
return io.EOF
}
r.conn.mu.Lock()
defer r.conn.mu.Unlock()
status := Status(C.sqlrite_step(r.handle))
switch status {
case statusDone:
return io.EOF
case statusRow:
default:
return wrapErr(status, "step")
}
for i := 0; i < len(dest); i++ {
if i >= len(r.cols) {
dest[i] = nil
continue
}
v, err := readColumn(r.handle, C.int(i))
if err != nil {
return err
}
dest[i] = v
}
return nil
}
func readColumn(handle *C.SqlriteStatement, idx C.int) (driver.Value, error) {
var isNull C.int
if st := Status(C.sqlrite_column_is_null(handle, idx, &isNull)); st != statusOk {
return nil, wrapErr(st, "is_null")
}
if isNull != 0 {
return nil, nil
}
var i int64
if st := Status(C.sqlrite_column_int64(handle, idx, (*C.int64_t)(&i))); st == statusOk {
return i, nil
}
var d C.double
if st := Status(C.sqlrite_column_double(handle, idx, &d)); st == statusOk {
return float64(d), nil
}
var cstr *C.char
if st := Status(C.sqlrite_column_text(handle, idx, &cstr)); st == statusOk {
defer C.sqlrite_free_string(cstr)
return C.GoString(cstr), nil
}
return nil, fmt.Errorf("sqlrite: failed to read column %d", int(idx))
}