-
Notifications
You must be signed in to change notification settings - Fork 10
.,cgosqlite: add log handler callback #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package cgosqlite | ||
|
|
||
| // #include <sqlite3.h> | ||
| // | ||
| // void logCallbackGo(void* userData, int errCode, char* msgC); | ||
| // | ||
| // static void log_callback_into_go(void *userData, int errCode, const char *msg) { | ||
| // logCallbackGo(userData, errCode, (char*)msg); | ||
| // } | ||
| // | ||
| // static int ts_sqlite3_config_log(void) { | ||
| // // TODO(raggi): if the library gains new uses of sqlite3_config they need to | ||
| // // share a mutex. | ||
| // return sqlite3_config(SQLITE_CONFIG_LOG, log_callback_into_go, NULL); | ||
| // } | ||
| import "C" | ||
| import ( | ||
| "sync" | ||
| "unsafe" | ||
|
|
||
| "github.com/tailscale/sqlite/sqliteh" | ||
| ) | ||
|
|
||
| // LogCallback receives SQLite log messages. | ||
| type LogCallback func(code sqliteh.Code, msg string) | ||
|
|
||
| var ( | ||
| logCallbackMu sync.Mutex | ||
| logCallback LogCallback | ||
| ) | ||
|
|
||
| //export logCallbackGo | ||
| func logCallbackGo(userData unsafe.Pointer, errCode C.int, msgC *C.char) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're not using the userData? This is global and not per-DB?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I figured you'd do like 695e777 did for the WALHook
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's global yeah, it's a sqlite3_config option, thankfully one of the few that can be set after sqlite3_initialize. |
||
| logCallbackMu.Lock() | ||
| cb := logCallback | ||
| logCallbackMu.Unlock() | ||
|
|
||
| if cb == nil { | ||
| return | ||
| } | ||
|
|
||
| msg := C.GoString(msgC) | ||
| cb(sqliteh.Code(errCode), msg) | ||
| } | ||
|
|
||
| // SetLogCallback sets the global SQLite log callback. | ||
| // If callback is nil, logs are discarded. | ||
| func SetLogCallback(callback LogCallback) error { | ||
| logCallbackMu.Lock() | ||
| logCallback = callback | ||
| logCallbackMu.Unlock() | ||
|
|
||
| res := C.ts_sqlite3_config_log() | ||
| return errCode(res) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //go:build cgo | ||
| // +build cgo | ||
|
|
||
| package sqlite | ||
|
|
||
| import ( | ||
| "sync" | ||
| "testing" | ||
|
|
||
| "github.com/tailscale/sqlite/cgosqlite" | ||
| "github.com/tailscale/sqlite/sqliteh" | ||
| ) | ||
|
|
||
| // ensure LogCallback is convertible to cgosqlite.LogCallback | ||
| var _ cgosqlite.LogCallback = cgosqlite.LogCallback(LogCallback(func(code sqliteh.Code, msg string) {})) | ||
|
|
||
| func TestSetLogCallback(t *testing.T) { | ||
| var mu sync.Mutex | ||
| var logs []string | ||
|
|
||
| err := SetLogCallback(func(code sqliteh.Code, msg string) { | ||
| mu.Lock() | ||
| defer mu.Unlock() | ||
| logs = append(logs, msg) | ||
| }) | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } | ||
| defer SetLogCallback(nil) | ||
|
|
||
| db := openTestDB(t) | ||
|
|
||
| _, err = db.Exec("SELECT * FROM nonexistent_table") | ||
| if err == nil { | ||
| t.Fatal("expected error from invalid SQL") | ||
| } | ||
|
|
||
| mu.Lock() | ||
| gotLogs := len(logs) > 0 | ||
| mu.Unlock() | ||
|
|
||
| if !gotLogs { | ||
| t.Fatal("expected to receive log messages") | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isnt
/* .... */comment style more common for cgo C code so it doesn't look like commented out code?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, but this would be the first code in this package to follow that convention