File tree Expand file tree Collapse file tree 3 files changed +113
-1
lines changed Expand file tree Collapse file tree 3 files changed +113
-1
lines changed Original file line number Diff line number Diff line change 1+ package cgosqlite
2+
3+ // #include <sqlite3.h>
4+ //
5+ // void logCallbackGo(void* userData, int errCode, char* msgC);
6+ //
7+ // static void log_callback_into_go(void *userData, int errCode, const char *msg) {
8+ // logCallbackGo(userData, errCode, (char*)msg);
9+ // }
10+ //
11+ // static int ts_sqlite3_config_log(void) {
12+ // // TODO(raggi): if the library gains new uses of sqlite3_config they need to
13+ // // share a mutex.
14+ // return sqlite3_config(SQLITE_CONFIG_LOG, log_callback_into_go, NULL);
15+ // }
16+ import "C"
17+ import (
18+ "sync"
19+ "unsafe"
20+
21+ "github.com/tailscale/sqlite/sqliteh"
22+ )
23+
24+ // LogCallback receives SQLite log messages.
25+ type LogCallback func (code sqliteh.Code , msg string )
26+
27+ var (
28+ logCallbackMu sync.Mutex
29+ logCallback LogCallback
30+ )
31+
32+ //export logCallbackGo
33+ func logCallbackGo (userData unsafe.Pointer , errCode C.int , msgC * C.char ) {
34+ logCallbackMu .Lock ()
35+ cb := logCallback
36+ logCallbackMu .Unlock ()
37+
38+ if cb == nil {
39+ return
40+ }
41+
42+ msg := C .GoString (msgC )
43+ cb (sqliteh .Code (errCode ), msg )
44+ }
45+
46+ // SetLogCallback sets the global SQLite log callback.
47+ // If callback is nil, logs are discarded.
48+ func SetLogCallback (callback LogCallback ) error {
49+ logCallbackMu .Lock ()
50+ logCallback = callback
51+ logCallbackMu .Unlock ()
52+
53+ res := C .ts_sqlite3_config_log ()
54+ return errCode (res )
55+ }
Original file line number Diff line number Diff line change 33
44package sqlite
55
6- import "github.com/tailscale/sqlite/cgosqlite"
6+ import (
7+ "github.com/tailscale/sqlite/cgosqlite"
8+ "github.com/tailscale/sqlite/sqliteh"
9+ )
710
811func init () {
912 Open = cgosqlite .Open
1013}
14+
15+ // LogCallback receives SQLite log messages.
16+ type LogCallback func (code sqliteh.Code , msg string )
17+
18+ // SetLogCallback sets the global SQLite log callback.
19+ // If callback is nil, logs are discarded.
20+ func SetLogCallback (callback LogCallback ) error {
21+ return cgosqlite .SetLogCallback (cgosqlite .LogCallback (callback ))
22+ }
Original file line number Diff line number Diff line change 1+ //go:build cgo
2+ // +build cgo
3+
4+ package sqlite
5+
6+ import (
7+ "sync"
8+ "testing"
9+
10+ "github.com/tailscale/sqlite/cgosqlite"
11+ "github.com/tailscale/sqlite/sqliteh"
12+ )
13+
14+ // ensure LogCallback is convertible to cgosqlite.LogCallback
15+ var _ cgosqlite.LogCallback = cgosqlite .LogCallback (LogCallback (func (code sqliteh.Code , msg string ) {}))
16+
17+ func TestSetLogCallback (t * testing.T ) {
18+ var mu sync.Mutex
19+ var logs []string
20+
21+ err := SetLogCallback (func (code sqliteh.Code , msg string ) {
22+ mu .Lock ()
23+ defer mu .Unlock ()
24+ logs = append (logs , msg )
25+ })
26+ if err != nil {
27+ t .Fatal (err )
28+ }
29+ defer SetLogCallback (nil )
30+
31+ db := openTestDB (t )
32+
33+ _ , err = db .Exec ("SELECT * FROM nonexistent_table" )
34+ if err == nil {
35+ t .Fatal ("expected error from invalid SQL" )
36+ }
37+
38+ mu .Lock ()
39+ gotLogs := len (logs ) > 0
40+ mu .Unlock ()
41+
42+ if ! gotLogs {
43+ t .Fatal ("expected to receive log messages" )
44+ }
45+ }
You can’t perform that action at this time.
0 commit comments