Files
sqlite3/stmt.go

314 lines
7.9 KiB
Go
Raw Normal View History

2023-01-15 04:35:37 +00:00
package sqlite3
2023-01-17 13:43:16 +00:00
import (
"math"
)
2023-01-15 04:35:37 +00:00
2023-02-10 14:14:19 +00:00
// Stmt is a prepared statement object.
//
// https://www.sqlite.org/c3ref/stmt.html
2023-01-15 04:35:37 +00:00
type Stmt struct {
c *Conn
handle uint32
2023-01-21 00:33:46 +00:00
err error
2023-01-15 04:35:37 +00:00
}
2023-02-10 14:14:19 +00:00
// Close destroys the prepared statement object.
//
// https://www.sqlite.org/c3ref/finalize.html
2023-01-15 04:35:37 +00:00
func (s *Stmt) Close() error {
2023-02-10 14:14:19 +00:00
if s == nil {
return nil
}
2023-01-18 12:44:14 +00:00
r, err := s.c.api.finalize.Call(s.c.ctx, uint64(s.handle))
2023-01-15 04:35:37 +00:00
if err != nil {
return err
}
s.handle = 0
2023-01-17 13:43:16 +00:00
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// Reset resets the prepared statement object.
//
// https://www.sqlite.org/c3ref/reset.html
2023-01-17 15:01:30 +00:00
func (s *Stmt) Reset() error {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.reset.Call(s.c.ctx, uint64(s.handle))
2023-01-17 15:01:30 +00:00
if err != nil {
return err
}
2023-02-10 14:14:19 +00:00
s.err = nil
2023-01-17 15:01:30 +00:00
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// ClearBindings resets all bindings on the prepared statement.
//
// https://www.sqlite.org/c3ref/clear_bindings.html
func (s *Stmt) ClearBindings() error {
r, err := s.c.api.clearBindings.Call(s.c.ctx, uint64(s.handle))
if err != nil {
return err
}
return s.c.error(r[0])
}
// Step evaluates the SQL statement.
// If the SQL statement being executed returns any data,
// then true is returned each time a new row of data is ready for processing by the caller.
// The values may be accessed using the Column access functions.
// Step is called again to retrieve the next row of data.
// If an error has occurred, Step returns false;
// call [Stmt.Err] or [Stmt.Reset] to get the error.
//
// https://www.sqlite.org/c3ref/step.html
2023-01-21 00:33:46 +00:00
func (s *Stmt) Step() bool {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.step.Call(s.c.ctx, uint64(s.handle))
2023-01-17 15:01:30 +00:00
if err != nil {
2023-01-21 00:33:46 +00:00
s.err = err
return false
2023-01-17 15:01:30 +00:00
}
if r[0] == _ROW {
2023-01-21 00:33:46 +00:00
return true
2023-01-17 15:01:30 +00:00
}
if r[0] == _DONE {
2023-01-21 00:33:46 +00:00
s.err = nil
} else {
s.err = s.c.error(r[0])
2023-01-17 15:01:30 +00:00
}
2023-01-21 00:33:46 +00:00
return false
}
2023-02-10 14:14:19 +00:00
// Err gets the last error occurred during [Stmt.Step].
// Err returns nil after [Stmt.Reset] is called.
//
// https://www.sqlite.org/c3ref/step.html
2023-01-21 00:33:46 +00:00
func (s *Stmt) Err() error {
return s.err
2023-01-17 15:01:30 +00:00
}
2023-02-10 14:14:19 +00:00
// Exec is a convenience function that repeatedly calls [Stmt.Step] until it returns false,
// then calls [Stmt.Reset] to reset the statement and get any error that occurred.
2023-02-08 00:00:53 +00:00
func (s *Stmt) Exec() error {
for s.Step() {
}
2023-02-10 14:14:19 +00:00
return s.Reset()
2023-02-08 00:00:53 +00:00
}
2023-02-10 14:14:19 +00:00
// BindBool binds a bool to the prepared statement.
// The leftmost SQL parameter has an index of 1.
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are stored as integers 0 (false) and 1 (true).
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindBool(param int, value bool) error {
if value {
return s.BindInt64(param, 1)
}
return s.BindInt64(param, 0)
}
2023-02-10 14:14:19 +00:00
// BindInt binds an int to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindInt(param int, value int) error {
return s.BindInt64(param, int64(value))
}
2023-02-10 14:14:19 +00:00
// BindInt64 binds an int64 to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindInt64(param int, value int64) error {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.bindInteger.Call(s.c.ctx,
2023-01-17 13:43:16 +00:00
uint64(s.handle), uint64(param), uint64(value))
if err != nil {
return err
}
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// BindFloat binds a float64 to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindFloat(param int, value float64) error {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.bindFloat.Call(s.c.ctx,
2023-01-17 13:43:16 +00:00
uint64(s.handle), uint64(param), math.Float64bits(value))
if err != nil {
return err
}
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// BindText binds a string to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindText(param int, value string) error {
ptr := s.c.newString(value)
2023-01-18 12:44:14 +00:00
r, err := s.c.api.bindText.Call(s.c.ctx,
2023-01-17 13:43:16 +00:00
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
s.c.api.destructor, _UTF8)
if err != nil {
return err
}
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// BindBlob binds a []byte to the prepared statement.
// The leftmost SQL parameter has an index of 1.
// Binding a nil slice is the same as calling [Stmt.BindNull].
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindBlob(param int, value []byte) error {
ptr := s.c.newBytes(value)
2023-01-18 12:44:14 +00:00
r, err := s.c.api.bindBlob.Call(s.c.ctx,
2023-01-17 13:43:16 +00:00
uint64(s.handle), uint64(param),
uint64(ptr), uint64(len(value)),
s.c.api.destructor)
if err != nil {
return err
}
return s.c.error(r[0])
}
2023-02-10 14:14:19 +00:00
// BindNull binds a NULL to the prepared statement.
// The leftmost SQL parameter has an index of 1.
//
// https://www.sqlite.org/c3ref/bind_blob.html
2023-01-17 13:43:16 +00:00
func (s *Stmt) BindNull(param int) error {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.bindNull.Call(s.c.ctx,
2023-01-17 13:43:16 +00:00
uint64(s.handle), uint64(param))
if err != nil {
return err
2023-01-15 04:35:37 +00:00
}
2023-01-17 13:43:16 +00:00
return s.c.error(r[0])
2023-01-15 04:35:37 +00:00
}
2023-01-17 18:31:46 +00:00
2023-02-10 14:14:19 +00:00
// ColumnType returns the initial [Datatype] of the result column.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-02-08 00:00:53 +00:00
func (s *Stmt) ColumnType(col int) Datatype {
r, err := s.c.api.columnType.Call(s.c.ctx,
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
return Datatype(r[0])
}
2023-02-10 14:14:19 +00:00
// ColumnBool returns the value of the result column as a bool.
// The leftmost column of the result set has the index 0.
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are retrieved as integers,
// with 0 converted to false and any other value to true.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-17 18:31:46 +00:00
func (s *Stmt) ColumnBool(col int) bool {
if i := s.ColumnInt64(col); i != 0 {
return true
}
return false
}
2023-02-10 14:14:19 +00:00
// ColumnInt returns the value of the result column as an int.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-17 18:31:46 +00:00
func (s *Stmt) ColumnInt(col int) int {
return int(s.ColumnInt64(col))
}
2023-02-10 14:14:19 +00:00
// ColumnInt64 returns the value of the result column as an int64.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-17 18:31:46 +00:00
func (s *Stmt) ColumnInt64(col int) int64 {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.columnInteger.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
return int64(r[0])
}
2023-02-10 14:14:19 +00:00
// ColumnFloat returns the value of the result column as a float64.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-17 18:31:46 +00:00
func (s *Stmt) ColumnFloat(col int) float64 {
2023-02-08 00:00:53 +00:00
r, err := s.c.api.columnFloat.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
return math.Float64frombits(r[0])
}
2023-02-10 14:14:19 +00:00
// ColumnText returns the value of the result column as a string.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-17 18:31:46 +00:00
func (s *Stmt) ColumnText(col int) string {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.columnText.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
ptr := uint32(r[0])
if ptr == 0 {
2023-01-21 12:09:54 +00:00
r, err = s.c.api.errcode.Call(s.c.ctx, uint64(s.handle))
if err != nil {
panic(err)
}
s.err = s.c.error(r[0])
2023-01-17 18:31:46 +00:00
return ""
}
2023-01-18 12:44:14 +00:00
r, err = s.c.api.columnBytes.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
2023-01-29 02:11:41 +00:00
mem := s.c.mem.view(ptr, uint32(r[0]))
2023-01-17 18:31:46 +00:00
return string(mem)
}
2023-02-10 14:14:19 +00:00
// ColumnBlob appends to buf and returns
// the value of the result column as a []byte.
// The leftmost column of the result set has the index 0.
//
// https://www.sqlite.org/c3ref/column_blob.html
2023-01-21 12:09:54 +00:00
func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
2023-01-18 12:44:14 +00:00
r, err := s.c.api.columnBlob.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
ptr := uint32(r[0])
if ptr == 0 {
2023-01-21 12:09:54 +00:00
r, err = s.c.api.errcode.Call(s.c.ctx, uint64(s.handle))
if err != nil {
panic(err)
}
s.err = s.c.error(r[0])
2023-02-08 00:00:53 +00:00
return buf[0:0]
2023-01-17 18:31:46 +00:00
}
2023-01-18 12:44:14 +00:00
r, err = s.c.api.columnBytes.Call(s.c.ctx,
2023-01-17 18:31:46 +00:00
uint64(s.handle), uint64(col))
if err != nil {
panic(err)
}
2023-01-29 02:11:41 +00:00
mem := s.c.mem.view(ptr, uint32(r[0]))
2023-01-21 12:09:54 +00:00
return append(buf[0:0], mem...)
2023-01-17 18:31:46 +00:00
}