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_blob_open
sqlite3_blob_close
sqlite3_blob_reopen
sqlite3_blob_bytes
sqlite3_blob_read
sqlite3_blob_write
sqlite3_blob_reopen
sqlite3_backup_init
sqlite3_backup_step
sqlite3_backup_finish

View File

@@ -162,6 +162,16 @@ func newModule(mod api.Module) (m *module, err error) {
valueText: getFun("sqlite3_value_text"),
valueBlob: getFun("sqlite3_value_blob"),
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 {
return nil, err
@@ -326,10 +336,10 @@ type sqliteAPI struct {
step api.Function
exec api.Function
clearBindings api.Function
bindNull api.Function
bindCount api.Function
bindIndex api.Function
bindName api.Function
bindNull api.Function
bindInteger api.Function
bindFloat api.Function
bindText api.Function
@@ -364,5 +374,15 @@ type sqliteAPI struct {
valueText api.Function
valueBlob 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
}

View File

@@ -131,10 +131,11 @@ func (s *Stmt) BindName(param int) string {
//
// https://www.sqlite.org/c3ref/bind_blob.html
func (s *Stmt) BindBool(param int, value bool) error {
var i int64
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.