mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Documentation.
This commit is contained in:
17
conn.go
17
conn.go
@@ -53,13 +53,18 @@ func OpenFlags(filename string, flags OpenFlag) (conn *Conn, err error) {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close closes a database connection.
|
||||
// Close closes the database connection.
|
||||
//
|
||||
// If the database connection is associated with unfinalized prepared statements,
|
||||
// open blob handles, and/or unfinished backup objects,
|
||||
// Close will leave the database connection open and return [BUSY].
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/close.html
|
||||
func (c *Conn) Close() error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
r, err := c.api.close.Call(c.ctx, uint64(c.handle))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -68,6 +73,8 @@ func (c *Conn) Close() error {
|
||||
if err := c.error(r[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.handle = 0
|
||||
return c.mem.mod.Close(c.ctx)
|
||||
}
|
||||
|
||||
@@ -86,17 +93,17 @@ func (c *Conn) Exec(sql string) error {
|
||||
return c.error(r[0])
|
||||
}
|
||||
|
||||
// Prepare calls [PrepareFlags] with no flags.
|
||||
// Prepare calls [Conn.PrepareFlags] with no flags.
|
||||
func (c *Conn) Prepare(sql string) (stmt *Stmt, tail string, err error) {
|
||||
return c.PrepareFlags(sql, 0)
|
||||
}
|
||||
|
||||
// PrepareFlags compiles the first statement in sql;
|
||||
// PrepareFlags compiles the first SQL statement in sql;
|
||||
// tail is left pointing to what remains uncompiled.
|
||||
// If the input text contains no SQL (if the input is an empty string or a comment),
|
||||
// both stmt and err will be nil
|
||||
// both stmt and err will be nil.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/exec.html
|
||||
// https://www.sqlite.org/c3ref/prepare.html
|
||||
func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail string, err error) {
|
||||
sqlPtr := c.newString(sql)
|
||||
stmtPtr := c.new(ptrlen)
|
||||
|
||||
@@ -121,3 +121,8 @@ func TestConn_free(t *testing.T) {
|
||||
|
||||
db.free(ptr)
|
||||
}
|
||||
|
||||
func TestConn_Close(t *testing.T) {
|
||||
var conn *Conn
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/ncruces/go-sqlite3
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/ncruces/julianday v0.1.4
|
||||
github.com/ncruces/julianday v0.1.5
|
||||
github.com/tetratelabs/wazero v1.0.0-pre.8
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.5.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1,5 +1,5 @@
|
||||
github.com/ncruces/julianday v0.1.4 h1:PFv147rE9ZApvAJW8yBcASI104HyNtBTnNsZpJB4tAI=
|
||||
github.com/ncruces/julianday v0.1.4/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/ncruces/julianday v0.1.5 h1:hDJ9ejiMp3DHsoZ5KW4c1lwfMjbARS7u/gbYcd0FBZk=
|
||||
github.com/ncruces/julianday v0.1.5/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/tetratelabs/wazero v1.0.0-pre.8 h1:Ir82PWj79WCppH+9ny73eGY2qv+oCnE3VwMY92cBSyI=
|
||||
github.com/tetratelabs/wazero v1.0.0-pre.8/go.mod h1:u8wrFmpdrykiFK0DFPiFm5a4+0RzsdmXYVtijBKqUVo=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
|
||||
109
stmt.go
109
stmt.go
@@ -4,13 +4,23 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Stmt is a prepared statement object.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/stmt.html
|
||||
type Stmt struct {
|
||||
c *Conn
|
||||
handle uint32
|
||||
err error
|
||||
}
|
||||
|
||||
// Close destroys the prepared statement object.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/finalize.html
|
||||
func (s *Stmt) Close() error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
r, err := s.c.api.finalize.Call(s.c.ctx, uint64(s.handle))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -20,14 +30,38 @@ func (s *Stmt) Close() error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// Reset resets the prepared statement object.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/reset.html
|
||||
func (s *Stmt) Reset() error {
|
||||
r, err := s.c.api.reset.Call(s.c.ctx, uint64(s.handle))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.err = nil
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) Step() bool {
|
||||
r, err := s.c.api.step.Call(s.c.ctx, uint64(s.handle))
|
||||
if err != nil {
|
||||
@@ -45,20 +79,28 @@ func (s *Stmt) Step() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Err gets the last error occurred during [Stmt.Step].
|
||||
// Err returns nil after [Stmt.Reset] is called.
|
||||
//
|
||||
// https://www.sqlite.org/c3ref/step.html
|
||||
func (s *Stmt) Err() error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (s *Stmt) Exec() error {
|
||||
for s.Step() {
|
||||
}
|
||||
err := s.Err()
|
||||
if rerr := s.Reset(); err == nil {
|
||||
err = rerr
|
||||
}
|
||||
return err
|
||||
return s.Reset()
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindBool(param int, value bool) error {
|
||||
if value {
|
||||
return s.BindInt64(param, 1)
|
||||
@@ -66,10 +108,18 @@ func (s *Stmt) BindBool(param int, value bool) error {
|
||||
return s.BindInt64(param, 0)
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindInt(param int, value int) error {
|
||||
return s.BindInt64(param, int64(value))
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindInt64(param int, value int64) error {
|
||||
r, err := s.c.api.bindInteger.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(param), uint64(value))
|
||||
@@ -79,6 +129,10 @@ func (s *Stmt) BindInt64(param int, value int64) error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindFloat(param int, value float64) error {
|
||||
r, err := s.c.api.bindFloat.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(param), math.Float64bits(value))
|
||||
@@ -88,6 +142,10 @@ func (s *Stmt) BindFloat(param int, value float64) error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindText(param int, value string) error {
|
||||
ptr := s.c.newString(value)
|
||||
r, err := s.c.api.bindText.Call(s.c.ctx,
|
||||
@@ -100,6 +158,11 @@ func (s *Stmt) BindText(param int, value string) error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindBlob(param int, value []byte) error {
|
||||
ptr := s.c.newBytes(value)
|
||||
r, err := s.c.api.bindBlob.Call(s.c.ctx,
|
||||
@@ -112,6 +175,10 @@ func (s *Stmt) BindBlob(param int, value []byte) error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) BindNull(param int) error {
|
||||
r, err := s.c.api.bindNull.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(param))
|
||||
@@ -121,6 +188,10 @@ func (s *Stmt) BindNull(param int) error {
|
||||
return s.c.error(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnType(col int) Datatype {
|
||||
r, err := s.c.api.columnType.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(col))
|
||||
@@ -130,6 +201,13 @@ func (s *Stmt) ColumnType(col int) Datatype {
|
||||
return Datatype(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnBool(col int) bool {
|
||||
if i := s.ColumnInt64(col); i != 0 {
|
||||
return true
|
||||
@@ -137,10 +215,18 @@ func (s *Stmt) ColumnBool(col int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnInt(col int) int {
|
||||
return int(s.ColumnInt64(col))
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnInt64(col int) int64 {
|
||||
r, err := s.c.api.columnInteger.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(col))
|
||||
@@ -150,6 +236,10 @@ func (s *Stmt) ColumnInt64(col int) int64 {
|
||||
return int64(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnFloat(col int) float64 {
|
||||
r, err := s.c.api.columnFloat.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(col))
|
||||
@@ -159,6 +249,10 @@ func (s *Stmt) ColumnFloat(col int) float64 {
|
||||
return math.Float64frombits(r[0])
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnText(col int) string {
|
||||
r, err := s.c.api.columnText.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(col))
|
||||
@@ -186,6 +280,11 @@ func (s *Stmt) ColumnText(col int) string {
|
||||
return string(mem)
|
||||
}
|
||||
|
||||
// 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
|
||||
func (s *Stmt) ColumnBlob(col int, buf []byte) []byte {
|
||||
r, err := s.c.api.columnBlob.Call(s.c.ctx,
|
||||
uint64(s.handle), uint64(col))
|
||||
|
||||
38
stmt_test.go
38
stmt_test.go
@@ -33,6 +33,16 @@ func TestStmt(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = stmt.ClearBindings()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = stmt.Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = stmt.BindBool(1, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -118,7 +128,7 @@ func TestStmt(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The table should have: 0, 1, 2, π, NULL, "", "text", `blob`, NULL
|
||||
// The table should have: 0, NULL, 1, 2, π, NULL, "", "text", `blob`, NULL
|
||||
stmt, _, err = db.Prepare(`SELECT col FROM test`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -145,6 +155,27 @@ func TestStmt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
if stmt.Step() {
|
||||
if got := stmt.ColumnType(0); got != NULL {
|
||||
t.Errorf("got %v, want NULL", got)
|
||||
}
|
||||
if got := stmt.ColumnBool(0); got != false {
|
||||
t.Errorf("got %v, want false", got)
|
||||
}
|
||||
if got := stmt.ColumnInt(0); got != 0 {
|
||||
t.Errorf("got %v, want zero", got)
|
||||
}
|
||||
if got := stmt.ColumnFloat(0); got != 0 {
|
||||
t.Errorf("got %v, want zero", got)
|
||||
}
|
||||
if got := stmt.ColumnText(0); got != "" {
|
||||
t.Errorf("got %q, want empty", got)
|
||||
}
|
||||
if got := stmt.ColumnBlob(0, nil); got != nil {
|
||||
t.Errorf("got %q, want nil", got)
|
||||
}
|
||||
}
|
||||
|
||||
if stmt.Step() {
|
||||
if got := stmt.ColumnType(0); got != INTEGER {
|
||||
t.Errorf("got %v, want INTEGER", got)
|
||||
@@ -323,3 +354,8 @@ func TestStmt(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStmt_Close(t *testing.T) {
|
||||
var stmt *Stmt
|
||||
stmt.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user