mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
Error logging.
This commit is contained in:
32
config.go
32
config.go
@@ -1,9 +1,14 @@
|
||||
package sqlite3
|
||||
|
||||
import "github.com/ncruces/go-sqlite3/internal/util"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/internal/util"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
)
|
||||
|
||||
// Config makes configuration changes to a database connection.
|
||||
// Only bool configuratiton options are supported.
|
||||
// Only boolean configuration options are supported.
|
||||
// Called with no arg reads the current configuration value,
|
||||
// called with one arg sets and returns the new value.
|
||||
//
|
||||
@@ -27,3 +32,26 @@ func (c *Conn) Config(op DBConfig, arg ...bool) (bool, error) {
|
||||
uint64(op), uint64(argsPtr))
|
||||
return util.ReadUint32(c.mod, argsPtr) != 0, c.error(r)
|
||||
}
|
||||
|
||||
// ConfigLog sets up the error logging callback for the connection.
|
||||
//
|
||||
// https://www.sqlite.org/errlog.html
|
||||
func (c *Conn) ConfigLog(cb func(code ExtendedErrorCode, msg string)) error {
|
||||
var enable uint64
|
||||
if cb != nil {
|
||||
enable = 1
|
||||
}
|
||||
r := c.call("sqlite3_config_log_go", enable)
|
||||
if err := c.error(r); err != nil {
|
||||
return err
|
||||
}
|
||||
c.log = cb
|
||||
return nil
|
||||
}
|
||||
|
||||
func logCallback(ctx context.Context, mod api.Module, _, iCode, zMsg uint32) {
|
||||
if c, ok := ctx.Value(connKey{}).(*Conn); ok && c.log != nil {
|
||||
msg := util.ReadString(mod, zMsg, _MAX_LENGTH)
|
||||
c.log(xErrorCode(iCode), msg)
|
||||
}
|
||||
}
|
||||
|
||||
13
conn.go
13
conn.go
@@ -20,6 +20,7 @@ type Conn struct {
|
||||
|
||||
interrupt context.Context
|
||||
pending *Stmt
|
||||
log func(code xErrorCode, msg string)
|
||||
arena arena
|
||||
|
||||
handle uint32
|
||||
@@ -258,6 +259,12 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
|
||||
return old
|
||||
}
|
||||
|
||||
func (c *Conn) checkInterrupt() {
|
||||
if c.interrupt != nil && c.interrupt.Err() != nil {
|
||||
c.call("sqlite3_interrupt", uint64(c.handle))
|
||||
}
|
||||
}
|
||||
|
||||
func progressCallback(ctx context.Context, mod api.Module, _ uint32) uint32 {
|
||||
if c, ok := ctx.Value(connKey{}).(*Conn); ok {
|
||||
if c.interrupt != nil && c.interrupt.Err() != nil {
|
||||
@@ -267,12 +274,6 @@ func progressCallback(ctx context.Context, mod api.Module, _ uint32) uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Conn) checkInterrupt() {
|
||||
if c.interrupt != nil && c.interrupt.Err() != nil {
|
||||
c.call("sqlite3_interrupt", uint64(c.handle))
|
||||
}
|
||||
}
|
||||
|
||||
// Pragma executes a PRAGMA statement and returns any results.
|
||||
//
|
||||
// https://sqlite.org/pragma.html
|
||||
|
||||
@@ -39,6 +39,7 @@ sqlite3_column_name
|
||||
sqlite3_column_text
|
||||
sqlite3_column_type
|
||||
sqlite3_column_value
|
||||
sqlite3_config_log_go
|
||||
sqlite3_create_aggregate_function_go
|
||||
sqlite3_create_collation_go
|
||||
sqlite3_create_function_go
|
||||
|
||||
Binary file not shown.
@@ -53,18 +53,18 @@ func (d fsdir) Open() (sqlite3.VTabCursor, error) {
|
||||
|
||||
type cursor struct {
|
||||
fsys fs.FS
|
||||
base string
|
||||
rowID int64
|
||||
eof bool
|
||||
curr entry
|
||||
next chan entry
|
||||
done chan struct{}
|
||||
base string
|
||||
rowID int64
|
||||
eof bool
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
path string
|
||||
fs.DirEntry
|
||||
err error
|
||||
path string
|
||||
}
|
||||
|
||||
func (c *cursor) Close() error {
|
||||
@@ -180,7 +180,7 @@ func (c *cursor) WalkDirFunc(path string, d fs.DirEntry, err error) error {
|
||||
select {
|
||||
case <-c.done:
|
||||
return fs.SkipAll
|
||||
case c.next <- entry{path, d, err}:
|
||||
case c.next <- entry{d, err, path}:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +282,7 @@ func (a *arena) string(s string) uint32 {
|
||||
|
||||
func exportCallbacks(env wazero.HostModuleBuilder) wazero.HostModuleBuilder {
|
||||
util.ExportFuncII(env, "go_progress", progressCallback)
|
||||
util.ExportFuncVIII(env, "go_log", logCallback)
|
||||
util.ExportFuncVI(env, "go_destroy", destroyCallback)
|
||||
util.ExportFuncVIII(env, "go_func", funcCallback)
|
||||
util.ExportFuncVIII(env, "go_step", stepCallback)
|
||||
|
||||
9
sqlite3/log.c
Normal file
9
sqlite3/log.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
void go_log(void*, int, const char*);
|
||||
|
||||
int sqlite3_config_log_go(bool enable) {
|
||||
return sqlite3_config(SQLITE_CONFIG_LOG, enable ? go_log : NULL, NULL);
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ext/uuid.c"
|
||||
// Bindings
|
||||
#include "func.c"
|
||||
#include "log.c"
|
||||
#include "pointer.c"
|
||||
#include "progress.c"
|
||||
#include "time.c"
|
||||
|
||||
@@ -339,3 +339,28 @@ func TestConn_Config(t *testing.T) {
|
||||
t.Error("want false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConn_ConfigLog(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
db, err := sqlite3.Open(":memory:")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var code sqlite3.ExtendedErrorCode
|
||||
err = db.ConfigLog(func(c sqlite3.ExtendedErrorCode, msg string) {
|
||||
t.Log(msg)
|
||||
code = c
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
db.Prepare(`SELECT * FRM sqlite_schema`)
|
||||
|
||||
if code != sqlite3.ExtendedErrorCode(sqlite3.ERROR) {
|
||||
t.Error("want sqlite3.ERROR")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user