mirror of https://github.com/usememos/memos.git
45 lines
1.4 KiB
Go
45 lines
1.4 KiB
Go
// Package sqlite provides SQLite driver implementation with custom functions.
|
|
// Custom functions are registered globally on first use to extend SQLite's
|
|
// limited ASCII-only text operations with proper Unicode support.
|
|
package sqlite
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"sync"
|
|
|
|
"golang.org/x/text/cases"
|
|
msqlite "modernc.org/sqlite"
|
|
)
|
|
|
|
var (
|
|
registerUnicodeLowerOnce sync.Once
|
|
registerUnicodeLowerErr error
|
|
// unicodeFold provides Unicode case folding for case-insensitive comparisons.
|
|
// It's safe to use concurrently and reused across all function calls.
|
|
unicodeFold = cases.Fold()
|
|
)
|
|
|
|
// ensureUnicodeLowerRegistered registers the memos_unicode_lower custom function
|
|
// with SQLite. This function provides proper Unicode case folding for case-insensitive
|
|
// text comparisons, overcoming modernc.org/sqlite's lack of ICU extension.
|
|
//
|
|
// The function is registered once globally and is safe to call multiple times.
|
|
func ensureUnicodeLowerRegistered() error {
|
|
registerUnicodeLowerOnce.Do(func() {
|
|
registerUnicodeLowerErr = msqlite.RegisterScalarFunction("memos_unicode_lower", 1, func(_ *msqlite.FunctionContext, args []driver.Value) (driver.Value, error) {
|
|
if len(args) == 0 || args[0] == nil {
|
|
return nil, nil
|
|
}
|
|
switch v := args[0].(type) {
|
|
case string:
|
|
return unicodeFold.String(v), nil
|
|
case []byte:
|
|
return unicodeFold.String(string(v)), nil
|
|
default:
|
|
return v, nil
|
|
}
|
|
})
|
|
})
|
|
return registerUnicodeLowerErr
|
|
}
|