Wrap context.

This commit is contained in:
Nuno Cruces
2023-06-30 11:48:54 +01:00
parent a6c2fccd74
commit 232a7705b5
4 changed files with 146 additions and 4 deletions

121
context.go Normal file
View File

@@ -0,0 +1,121 @@
package sqlite3
import (
"math"
"time"
"github.com/ncruces/go-sqlite3/internal/util"
)
// Context is the context in which an SQL function executes.
//
// https://www.sqlite.org/c3ref/context.html
type Context struct {
c *Conn
handle uint32
}
// ResultBool sets the result of the function to a bool.
// 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/result_blob.html
func (c *Context) ResultBool(value bool) {
var i int64
if value {
i = 1
}
c.ResultInt64(i)
}
// ResultInt sets the result of the function to an int.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultInt(value int) {
c.ResultInt64(int64(value))
}
// ResultInt64 sets the result of the function to an int64.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultInt64(value int64) {
c.c.call(c.c.api.resultInteger,
uint64(c.handle), uint64(value))
}
// ResultFloat sets the result of the function to a float64.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultFloat(value float64) {
c.c.call(c.c.api.resultFloat,
uint64(c.handle), math.Float64bits(value))
}
// ResultText sets the result of the function to a string.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultText(value string) {
ptr := c.c.newString(value)
c.c.call(c.c.api.resultText,
uint64(c.handle), uint64(ptr), uint64(len(value)),
uint64(c.c.api.destructor), _UTF8)
}
// ResultBlob sets the result of the function to a []byte.
// Returning a nil slice is the same as calling [Context.ResultNull].
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultBlob(value []byte) {
ptr := c.c.newBytes(value)
c.c.call(c.c.api.resultBlob,
uint64(c.handle), uint64(ptr), uint64(len(value)),
uint64(c.c.api.destructor))
}
// BindZeroBlob sets the result of the function to a zero-filled, length n BLOB.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultZeroBlob(n int64) {
c.c.call(c.c.api.resultZeroBlob,
uint64(c.handle), uint64(n))
}
// ResultNull sets the result of the function to NULL.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultNull() {
c.c.call(c.c.api.resultNull,
uint64(c.handle))
}
// ResultTime sets the result of the function to a [time.Time].
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultTime(value time.Time, format TimeFormat) {
if format == TimeFormatDefault {
c.resultRFC3339Nano(value)
return
}
switch v := format.Encode(value).(type) {
case string:
c.ResultText(v)
case int64:
c.ResultInt64(v)
case float64:
c.ResultFloat(v)
default:
panic(util.AssertErr())
}
}
func (c *Context) resultRFC3339Nano(value time.Time) {
const maxlen = uint64(len(time.RFC3339Nano))
ptr := c.c.new(maxlen)
buf := util.View(c.c.mod, ptr, maxlen)
buf = value.AppendFormat(buf[:0], time.RFC3339Nano)
c.c.call(c.c.api.resultText,
uint64(c.handle), uint64(ptr), uint64(len(buf)),
uint64(c.c.api.destructor), _UTF8)
}

View File

@@ -33,10 +33,10 @@ sqlite3_column_blob
sqlite3_column_bytes sqlite3_column_bytes
sqlite3_blob_open sqlite3_blob_open
sqlite3_blob_close sqlite3_blob_close
sqlite3_blob_reopen
sqlite3_blob_bytes sqlite3_blob_bytes
sqlite3_blob_read sqlite3_blob_read
sqlite3_blob_write sqlite3_blob_write
sqlite3_blob_reopen
sqlite3_backup_init sqlite3_backup_init
sqlite3_backup_step sqlite3_backup_step
sqlite3_backup_finish sqlite3_backup_finish

View File

@@ -162,6 +162,16 @@ func newModule(mod api.Module) (m *module, err error) {
valueText: getFun("sqlite3_value_text"), valueText: getFun("sqlite3_value_text"),
valueBlob: getFun("sqlite3_value_blob"), valueBlob: getFun("sqlite3_value_blob"),
valueBytes: getFun("sqlite3_value_bytes"), valueBytes: getFun("sqlite3_value_bytes"),
resultNull: getFun("sqlite3_result_null"),
resultInteger: getFun("sqlite3_result_int64"),
resultFloat: getFun("sqlite3_result_double"),
resultText: getFun("sqlite3_result_text64"),
resultBlob: getFun("sqlite3_result_blob64"),
resultZeroBlob: getFun("sqlite3_result_zeroblob64"),
resultError: getFun("sqlite3_result_error"),
resultErrorCode: getFun("sqlite3_result_error_code"),
resultErrorMem: getFun("sqlite3_result_error_nomem"),
resultErrorBig: getFun("sqlite3_result_error_toobig"),
} }
if err != nil { if err != nil {
return nil, err return nil, err
@@ -326,10 +336,10 @@ type sqliteAPI struct {
step api.Function step api.Function
exec api.Function exec api.Function
clearBindings api.Function clearBindings api.Function
bindNull api.Function
bindCount api.Function bindCount api.Function
bindIndex api.Function bindIndex api.Function
bindName api.Function bindName api.Function
bindNull api.Function
bindInteger api.Function bindInteger api.Function
bindFloat api.Function bindFloat api.Function
bindText api.Function bindText api.Function
@@ -364,5 +374,15 @@ type sqliteAPI struct {
valueText api.Function valueText api.Function
valueBlob api.Function valueBlob api.Function
valueBytes api.Function valueBytes api.Function
resultNull api.Function
resultInteger api.Function
resultFloat api.Function
resultText api.Function
resultBlob api.Function
resultZeroBlob api.Function
resultError api.Function
resultErrorCode api.Function
resultErrorMem api.Function
resultErrorBig api.Function
destructor uint32 destructor uint32
} }

View File

@@ -131,10 +131,11 @@ func (s *Stmt) BindName(param int) string {
// //
// https://www.sqlite.org/c3ref/bind_blob.html // https://www.sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindBool(param int, value bool) error { func (s *Stmt) BindBool(param int, value bool) error {
var i int64
if value { if value {
return s.BindInt64(param, 1) i = 1
} }
return s.BindInt64(param, 0) return s.BindInt64(param, i)
} }
// BindInt binds an int to the prepared statement. // BindInt binds an int to the prepared statement.