Result columns.

This commit is contained in:
Nuno Cruces
2023-01-17 18:31:46 +00:00
parent e59118d548
commit 0652903b6d
4 changed files with 113 additions and 19 deletions

View File

@@ -28,7 +28,6 @@ Roadmap:
- [`modernc.org/sqlite`](https://modernc.org/sqlite) - [`modernc.org/sqlite`](https://modernc.org/sqlite)
Random TODO list: Random TODO list:
- wrap more of the SQLite API, enough to run useful queries;
- create a Go VFS that's enough to use `:memory:` databases without WASI; - create a Go VFS that's enough to use `:memory:` databases without WASI;
- expand that VFS to wrap an `io.ReaderAt`; - expand that VFS to wrap an `io.ReaderAt`;
- optimize small allocations that last a single function call; - optimize small allocations that last a single function call;

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"log" "log"
"github.com/ncruces/go-sqlite3" "github.com/ncruces/go-sqlite3"
@@ -28,6 +29,15 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
for {
if row, err := stmt.Step(); err != nil {
log.Fatal(err)
} else if !row {
break
}
fmt.Println(stmt.ColumnInt(0), stmt.ColumnText(1))
}
err = stmt.Close() err = stmt.Close()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

40
conn.go
View File

@@ -182,46 +182,50 @@ func (c *Conn) new(len uint32) uint32 {
} }
func (c *Conn) newBytes(s []byte) uint32 { func (c *Conn) newBytes(s []byte) uint32 {
ptr := c.new(uint32(len(s))) if s == nil {
return 0
buf, ok := c.memory.Read(ptr, uint32(len(s)))
if !ok {
c.api.free.Call(context.TODO(), uint64(ptr))
panic("sqlite3: failed to init bytes")
} }
copy(buf, s) siz := uint32(len(s))
ptr := c.new(siz)
mem, ok := c.memory.Read(ptr, siz)
if !ok {
c.api.free.Call(context.TODO(), uint64(ptr))
panic("sqlite3: out of range")
}
copy(mem, s)
return ptr return ptr
} }
func (c *Conn) newString(s string) uint32 { func (c *Conn) newString(s string) uint32 {
ptr := c.new(uint32(len(s) + 1)) siz := uint32(len(s) + 1)
ptr := c.new(siz)
buf, ok := c.memory.Read(ptr, uint32(len(s)+1)) mem, ok := c.memory.Read(ptr, siz)
if !ok { if !ok {
c.api.free.Call(context.TODO(), uint64(ptr)) c.api.free.Call(context.TODO(), uint64(ptr))
panic("sqlite3: failed to init string") panic("sqlite3: out of range")
} }
buf[len(s)] = 0 mem[len(s)] = 0
copy(buf, s) copy(mem, s)
return ptr return ptr
} }
func (c *Conn) getString(ptr, maxlen uint32) string { func (c *Conn) getString(ptr, maxlen uint32) string {
buf, ok := c.memory.Read(ptr, maxlen) mem, ok := c.memory.Read(ptr, maxlen)
if !ok { if !ok {
if size := c.memory.Size(); ptr < size { if size := c.memory.Size(); ptr < size {
buf, ok = c.memory.Read(ptr, size-ptr) mem, ok = c.memory.Read(ptr, size-ptr)
} }
if !ok { if !ok {
panic("sqlite3: invalid pointer") panic("sqlite3: out of range")
} }
} }
if i := bytes.IndexByte(buf, 0); i < 0 { if i := bytes.IndexByte(mem, 0); i < 0 {
panic("sqlite3: missing NUL terminator") panic("sqlite3: missing NUL terminator")
} else { } else {
return string(buf[:i]) return string(mem[:i])
} }
} }

81
stmt.go
View File

@@ -103,3 +103,84 @@ func (s *Stmt) BindNull(param int) error {
} }
return s.c.error(r[0]) return s.c.error(r[0])
} }
func (s *Stmt) ColumnBool(col int) bool {
if i := s.ColumnInt64(col); i != 0 {
return true
}
return false
}
func (s *Stmt) ColumnInt(col int) int {
return int(s.ColumnInt64(col))
}
func (s *Stmt) ColumnInt64(col int) int64 {
r, err := s.c.api.columnInteger.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
return int64(r[0])
}
func (s *Stmt) ColumnFloat(col int) float64 {
r, err := s.c.api.columnInteger.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
return math.Float64frombits(r[0])
}
func (s *Stmt) ColumnText(col int) string {
r, err := s.c.api.columnText.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
ptr := uint32(r[0])
if ptr == 0 {
// handle error
return ""
}
r, err = s.c.api.columnBytes.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
mem, ok := s.c.memory.Read(ptr, uint32(r[0]))
if !ok {
panic("sqlite3: out of range")
}
return string(mem)
}
func (s *Stmt) ColumnBlob(col int, buf []byte) int {
r, err := s.c.api.columnBlob.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
ptr := uint32(r[0])
if ptr == 0 {
// handle error
return 0
}
r, err = s.c.api.columnBytes.Call(context.TODO(),
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
mem, ok := s.c.memory.Read(ptr, uint32(r[0]))
if !ok {
panic("sqlite3: out of range")
}
return copy(mem, buf)
}