Commit c1df3127 authored by gwenn's avatar gwenn

Adds contextual details to errors when possible.

parent bedc25eb
...@@ -12,6 +12,7 @@ import "C" ...@@ -12,6 +12,7 @@ import "C"
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"unsafe" "unsafe"
) )
...@@ -68,7 +69,7 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq ...@@ -68,7 +69,7 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq
if bl != nil { if bl != nil {
C.sqlite3_blob_close(bl) C.sqlite3_blob_close(bl)
} }
return nil, c.error(rv) return nil, c.error(rv, fmt.Sprintf("Conn.blob_open(db: %q, tbl: %q, col: %q, row: %d)", db, table, column, row))
} }
if bl == nil { if bl == nil {
return nil, errors.New("sqlite succeeded without returning a blob") return nil, errors.New("sqlite succeeded without returning a blob")
...@@ -80,11 +81,11 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq ...@@ -80,11 +81,11 @@ func (c *Conn) blob_open(db, table, column string, row int64, write bool) (*C.sq
// (See http://sqlite.org/c3ref/blob_close.html) // (See http://sqlite.org/c3ref/blob_close.html)
func (r *BlobReader) Close() error { func (r *BlobReader) Close() error {
if r == nil { if r == nil {
return errors.New("nil sqlite blob reader") return errors.New("nil sqlite blob")
} }
rv := C.sqlite3_blob_close(r.bl) rv := C.sqlite3_blob_close(r.bl)
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return r.c.error(rv) return r.c.error(rv, "BlobReader.Close")
} }
r.bl = nil r.bl = nil
return nil return nil
...@@ -110,7 +111,7 @@ func (r *BlobReader) Read(v []byte) (int, error) { ...@@ -110,7 +111,7 @@ func (r *BlobReader) Read(v []byte) (int, error) {
n := len(v) n := len(v)
rv := C.sqlite3_blob_read(r.bl, unsafe.Pointer(p), C.int(n), C.int(r.ReadOffset)) rv := C.sqlite3_blob_read(r.bl, unsafe.Pointer(p), C.int(n), C.int(r.ReadOffset))
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return 0, r.c.error(rv) return 0, r.c.error(rv, "BlobReader.Read")
} }
r.ReadOffset += n r.ReadOffset += n
return n, nil return n, nil
...@@ -150,7 +151,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) { ...@@ -150,7 +151,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
n := len(v) n := len(v)
rv := C.sqlite3_blob_write(w.bl, unsafe.Pointer(p), C.int(n), C.int(w.WriteOffset)) rv := C.sqlite3_blob_write(w.bl, unsafe.Pointer(p), C.int(n), C.int(w.WriteOffset))
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return 0, w.c.error(rv) return 0, w.c.error(rv, "BlobReadWiter.Write")
} }
w.WriteOffset += n w.WriteOffset += n
return n, err return n, err
...@@ -161,7 +162,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) { ...@@ -161,7 +162,7 @@ func (w *BlobReadWriter) Write(v []byte) (int, error) {
func (r *BlobReader) Reopen(rowid int64) error { func (r *BlobReader) Reopen(rowid int64) error {
rv := C.sqlite3_blob_reopen(r.bl, C.sqlite3_int64(rowid)) rv := C.sqlite3_blob_reopen(r.bl, C.sqlite3_int64(rowid))
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return r.c.error(rv) return r.c.error(rv, fmt.Sprintf("BlobReader.Reopen(%d)", rowid))
} }
r.size = -1 r.size = -1
r.ReadOffset = 0 r.ReadOffset = 0
......
...@@ -421,7 +421,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac ...@@ -421,7 +421,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac
if len(c.udfs) > 0 { if len(c.udfs) > 0 {
delete(c.udfs, functionName) delete(c.udfs, functionName)
} }
return c.error(C.sqlite3_create_function_v2(c.db, fname, C.int(nArg), C.SQLITE_UTF8, nil, nil, nil, nil, nil)) return c.error(C.sqlite3_create_function_v2(c.db, fname, C.int(nArg), C.SQLITE_UTF8, nil, nil, nil, nil, nil),
fmt.Sprintf("<Conn.CreateScalarFunction(%q)", functionName))
} }
// To make sure it is not gced, keep a reference in the connection. // To make sure it is not gced, keep a reference in the connection.
udf := &sqliteFunction{f, nil, nil, d, pApp, make(map[*ScalarContext]bool), nil} udf := &sqliteFunction{f, nil, nil, d, pApp, make(map[*ScalarContext]bool), nil}
...@@ -429,7 +430,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac ...@@ -429,7 +430,8 @@ func (c *Conn) CreateScalarFunction(functionName string, nArg int, pApp interfac
c.udfs = make(map[string]*sqliteFunction) c.udfs = make(map[string]*sqliteFunction)
} }
c.udfs[functionName] = udf // FIXME same function name with different args is not supported c.udfs[functionName] = udf // FIXME same function name with different args is not supported
return c.error(C.goSqlite3CreateScalarFunction(c.db, fname, C.int(nArg), C.SQLITE_UTF8, unsafe.Pointer(udf))) return c.error(C.goSqlite3CreateScalarFunction(c.db, fname, C.int(nArg), C.SQLITE_UTF8, unsafe.Pointer(udf)),
fmt.Sprintf("Conn.CreateScalarFunction(%q)", functionName))
} }
// CreateAggregateFunction creates or redefines SQL aggregate functions. // CreateAggregateFunction creates or redefines SQL aggregate functions.
...@@ -443,7 +445,8 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter ...@@ -443,7 +445,8 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter
if len(c.udfs) > 0 { if len(c.udfs) > 0 {
delete(c.udfs, functionName) delete(c.udfs, functionName)
} }
return c.error(C.sqlite3_create_function_v2(c.db, fname, C.int(nArg), C.SQLITE_UTF8, nil, nil, nil, nil, nil)) return c.error(C.sqlite3_create_function_v2(c.db, fname, C.int(nArg), C.SQLITE_UTF8, nil, nil, nil, nil, nil),
fmt.Sprintf("<Conn.CreateAggregateFunction(%q)", functionName))
} }
// To make sure it is not gced, keep a reference in the connection. // To make sure it is not gced, keep a reference in the connection.
udf := &sqliteFunction{nil, step, final, d, pApp, nil, make(map[*AggregateContext]bool)} udf := &sqliteFunction{nil, step, final, d, pApp, nil, make(map[*AggregateContext]bool)}
...@@ -451,5 +454,6 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter ...@@ -451,5 +454,6 @@ func (c *Conn) CreateAggregateFunction(functionName string, nArg int, pApp inter
c.udfs = make(map[string]*sqliteFunction) c.udfs = make(map[string]*sqliteFunction)
} }
c.udfs[functionName] = udf // FIXME same function name with different args is not supported c.udfs[functionName] = udf // FIXME same function name with different args is not supported
return c.error(C.goSqlite3CreateAggregateFunction(c.db, fname, C.int(nArg), C.SQLITE_UTF8, unsafe.Pointer(udf))) return c.error(C.goSqlite3CreateAggregateFunction(c.db, fname, C.int(nArg), C.SQLITE_UTF8, unsafe.Pointer(udf)),
fmt.Sprintf("Conn.CreateAggregateFunction(%q)", functionName))
} }
...@@ -35,7 +35,10 @@ static int my_table_column_metadata( ...@@ -35,7 +35,10 @@ static int my_table_column_metadata(
*/ */
import "C" import "C"
import "unsafe" import (
"fmt"
"unsafe"
)
// Databases returns one couple (name, file) for each database attached to the current database connection. // Databases returns one couple (name, file) for each database attached to the current database connection.
// (See http://www.sqlite.org/pragma.html#pragma_database_list) // (See http://www.sqlite.org/pragma.html#pragma_database_list)
...@@ -146,7 +149,7 @@ func (c *Conn) Column(dbName, tableName, columnName string) (*Column, error) { ...@@ -146,7 +149,7 @@ func (c *Conn) Column(dbName, tableName, columnName string) (*Column, error) {
rv := C.my_table_column_metadata(c.db, zDbName, zTableName, zColumnName, &zDataType, &zCollSeq, rv := C.my_table_column_metadata(c.db, zDbName, zTableName, zColumnName, &zDataType, &zCollSeq,
&notNull, &primaryKey, &autoinc) &notNull, &primaryKey, &autoinc)
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return nil, c.error(rv) return nil, c.error(rv, fmt.Sprintf("Conn.Column(db: %q, tbl: %q, col: %q)", dbName, tableName, columnName))
} }
return &Column{-1, columnName, C.GoString(zDataType), notNull == 1, "", primaryKey == 1, return &Column{-1, columnName, C.GoString(zDataType), notNull == 1, "", primaryKey == 1,
autoinc == 1, C.GoString(zCollSeq)}, nil autoinc == 1, C.GoString(zCollSeq)}, nil
......
...@@ -32,7 +32,7 @@ func (c *Conn) IntegrityCheck(dbName string, max int, quick bool) error { ...@@ -32,7 +32,7 @@ func (c *Conn) IntegrityCheck(dbName string, max int, quick bool) error {
return err return err
} }
if msg != "ok" { if msg != "ok" {
return c.specificError("Integrity check failed (%s)", msg) return c.specificError("Integrity check failed on %q (%s)", dbName, msg)
} }
return nil return nil
} }
...@@ -155,5 +155,5 @@ func (c *Conn) oneValue(query string, value interface{}) error { // no cache ...@@ -155,5 +155,5 @@ func (c *Conn) oneValue(query string, value interface{}) error { // no cache
} else if err == Done { } else if err == Done {
return io.EOF return io.EOF
} }
return s.error(rv) return s.error(rv, fmt.Sprintf("Conn.oneValue(%q)", query))
} }
...@@ -243,7 +243,7 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error) ...@@ -243,7 +243,7 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error)
// BusyTimeout sets a busy timeout. // BusyTimeout sets a busy timeout.
// (See http://sqlite.org/c3ref/busy_timeout.html) // (See http://sqlite.org/c3ref/busy_timeout.html)
func (c *Conn) BusyTimeout(ms int) error { // TODO time.Duration ? func (c *Conn) BusyTimeout(ms int) error { // TODO time.Duration ?
return c.error(C.sqlite3_busy_timeout(c.db, C.int(ms))) return c.error(C.sqlite3_busy_timeout(c.db, C.int(ms)), "Conn.BusyTimeout")
} }
// EnableFKey enables or disables the enforcement of foreign key constraints. // EnableFKey enables or disables the enforcement of foreign key constraints.
...@@ -292,7 +292,7 @@ func (c *Conn) queryOrSetEnableDbConfig(key, i C.int) (bool, error) { ...@@ -292,7 +292,7 @@ func (c *Conn) queryOrSetEnableDbConfig(key, i C.int) (bool, error) {
// EnableExtendedResultCodes enables or disables the extended result codes feature of SQLite. // EnableExtendedResultCodes enables or disables the extended result codes feature of SQLite.
// (See http://sqlite.org/c3ref/extended_result_codes.html) // (See http://sqlite.org/c3ref/extended_result_codes.html)
func (c *Conn) EnableExtendedResultCodes(b bool) error { func (c *Conn) EnableExtendedResultCodes(b bool) error {
return c.error(C.sqlite3_extended_result_codes(c.db, btocint(b))) return c.error(C.sqlite3_extended_result_codes(c.db, btocint(b)), "Conn.EnableExtendedResultCodes")
} }
// Readonly determines if a database is read-only. // Readonly determines if a database is read-only.
...@@ -335,7 +335,7 @@ func (c *Conn) Exec(cmd string, args ...interface{}) error { ...@@ -335,7 +335,7 @@ func (c *Conn) Exec(cmd string, args ...interface{}) error {
if len(s.tail) > 0 { if len(s.tail) > 0 {
if len(args) > 0 { if len(args) > 0 {
s.finalize() s.finalize()
return c.specificError("Cannot execute multiple statements when args are specified") return c.specificError("cannot execute multiple statements when args are specified: %q", cmd)
} }
} }
cmd = s.tail cmd = s.tail
...@@ -478,7 +478,7 @@ func (c *Conn) exec(cmd string) error { ...@@ -478,7 +478,7 @@ func (c *Conn) exec(cmd string) error {
defer s.finalize() defer s.finalize()
rv := C.sqlite3_step(s.stmt) rv := C.sqlite3_step(s.stmt)
if Errno(rv) != Done { if Errno(rv) != Done {
return s.error(rv) return s.error(rv, "Conn.exec(%q)", cmd)
} }
return nil return nil
} }
...@@ -511,7 +511,7 @@ func (c *Conn) Close() error { ...@@ -511,7 +511,7 @@ func (c *Conn) Close() error {
c.db = nil c.db = nil
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
Log(int(rv), "error while closing Conn") Log(int(rv), "error while closing Conn")
return c.error(rv) return c.error(rv, "Conn.Close")
} }
return nil return nil
} }
......
...@@ -34,7 +34,6 @@ import "C" ...@@ -34,7 +34,6 @@ import "C"
import ( import (
"errors" "errors"
"fmt" "fmt"
"reflect"
"time" "time"
"unsafe" "unsafe"
) )
...@@ -150,7 +149,7 @@ func (s *Stmt) exec() error { ...@@ -150,7 +149,7 @@ func (s *Stmt) exec() error {
rv := C.sqlite3_step(s.stmt) rv := C.sqlite3_step(s.stmt)
C.sqlite3_reset(s.stmt) C.sqlite3_reset(s.stmt)
if Errno(rv) != Done { if Errno(rv) != Done {
return s.error(rv) return s.error(rv, "Stmt.exec")
} }
return nil return nil
} }
...@@ -228,6 +227,7 @@ func (s *Stmt) SelectOneRow(args ...interface{}) (bool, error) { ...@@ -228,6 +227,7 @@ func (s *Stmt) SelectOneRow(args ...interface{}) (bool, error) {
} }
// BindParameterCount returns the number of SQL parameters. // BindParameterCount returns the number of SQL parameters.
// FIXME If parameters of the ?NNN form are used, there may be gaps in the list.
// (See http://sqlite.org/c3ref/bind_parameter_count.html) // (See http://sqlite.org/c3ref/bind_parameter_count.html)
func (s *Stmt) BindParameterCount() int { func (s *Stmt) BindParameterCount() int {
if s.bindParameterCount == -1 { if s.bindParameterCount == -1 {
...@@ -252,7 +252,7 @@ func (s *Stmt) BindParameterIndex(name string) (int, error) { ...@@ -252,7 +252,7 @@ func (s *Stmt) BindParameterIndex(name string) (int, error) {
defer C.free(unsafe.Pointer(cname)) defer C.free(unsafe.Pointer(cname))
index = int(C.sqlite3_bind_parameter_index(s.stmt, cname)) index = int(C.sqlite3_bind_parameter_index(s.stmt, cname))
if index == 0 { if index == 0 {
return index, s.specificError("invalid parameter name: %s", name) return index, s.specificError("invalid parameter name: %q", name)
} }
s.params[name] = index s.params[name] = index
return index, nil return index, nil
...@@ -273,12 +273,12 @@ func (s *Stmt) BindParameterName(i int) (string, error) { ...@@ -273,12 +273,12 @@ func (s *Stmt) BindParameterName(i int) (string, error) {
// NamedBind binds parameters by their name (name1, value1, ...) // NamedBind binds parameters by their name (name1, value1, ...)
func (s *Stmt) NamedBind(args ...interface{}) error { func (s *Stmt) NamedBind(args ...interface{}) error {
if len(args)%2 != 0 { if len(args)%2 != 0 {
return s.specificError("Expected an even number of arguments") return s.specificError("expected an even number of arguments: %d", len(args))
} }
for i := 0; i < len(args); i += 2 { for i := 0; i < len(args); i += 2 {
name, ok := args[i].(string) name, ok := args[i].(string)
if !ok { if !ok {
return s.specificError("non-string param name") return s.specificError("non-string param name at %d: %T", i, args[i])
} }
index, err := s.BindParameterIndex(name) // How to look up only once for one statement ? index, err := s.BindParameterIndex(name) // How to look up only once for one statement ?
if err != nil { if err != nil {
...@@ -346,9 +346,9 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error { ...@@ -346,9 +346,9 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error {
case ZeroBlobLength: case ZeroBlobLength:
rv = C.sqlite3_bind_zeroblob(s.stmt, i, C.int(value)) rv = C.sqlite3_bind_zeroblob(s.stmt, i, C.int(value))
default: default:
return s.specificError("unsupported type in Bind: %s", reflect.TypeOf(value)) return s.specificError("unsupported type in Bind: %T", value)
} }
return s.error(rv) return s.error(rv, "Stmt.Bind")
} }
// Next evaluates an SQL statement // Next evaluates an SQL statement
...@@ -376,7 +376,7 @@ func (s *Stmt) Next() (bool, error) { ...@@ -376,7 +376,7 @@ func (s *Stmt) Next() (bool, error) {
} }
C.sqlite3_reset(s.stmt) C.sqlite3_reset(s.stmt)
if err != Done { if err != Done {
return false, s.error(rv) return false, s.error(rv, "Stmt.Next")
} }
// TODO Check column count > 0 // TODO Check column count > 0
return false, nil return false, nil
...@@ -386,13 +386,13 @@ func (s *Stmt) Next() (bool, error) { ...@@ -386,13 +386,13 @@ func (s *Stmt) Next() (bool, error) {
// and reset it back to its starting state so that it can be reused. // and reset it back to its starting state so that it can be reused.
// (See http://sqlite.org/c3ref/reset.html) // (See http://sqlite.org/c3ref/reset.html)
func (s *Stmt) Reset() error { func (s *Stmt) Reset() error {
return s.error(C.sqlite3_reset(s.stmt)) return s.error(C.sqlite3_reset(s.stmt), "Stmt.Reset")
} }
// ClearBindings resets all bindings on a prepared statement. // ClearBindings resets all bindings on a prepared statement.
// (See http://sqlite.org/c3ref/clear_bindings.html) // (See http://sqlite.org/c3ref/clear_bindings.html)
func (s *Stmt) ClearBindings() error { func (s *Stmt) ClearBindings() error {
return s.error(C.sqlite3_clear_bindings(s.stmt)) return s.error(C.sqlite3_clear_bindings(s.stmt), "Stmt.ClearBindings")
} }
// ColumnCount returns the number of columns in the result set for the statement (with or without row). // ColumnCount returns the number of columns in the result set for the statement (with or without row).
...@@ -470,12 +470,12 @@ func (s *Stmt) ColumnType(index int) Type { ...@@ -470,12 +470,12 @@ func (s *Stmt) ColumnType(index int) Type {
// (See http://sqlite.org/c3ref/column_blob.html) // (See http://sqlite.org/c3ref/column_blob.html)
func (s *Stmt) NamedScan(args ...interface{}) error { func (s *Stmt) NamedScan(args ...interface{}) error {
if len(args)%2 != 0 { if len(args)%2 != 0 {
return s.specificError("Expected an even number of arguments") return s.specificError("expected an even number of arguments: %d", len(args))
} }
for i := 0; i < len(args); i += 2 { for i := 0; i < len(args); i += 2 {
name, ok := args[i].(string) name, ok := args[i].(string)
if !ok { if !ok {
return s.specificError("non-string field name") return s.specificError("non-string field name at %d: %T", i, args[i])
} }
index, err := s.ColumnIndex(name) // How to look up only once for one statement ? index, err := s.ColumnIndex(name) // How to look up only once for one statement ?
if err != nil { if err != nil {
...@@ -660,7 +660,7 @@ func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) { ...@@ -660,7 +660,7 @@ func (s *Stmt) ScanByIndex(index int, value interface{}) (bool, error) {
case func(interface{}) (bool, error): case func(interface{}) (bool, error):
isNull, err = value(s.ScanValue(index)) isNull, err = value(s.ScanValue(index))
default: default:
return false, s.specificError("unsupported type in Scan: %s", reflect.TypeOf(value)) return false, s.specificError("unsupported type in Scan: %T", value)
} }
return isNull, err return isNull, err
} }
...@@ -885,14 +885,14 @@ func (s *Stmt) checkTypeMismatch(source, target Type) error { ...@@ -885,14 +885,14 @@ func (s *Stmt) checkTypeMismatch(source, target Type) error {
case Text: case Text:
fallthrough fallthrough
case Blob: case Blob:
return s.specificError("Type mismatch, source %s vs target %s", source, target) return s.specificError("type mismatch, source %s vs target %s", source, target)
} }
case Float: case Float:
switch source { switch source {
case Text: case Text:
fallthrough fallthrough
case Blob: case Blob:
return s.specificError("Type mismatch, source %s vs target %s", source, target) return s.specificError("type mismatch, source %s vs target %s", source, target)
} }
} }
return nil return nil
...@@ -923,7 +923,7 @@ func (s *Stmt) finalize() error { ...@@ -923,7 +923,7 @@ func (s *Stmt) finalize() error {
s.stmt = nil s.stmt = nil
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
Log(int(rv), "error while finalizing Stmt") Log(int(rv), "error while finalizing Stmt")
return s.error(rv) return s.error(rv, "Stmt.finalize")
} }
return nil return nil
} }
......
...@@ -226,11 +226,11 @@ func goXAuth(udp unsafe.Pointer, action int, arg1, arg2, dbName, triggerName *C. ...@@ -226,11 +226,11 @@ func goXAuth(udp unsafe.Pointer, action int, arg1, arg2, dbName, triggerName *C.
func (c *Conn) SetAuthorizer(f Authorizer, udp interface{}) error { func (c *Conn) SetAuthorizer(f Authorizer, udp interface{}) error {
if f == nil { if f == nil {
c.authorizer = nil c.authorizer = nil
return c.error(C.sqlite3_set_authorizer(c.db, nil, nil)) return c.error(C.sqlite3_set_authorizer(c.db, nil, nil), "<Conn.SetAuthorizer")
} }
// To make sure it is not gced, keep a reference in the connection. // To make sure it is not gced, keep a reference in the connection.
c.authorizer = &sqliteAuthorizer{f, udp} c.authorizer = &sqliteAuthorizer{f, udp}
return c.error(C.goSqlite3SetAuthorizer(c.db, unsafe.Pointer(c.authorizer))) return c.error(C.goSqlite3SetAuthorizer(c.db, unsafe.Pointer(c.authorizer)), "Conn.SetAuthorizer")
} }
// Returns true to try again. // Returns true to try again.
...@@ -254,11 +254,11 @@ func goXBusy(udp unsafe.Pointer, count int) C.int { ...@@ -254,11 +254,11 @@ func goXBusy(udp unsafe.Pointer, count int) C.int {
func (c *Conn) BusyHandler(f BusyHandler, udp interface{}) error { func (c *Conn) BusyHandler(f BusyHandler, udp interface{}) error {
if f == nil { if f == nil {
c.busyHandler = nil c.busyHandler = nil
return c.error(C.sqlite3_busy_handler(c.db, nil, nil)) return c.error(C.sqlite3_busy_handler(c.db, nil, nil), "<Conn.BusyHandler")
} }
// To make sure it is not gced, keep a reference in the connection. // To make sure it is not gced, keep a reference in the connection.
c.busyHandler = &sqliteBusyHandler{f, udp} c.busyHandler = &sqliteBusyHandler{f, udp}
return c.error(C.goSqlite3BusyHandler(c.db, unsafe.Pointer(c.busyHandler))) return c.error(C.goSqlite3BusyHandler(c.db, unsafe.Pointer(c.busyHandler)), "Conn.BusyHandler")
} }
// Returns true to interrupt. // Returns true to interrupt.
......
...@@ -13,6 +13,7 @@ int goSqlite3CreateModule(sqlite3 *db, const char *zName, void *pClientData); ...@@ -13,6 +13,7 @@ int goSqlite3CreateModule(sqlite3 *db, const char *zName, void *pClientData);
import "C" import "C"
import ( import (
"fmt"
"reflect" "reflect"
"unsafe" "unsafe"
) )
...@@ -223,7 +224,7 @@ type VTabCursor interface { ...@@ -223,7 +224,7 @@ type VTabCursor interface {
func (c *Conn) DeclareVTab(sql string) error { func (c *Conn) DeclareVTab(sql string) error {
zSQL := C.CString(sql) zSQL := C.CString(sql)
defer C.free(unsafe.Pointer(zSQL)) defer C.free(unsafe.Pointer(zSQL))
return c.error(C.sqlite3_declare_vtab(c.db, zSQL)) return c.error(C.sqlite3_declare_vtab(c.db, zSQL), fmt.Sprintf("Conn.DeclareVTab(%q)", sql))
} }
// CreateModule registers a virtual table implementation. // CreateModule registers a virtual table implementation.
...@@ -237,7 +238,8 @@ func (c *Conn) CreateModule(moduleName string, module Module) error { ...@@ -237,7 +238,8 @@ func (c *Conn) CreateModule(moduleName string, module Module) error {
c.modules = make(map[string]*sqliteModule) c.modules = make(map[string]*sqliteModule)
} }
c.modules[moduleName] = udm // FIXME What happens if different modules are registered with the same name? c.modules[moduleName] = udm // FIXME What happens if different modules are registered with the same name?
return c.error(C.goSqlite3CreateModule(c.db, mname, unsafe.Pointer(udm))) return c.error(C.goSqlite3CreateModule(c.db, mname, unsafe.Pointer(udm)),
fmt.Sprintf("Conn.CreateModule(%q)", moduleName))
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment