Function aux data.

This commit is contained in:
Nuno Cruces
2023-07-04 02:18:03 +01:00
parent 0f7fa6ebc9
commit 632ea933b3
7 changed files with 101 additions and 13 deletions

View File

@@ -16,6 +16,22 @@ type Context struct {
handle uint32
}
// SetAuxData saves metadata for argument n of the function.
//
// https://www.sqlite.org/c3ref/get_auxdata.html
func (c Context) SetAuxData(n int, data any) {
ptr := util.AddHandle(c.ctx, data)
c.call(c.api.setAuxData, uint64(c.handle), uint64(n), uint64(ptr))
}
// GetAuxData returns metadata for argument n of the function.
//
// https://www.sqlite.org/c3ref/get_auxdata.html
func (c Context) GetAuxData(n int) any {
ptr := uint32(c.call(c.api.getAuxData, uint64(c.handle), uint64(n)))
return util.GetHandle(c.ctx, ptr)
}
// ResultBool sets the result of the function to a bool.
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are stored as integers 0 (false) and 1 (true).

View File

@@ -48,12 +48,14 @@ sqlite3_changes64
sqlite3_last_insert_rowid
sqlite3_get_autocommit
sqlite3_anycollseq_init
sqlite3_create_go_collation
sqlite3_create_go_function
sqlite3_create_go_aggregate_function
sqlite3_create_go_window_function
sqlite3_create_collation_go
sqlite3_create_function_go
sqlite3_create_aggregate_function_go
sqlite3_create_window_function_go
sqlite3_aggregate_context
sqlite3_user_data
sqlite3_set_auxdata_go
sqlite3_get_auxdata
sqlite3_value_type
sqlite3_value_int64
sqlite3_value_double

Binary file not shown.

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"log"
"regexp"
"golang.org/x/text/collate"
"golang.org/x/text/language"
@@ -117,3 +118,64 @@ func ExampleConn_CreateFunction() {
// COTÉE
// COTER
}
func ExampleContext_SetAuxData() {
db, err := sqlite3.Open(":memory:")
if err != nil {
log.Fatal(err)
}
err = db.Exec(`CREATE TABLE IF NOT EXISTS words (word VARCHAR(10))`)
if err != nil {
log.Fatal(err)
}
err = db.Exec(`INSERT INTO words (word) VALUES ('côte'), ('cote'), ('coter'), ('coté'), ('cotée'), ('côté')`)
if err != nil {
log.Fatal(err)
}
err = db.CreateFunction("regexp", 2, sqlite3.DETERMINISTIC|sqlite3.INNOCUOUS, func(ctx sqlite3.Context, arg ...sqlite3.Value) {
re, ok := ctx.GetAuxData(0).(*regexp.Regexp)
if !ok {
r, err := regexp.Compile(arg[0].Text())
if err != nil {
ctx.ResultError(err)
return
}
ctx.SetAuxData(0, r)
re = r
}
ctx.ResultBool(re.Match(arg[1].RawText()))
})
if err != nil {
log.Fatal(err)
}
stmt, _, err := db.Prepare(`SELECT word FROM words WHERE word REGEXP '^\p{L}+e$'`)
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
for stmt.Step() {
fmt.Println(stmt.ColumnText(0))
}
if err := stmt.Err(); err != nil {
log.Fatal(err)
}
err = stmt.Close()
if err != nil {
log.Fatal(err)
}
err = db.Close()
if err != nil {
log.Fatal(err)
}
// Unordered output:
// cote
// côte
// cotée
}

View File

@@ -29,7 +29,7 @@ func (s *handleState) Close() (err error) {
func GetHandle(ctx context.Context, id uint32) any {
if id == 0 {
panic(NilErr)
return nil
}
s := ctx.Value(handleKey{}).(*handleState)
return s.handles[^id]

View File

@@ -158,12 +158,14 @@ func newSQLite(mod api.Module) (sqlt *sqlite, err error) {
changes: getFun("sqlite3_changes64"),
lastRowid: getFun("sqlite3_last_insert_rowid"),
autocommit: getFun("sqlite3_get_autocommit"),
createCollation: getFun("sqlite3_create_go_collation"),
createFunction: getFun("sqlite3_create_go_function"),
createAggregate: getFun("sqlite3_create_go_aggregate_function"),
createWindow: getFun("sqlite3_create_go_window_function"),
createCollation: getFun("sqlite3_create_collation_go"),
createFunction: getFun("sqlite3_create_function_go"),
createAggregate: getFun("sqlite3_create_aggregate_function_go"),
createWindow: getFun("sqlite3_create_window_function_go"),
aggregateCtx: getFun("sqlite3_aggregate_context"),
userData: getFun("sqlite3_user_data"),
setAuxData: getFun("sqlite3_set_auxdata_go"),
getAuxData: getFun("sqlite3_get_auxdata"),
valueType: getFun("sqlite3_value_type"),
valueInteger: getFun("sqlite3_value_int64"),
valueFloat: getFun("sqlite3_value_double"),
@@ -381,6 +383,8 @@ type sqliteAPI struct {
createWindow api.Function
aggregateCtx api.Function
userData api.Function
setAuxData api.Function
getAuxData api.Function
valueType api.Function
valueInteger api.Function
valueFloat api.Function

View File

@@ -10,27 +10,31 @@ void go_value(sqlite3_context *);
void go_inverse(sqlite3_context *, int, sqlite3_value **);
void go_destroy(void *);
int sqlite3_create_go_collation(sqlite3 *db, const char *zName, void *pApp) {
int sqlite3_create_collation_go(sqlite3 *db, const char *zName, void *pApp) {
return sqlite3_create_collation_v2(db, zName, SQLITE_UTF8, pApp, go_compare,
go_destroy);
}
int sqlite3_create_go_function(sqlite3 *db, const char *zName, int nArg,
int sqlite3_create_function_go(sqlite3 *db, const char *zName, int nArg,
int flags, void *pApp) {
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8 | flags, pApp,
go_func, NULL, NULL, go_destroy);
}
int sqlite3_create_go_aggregate_function(sqlite3 *db, const char *zName,
int sqlite3_create_aggregate_function_go(sqlite3 *db, const char *zName,
int nArg, int flags, void *pApp) {
return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags,
pApp, go_step, go_final, NULL, NULL,
go_destroy);
}
int sqlite3_create_go_window_function(sqlite3 *db, const char *zName, int nArg,
int sqlite3_create_window_function_go(sqlite3 *db, const char *zName, int nArg,
int flags, void *pApp) {
return sqlite3_create_window_function(db, zName, nArg, SQLITE_UTF8 | flags,
pApp, go_step, go_final, go_value,
go_inverse, go_destroy);
}
void sqlite3_set_auxdata_go(sqlite3_context *ctx, int iArg, void *pAux) {
sqlite3_set_auxdata(ctx, iArg, pAux, go_destroy);
}