Refactor.

This commit is contained in:
Nuno Cruces
2023-07-03 17:08:16 +01:00
parent 1cc7ecfe8d
commit f6d7c5e9c5
5 changed files with 52 additions and 61 deletions

View File

@@ -21,7 +21,7 @@ type Context struct {
// 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) {
func (c Context) ResultBool(value bool) {
var i int64
if value {
i = 1
@@ -32,14 +32,14 @@ func (c *Context) ResultBool(value bool) {
// ResultInt sets the result of the function to an int.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultInt(value int) {
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) {
func (c Context) ResultInt64(value int64) {
c.call(c.api.resultInteger,
uint64(c.handle), uint64(value))
}
@@ -47,7 +47,7 @@ func (c *Context) ResultInt64(value int64) {
// ResultFloat sets the result of the function to a float64.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultFloat(value float64) {
func (c Context) ResultFloat(value float64) {
c.call(c.api.resultFloat,
uint64(c.handle), math.Float64bits(value))
}
@@ -55,7 +55,7 @@ func (c *Context) ResultFloat(value float64) {
// ResultText sets the result of the function to a string.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultText(value string) {
func (c Context) ResultText(value string) {
ptr := c.newString(value)
c.call(c.api.resultText,
uint64(c.handle), uint64(ptr), uint64(len(value)),
@@ -66,7 +66,7 @@ func (c *Context) ResultText(value string) {
// 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) {
func (c Context) ResultBlob(value []byte) {
ptr := c.newBytes(value)
c.call(c.api.resultBlob,
uint64(c.handle), uint64(ptr), uint64(len(value)),
@@ -76,7 +76,7 @@ func (c *Context) ResultBlob(value []byte) {
// 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) {
func (c Context) ResultZeroBlob(n int64) {
c.call(c.api.resultZeroBlob,
uint64(c.handle), uint64(n))
}
@@ -84,7 +84,7 @@ func (c *Context) ResultZeroBlob(n int64) {
// ResultNull sets the result of the function to NULL.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultNull() {
func (c Context) ResultNull() {
c.call(c.api.resultNull,
uint64(c.handle))
}
@@ -92,7 +92,7 @@ func (c *Context) ResultNull() {
// 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) {
func (c Context) ResultTime(value time.Time, format TimeFormat) {
if format == TimeFormatDefault {
c.resultRFC3339Nano(value)
return
@@ -109,7 +109,7 @@ func (c *Context) ResultTime(value time.Time, format TimeFormat) {
}
}
func (c *Context) resultRFC3339Nano(value time.Time) {
func (c Context) resultRFC3339Nano(value time.Time) {
const maxlen = uint64(len(time.RFC3339Nano))
ptr := c.new(maxlen)
@@ -124,7 +124,7 @@ func (c *Context) resultRFC3339Nano(value time.Time) {
// ResultError sets the result of the function an error.
//
// https://www.sqlite.org/c3ref/result_blob.html
func (c *Context) ResultError(err error) {
func (c Context) ResultError(err error) {
if errors.Is(err, NOMEM) {
c.call(c.api.resultErrorMem, uint64(c.handle))
return
@@ -137,7 +137,7 @@ func (c *Context) ResultError(err error) {
str := err.Error()
ptr := c.newString(str)
c.call(c.api.resultBlob,
c.call(c.api.resultError,
uint64(c.handle), uint64(ptr), uint64(len(str)))
c.free(ptr)
@@ -152,6 +152,6 @@ func (c *Context) ResultError(err error) {
}
if code != 0 {
c.call(c.api.resultErrorCode,
uint64(c.handle), uint64(xcode))
uint64(c.handle), uint64(code))
}
}

55
func.go
View File

@@ -56,8 +56,12 @@ func (c *Conn) CreateWindowFunction(name string, nArg int, flag FunctionFlag, fn
//
// https://www.sqlite.org/appfunc.html
type AggregateFunction interface {
// Step is invoked to add a row to the current window.
// The function arguments, if any, corresponding to the row being added are passed to Step.
Step(ctx Context, arg ...Value)
Final(ctx Context)
// Value is invoked to return the current value of the aggregate.
Value(ctx Context)
}
// WindowFunction is the interface an aggregate window function should implement.
@@ -65,7 +69,9 @@ type AggregateFunction interface {
// https://www.sqlite.org/windowfunctions.html
type WindowFunction interface {
AggregateFunction
Value(ctx Context)
// Inverse is invoked to remove the oldest presently aggregated result of Step from the current window.
// The function arguments, if any, are those passed to Step for the row being removed.
Inverse(ctx Context, arg ...Value)
}
@@ -92,48 +98,35 @@ func callbackCompare(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nK
func callbackFunc(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
module := ctx.Value(moduleKey{}).(*module)
fn := callbackHandle(module, pCtx).(func(ctx Context, arg ...Value))
fn(Context{
module: module,
handle: pCtx,
}, callbackArgs(module, nArg, pArg)...)
fn(Context{module, pCtx}, callbackArgs(module, nArg, pArg)...)
}
func callbackStep(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
module := ctx.Value(moduleKey{}).(*module)
fn := callbackAggregate(module, pCtx, nil).(AggregateFunction)
fn.Step(Context{
module: module,
handle: pCtx,
}, callbackArgs(module, nArg, pArg)...)
fn.Step(Context{module, pCtx}, callbackArgs(module, nArg, pArg)...)
}
func callbackFinal(ctx context.Context, mod api.Module, pCtx uint32) {
var handle uint32
module := ctx.Value(moduleKey{}).(*module)
fn := callbackAggregate(module, pCtx, &handle).(AggregateFunction)
fn.Final(Context{
module: module,
handle: pCtx,
})
util.DelHandle(ctx, handle)
fn.Value(Context{module, pCtx})
if err := util.DelHandle(ctx, handle); err != nil {
Context{module, pCtx}.ResultError(err)
}
}
func callbackValue(ctx context.Context, mod api.Module, pCtx uint32) {
module := ctx.Value(moduleKey{}).(*module)
fn := callbackAggregate(module, pCtx, nil).(WindowFunction)
fn.Value(Context{
module: module,
handle: pCtx,
})
fn := callbackAggregate(module, pCtx, nil).(AggregateFunction)
fn.Value(Context{module, pCtx})
}
func callbackInverse(ctx context.Context, mod api.Module, pCtx, nArg, pArg uint32) {
module := ctx.Value(moduleKey{}).(*module)
fn := callbackAggregate(module, pCtx, nil).(WindowFunction)
fn.Inverse(Context{
module: module,
handle: pCtx,
}, callbackArgs(module, nArg, pArg)...)
fn.Inverse(Context{module, pCtx}, callbackArgs(module, nArg, pArg)...)
}
func callbackHandle(module *module, pCtx uint32) any {
@@ -141,18 +134,21 @@ func callbackHandle(module *module, pCtx uint32) any {
return util.GetHandle(module.ctx, pApp)
}
func callbackAggregate(module *module, pCtx uint32, delete *uint32) any {
func callbackAggregate(module *module, pCtx uint32, close *uint32) any {
// On close, we're getting rid of the handle.
// Don't allocate space to store it.
var size uint64
if delete == nil {
if close == nil {
size = ptrlen
}
ptr := uint32(module.call(module.api.aggregateCtx, uint64(pCtx), size))
if ptr != 0 {
// Try loading the handle, if we already have one, or want a new one.
if ptr != 0 || size != 0 {
if handle := util.ReadUint32(module.mod, ptr); handle != 0 {
fn := util.GetHandle(module.ctx, handle)
if delete != nil {
*delete = handle
if close != nil {
*close = handle
}
if fn != nil {
return fn
@@ -160,6 +156,7 @@ func callbackAggregate(module *module, pCtx uint32, delete *uint32) any {
}
}
// Create a new aggregate and store the handle.
fn := callbackHandle(module, pCtx).(func() AggregateFunction)()
if ptr != 0 {
util.WriteUint32(module.mod, ptr, util.AddHandle(module.ctx, fn))

View File

@@ -61,18 +61,12 @@ func ExampleConn_CreateWindowFunction() {
// 0
}
type countASCII struct {
result int
}
type countASCII struct{ result int }
func newASCIICounter() sqlite3.AggregateFunction {
return &countASCII{}
}
func (f *countASCII) Final(ctx sqlite3.Context) {
f.Value(ctx)
}
func (f *countASCII) Value(ctx sqlite3.Context) {
ctx.ResultInt(f.result)
}

View File

@@ -18,7 +18,7 @@ type Value struct {
// Type returns the initial [Datatype] of the value.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Type() Datatype {
func (v Value) Type() Datatype {
r := v.call(v.api.valueType, uint64(v.handle))
return Datatype(r)
}
@@ -29,7 +29,7 @@ func (v *Value) Type() Datatype {
// with 0 converted to false and any other value to true.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Bool() bool {
func (v Value) Bool() bool {
if i := v.Int64(); i != 0 {
return true
}
@@ -39,14 +39,14 @@ func (v *Value) Bool() bool {
// Int returns the value as an int.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Int() int {
func (v Value) Int() int {
return int(v.Int64())
}
// Int64 returns the value as an int64.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Int64() int64 {
func (v Value) Int64() int64 {
r := v.call(v.api.valueInteger, uint64(v.handle))
return int64(r)
}
@@ -54,7 +54,7 @@ func (v *Value) Int64() int64 {
// Float returns the value as a float64.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Float() float64 {
func (v Value) Float() float64 {
r := v.call(v.api.valueFloat, uint64(v.handle))
return math.Float64frombits(r)
}
@@ -62,7 +62,7 @@ func (v *Value) Float() float64 {
// Time returns the value as a [time.Time].
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Time(format TimeFormat) time.Time {
func (v Value) Time(format TimeFormat) time.Time {
var a any
switch v.Type() {
case INTEGER:
@@ -83,7 +83,7 @@ func (v *Value) Time(format TimeFormat) time.Time {
// Text returns the value as a string.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Text() string {
func (v Value) Text() string {
return string(v.RawText())
}
@@ -91,7 +91,7 @@ func (v *Value) Text() string {
// the value as a []byte.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) Blob(buf []byte) []byte {
func (v Value) Blob(buf []byte) []byte {
return append(buf, v.RawBlob()...)
}
@@ -100,7 +100,7 @@ func (v *Value) Blob(buf []byte) []byte {
// subsequent calls to [Value] methods.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) RawText() []byte {
func (v Value) RawText() []byte {
r := v.call(v.api.valueText, uint64(v.handle))
return v.rawBytes(uint32(r))
}
@@ -110,12 +110,12 @@ func (v *Value) RawText() []byte {
// subsequent calls to [Value] methods.
//
// https://www.sqlite.org/c3ref/value_blob.html
func (v *Value) RawBlob() []byte {
func (v Value) RawBlob() []byte {
r := v.call(v.api.valueBlob, uint64(v.handle))
return v.rawBytes(uint32(r))
}
func (v *Value) rawBytes(ptr uint32) []byte {
func (v Value) rawBytes(ptr uint32) []byte {
if ptr == 0 {
return nil
}

View File

@@ -15,7 +15,7 @@ type VFS interface {
FullPathname(name string) (string, error)
}
// VFSParams extends VFS to with the ability to handle URI parameters
// VFSParams extends VFS with the ability to handle URI parameters
// through the OpenParams method.
//
// https://www.sqlite.org/c3ref/uri_boolean.html