Commit ab027b97 authored by gwenn's avatar gwenn

Fix garbage collection problem with user defined functions.

parent d1b8699e
......@@ -29,7 +29,7 @@ type BlobReadWriter struct {
}
// Zeroblobs are used to reserve space for a BLOB that is later written.
//
//
// Example:
// s, err := db.Prepare("INSERT INTO test VALUES (?)")
// // check err
......
......@@ -31,6 +31,8 @@ func (d *Driver) Open(name string) (driver.Conn, error) {
return &connImpl{c}, nil
}
// PRAGMA schema_version may be used to detect when the database schema is altered
func (c *connImpl) Exec(query string, args []interface{}) (driver.Result, error) {
if err := c.c.Exec(query, args...); err != nil {
return nil, err
......
This diff is collapsed.
......@@ -2,6 +2,7 @@ package sqlite_test
import (
. "github.com/gwenn/gosqlite"
"math/rand"
"regexp"
"testing"
)
......@@ -47,12 +48,13 @@ func re(ctx *Context, nArg int) {
ctx.ResultError(err.Error())
return
}
ctx.SetAuxData(0, re, nil)
ctx.SetAuxData(0, re)
} else {
//println("Reuse")
var ok bool
if re, ok = ad.(*regexp.Regexp); !ok {
ctx.ResultError("AuxData not a regexp ")
println(ad)
ctx.ResultError("AuxData not a regexp")
return
}
}
......@@ -102,3 +104,62 @@ func TestRegexpFunction(t *testing.T) {
t.Fatalf("couldn't finalize statement: %s", err)
}
}
func randomFill(db *Conn, n int) {
db.Exec("DROP TABLE IF EXISTS test")
db.Exec("CREATE TABLE test (name TEXT, rank int)")
s, _ := db.Prepare("INSERT INTO test (name, rank) VALUES (?, ?)")
names := []string{"Bart", "Homer", "Lisa", "Maggie", "Marge"}
db.Begin()
for i := 0; i < n; i++ {
s.Exec(names[rand.Intn(len(names))], rand.Intn(100))
}
s.Finalize()
db.Commit()
}
func BenchmarkLike(b *testing.B) {
b.StopTimer()
db, _ := Open("")
defer db.Close()
randomFill(db, 1000)
b.StartTimer()
for i := 0; i < b.N; i++ {
cs, _ := db.Prepare("SELECT count(1) FROM test where name like 'lisa'")
Must(cs.Next())
cs.Finalize()
}
}
func BenchmarkHalf(b *testing.B) {
b.StopTimer()
db, _ := Open("")
defer db.Close()
randomFill(db, 1000)
db.CreateScalarFunction("half", 1, nil, half, nil)
b.StartTimer()
for i := 0; i < b.N; i++ {
cs, _ := db.Prepare("SELECT count(1) FROM test where half(rank) > 20")
Must(cs.Next())
cs.Finalize()
}
}
func BenchmarkRegexp(b *testing.B) {
b.StopTimer()
db, _ := Open("")
defer db.Close()
randomFill(db, 1000)
db.CreateScalarFunction("regexp", 2, nil, re, reDestroy)
b.StartTimer()
for i := 0; i < b.N; i++ {
cs, _ := db.Prepare("SELECT count(1) FROM test where name regexp '(?i)\\blisa\\b'")
Must(cs.Next())
cs.Finalize()
}
}
......@@ -53,7 +53,7 @@ func (e *ConnError) Code() Errno {
return e.code
}
// FIXME it might be the case that a second error occurs on a separate thread in between the time of the first error and the call to this method.
// FIXME it might be the case that a second error occurs on a separate thread in between the time of the first error and the call to this method.
func (e *ConnError) ExtendedCode() int {
return int(C.sqlite3_extended_errcode(e.c.db))
}
......@@ -211,7 +211,7 @@ type Conn struct {
commitHook *sqliteCommitHook
rollbackHook *sqliteRollbackHook
updateHook *sqliteUpdateHook
udfs map[string]*sqliteScalarFunction
udfs map[string]*sqliteFunction
}
// Run-time library version number
......@@ -238,7 +238,7 @@ const (
// Open a new database connection.
// ":memory:" for memory db
// "" for temp file db
//
//
// Example:
// db, err := sqlite.Open(":memory:")
// if err != nil {
......@@ -302,8 +302,8 @@ func (c *Conn) EnableFKey(b bool) (bool, error) {
}
// Calls sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, -1)
// Another way is PRAGMA foreign_keys;
//
// Another way is PRAGMA foreign_keys;
//
// http://sqlite.org/c3ref/c_dbconfig_enable_fkey.html
func (c *Conn) IsFKeyEnabled() (bool, error) {
return c.queryOrSetEnableFKey(-1)
......
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