Commit fcb3fce3 authored by gwenn's avatar gwenn

Add test with the regexp implementation in Go.

parent bc59e46a
...@@ -46,6 +46,12 @@ static int my_value_numeric_type(sqlite3_value** argv, int i) { ...@@ -46,6 +46,12 @@ static int my_value_numeric_type(sqlite3_value** argv, int i) {
return sqlite3_value_numeric_type(argv[i]); return sqlite3_value_numeric_type(argv[i]);
} }
extern void goXAuxDataDestroy(void *ad);
static void goSqlite3SetAuxdata(sqlite3_context* ctx, int N, void* ad) {
sqlite3_set_auxdata(ctx, N, ad, goXAuxDataDestroy);
}
extern void goXFunc(sqlite3_context* ctx, int argc, sqlite3_value** argv); extern void goXFunc(sqlite3_context* ctx, int argc, sqlite3_value** argv);
extern void goXDestroy(void *pApp); extern void goXDestroy(void *pApp);
...@@ -71,6 +77,14 @@ type Context struct { ...@@ -71,6 +77,14 @@ type Context struct {
argv **C.sqlite3_value argv **C.sqlite3_value
} }
func (c *Context) ResultBool(b bool) {
if b {
c.ResultInt(1)
} else {
c.ResultInt(0)
}
}
// Set the result of an SQL function // Set the result of an SQL function
// Calls sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html // Calls sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html
func (c *Context) ResultBlob(b []byte) { func (c *Context) ResultBlob(b []byte) {
...@@ -162,15 +176,33 @@ func (c *Context) UserData() interface{} { ...@@ -162,15 +176,33 @@ func (c *Context) UserData() interface{} {
// Function auxiliary data // Function auxiliary data
// Calls sqlite3_get_auxdata, http://sqlite.org/c3ref/get_auxdata.html // Calls sqlite3_get_auxdata, http://sqlite.org/c3ref/get_auxdata.html
func (c *Context) GetAuxData(n int) interface{} { func (c *Context) GetAuxData(n int) interface{} {
return C.sqlite3_get_auxdata(c.context, C.int(n)) adp := (*sqliteAuxData)(C.sqlite3_get_auxdata(c.context, C.int(n)))
if adp == nil {
return nil
}
return adp.ad
} }
type AuxDataDestructor func(ad interface{}) type AuxDataDestructor func(ad interface{})
type sqliteAuxData struct {
ad interface{}
d AuxDataDestructor
}
//export goXAuxDataDestroy
func goXAuxDataDestroy(ad unsafe.Pointer) {
adp := (*sqliteAuxData)(ad)
if adp != nil && adp.d != nil {
adp.d(adp.ad)
}
}
// Function auxiliary data // Function auxiliary data
// Calls sqlite3_set_auxdata, http://sqlite.org/c3ref/get_auxdata.html // Calls sqlite3_set_auxdata, http://sqlite.org/c3ref/get_auxdata.html
func (c *Context) SetAuxData(n int, ad interface{}, f AuxDataDestructor) { func (c *Context) SetAuxData(n int, ad interface{}, d AuxDataDestructor) {
// FIXME C.sqlite3_set_auxdata(c.context, C.int(n), unsafe.Pointer(ad), nil /*void (*)(void*)*/ ) // How to make sure it is not gced?
adp := &sqliteAuxData{ad, d}
C.goSqlite3SetAuxdata(c.context, C.int(n), unsafe.Pointer(adp))
} }
// The leftmost value is number 0. // The leftmost value is number 0.
......
...@@ -2,11 +2,17 @@ package sqlite_test ...@@ -2,11 +2,17 @@ package sqlite_test
import ( import (
. "github.com/gwenn/gosqlite" . "github.com/gwenn/gosqlite"
"regexp"
"testing" "testing"
) )
func half(ctx *Context, nArg int) { func half(ctx *Context, nArg int) {
nt := ctx.NumericType(0)
if nt == Integer || nt == Float {
ctx.ResultDouble(ctx.Double(0) / 2) ctx.ResultDouble(ctx.Double(0) / 2)
} else {
ctx.ResultNull()
}
} }
func TestScalarFunction(t *testing.T) { func TestScalarFunction(t *testing.T) {
...@@ -46,3 +52,75 @@ func TestScalarFunction(t *testing.T) { ...@@ -46,3 +52,75 @@ func TestScalarFunction(t *testing.T) {
t.Errorf("couldn't destroy function: %s", err) t.Errorf("couldn't destroy function: %s", err)
} }
} }
func re(ctx *Context, nArg int) {
ad := ctx.GetAuxData(0)
var re *regexp.Regexp
if ad == nil {
//println("Compile")
var err error
re, err = regexp.Compile(ctx.Text(0))
if err != nil {
ctx.ResultError(err.Error())
return
}
ctx.SetAuxData(0, re, nil)
} else {
//println("Reuse")
var ok bool
if re, ok = ad.(*regexp.Regexp); !ok {
ctx.ResultError("AuxData not a regexp ")
return
}
}
m := re.MatchString(ctx.Text(1))
ctx.ResultBool(m)
}
func TestRegexpFunction(t *testing.T) {
db, err := Open("")
if err != nil {
t.Fatalf("couldn't open database file: %s", err)
}
defer db.Close()
err = db.CreateScalarFunction("regexp", 2, nil, re, nil)
if err != nil {
t.Fatalf("couldn't create function: %s", err)
}
s, err := db.Prepare("select regexp('l.s[aeiouy]', name) from (select 'lisa' as name union all select 'bart' as name)")
if err != nil {
t.Fatalf("couldn't prepare statement: %s", err)
}
b, err := s.Next()
if err != nil {
t.Fatalf("couldn't step statement: %s", err)
}
if !b {
t.Fatalf("No result")
}
i, _, err := s.ScanInt(0)
if err != nil {
t.Fatalf("couldn't scan result: %s", err)
}
if i != 1 {
t.Errorf("Expected %d but got %d", 1, i)
}
b, err = s.Next()
if err != nil {
t.Fatalf("couldn't step statement: %s", err)
}
if !b {
t.Fatalf("No result")
}
i, _, err = s.ScanInt(0)
if err != nil {
t.Fatalf("couldn't scan result: %s", err)
}
if i != 0 {
t.Errorf("Expected %d but got %d", 0, i)
}
err = s.Finalize()
if err != nil {
t.Fatalf("couldn't finalize statement: %s", err)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment