Collation callback.

This commit is contained in:
Nuno Cruces
2024-01-26 23:52:45 +00:00
parent 019c71fb55
commit 99ad7ff766
3 changed files with 34 additions and 8 deletions

View File

@@ -21,6 +21,7 @@ type Conn struct {
interrupt context.Context interrupt context.Context
pending *Stmt pending *Stmt
log func(code xErrorCode, msg string) log func(code xErrorCode, msg string)
collation func(name string)
arena arena arena arena
handle uint32 handle uint32

28
func.go
View File

@@ -8,8 +8,25 @@ import (
"github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/api"
) )
// AnyCollationNeeded registers a fake collating function // CollationNeeded registers a callback to be invoked
// for any unknown collating sequence. // whenever an unknown collation sequence is required.
//
// https://sqlite.org/c3ref/collation_needed.html
func (c *Conn) CollationNeeded(cb func(name string)) error {
var enable uint64
if cb != nil {
enable = 1
}
r := c.call("sqlite3_collation_needed_go", uint64(c.handle), enable)
if err := c.error(r); err != nil {
return err
}
c.collation = cb
return nil
}
// AnyCollationNeeded uses [Conn.CollationNeeded] to register
// a fake collating function for any unknown collating sequence.
// The fake collating function works like BINARY. // The fake collating function works like BINARY.
// //
// This can be used to load schemas that contain // This can be used to load schemas that contain
@@ -106,7 +123,12 @@ func destroyCallback(ctx context.Context, mod api.Module, pApp uint32) {
util.DelHandle(ctx, pApp) util.DelHandle(ctx, pApp)
} }
func collationCallback(ctx context.Context, mod api.Module, pArg, pDB, eTextRep, zName uint32) {} func collationCallback(ctx context.Context, mod api.Module, pArg, pDB, eTextRep, zName uint32) {
if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.handle == pDB && c.collation != nil {
name := util.ReadString(mod, zName, _MAX_NAME)
c.collation(name)
}
}
func compareCallback(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nKey2, pKey2 uint32) uint32 { func compareCallback(ctx context.Context, mod api.Module, pApp, nKey1, pKey1, nKey2, pKey2 uint32) uint32 {
fn := util.GetHandle(ctx, pApp).(func(a, b []byte) int) fn := util.GetHandle(ctx, pApp).(func(a, b []byte) int)

View File

@@ -6,11 +6,9 @@ import (
"log" "log"
"regexp" "regexp"
"golang.org/x/text/collate"
"golang.org/x/text/language"
"github.com/ncruces/go-sqlite3" "github.com/ncruces/go-sqlite3"
_ "github.com/ncruces/go-sqlite3/embed" _ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/ext/unicode"
) )
func ExampleConn_CreateCollation() { func ExampleConn_CreateCollation() {
@@ -30,12 +28,17 @@ func ExampleConn_CreateCollation() {
log.Fatal(err) log.Fatal(err)
} }
err = db.CreateCollation("french", collate.New(language.French).Compare) err = db.CollationNeeded(func(name string) {
err := unicode.RegisterCollation(db, name, name)
if err != nil {
log.Fatal(err)
}
})
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE french`) stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE fr_FR`)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }