Commit 0d47edb6 authored by Kirill Smelkov's avatar Kirill Smelkov

open: Fix error message

By accident I was trying to open a non-existing database file and got
the following message:

	unable to open database file (unable to open database file)

which was not helpful.

By convention the error returned by a function should contain the
context passed to that function - the filename in Open case, the
operation performed and the error description. So

- teach OpenError to print filename of the opened database and the
  operation.
- don't duplicate the code in braces if we have the error message
  with the same text because they are often redundant.
- if we have only error code but not a message, still we have to include
  the filename and operation in the printed context.
- in the Open itself: always return OpenError on handling errors from
  sqlite3_open_v2 even if db == nil - instead of returning only Errno
  without any context.

Now the error in my case is:

	notfound.db: unable to open database file

( @gwenn requested to omit the ": open" (operation) probable because it
  duplicates error detail a bit )

/helped-by @gwenn
parent 3415a54c
...@@ -40,10 +40,23 @@ type OpenError struct { ...@@ -40,10 +40,23 @@ type OpenError struct {
} }
func (e OpenError) Error() string { func (e OpenError) Error() string {
file := e.Filename
if file == "" {
file = "(temporary)"
}
s := fmt.Sprintf("%s: ", file)
codeErr := e.Code.Error()
if len(e.Msg) > 0 { if len(e.Msg) > 0 {
return fmt.Sprintf("%s (%s)", e.Msg, e.Code.Error()) s += e.Msg
// error code and msg are often redundant but not always
// (see sqlite3ErrorWithMsg usages in SQLite3 sources)
if codeErr != e.Msg {
s += fmt.Sprintf(" (%s)", codeErr)
}
} else {
s += codeErr
} }
return e.Code.Error() return s
} }
// ConnError is a wrapper for all SQLite connection related error. // ConnError is a wrapper for all SQLite connection related error.
...@@ -250,16 +263,17 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error) ...@@ -250,16 +263,17 @@ func OpenVfs(filename string, vfsname string, flags ...OpenFlag) (*Conn, error)
} }
rv := C.sqlite3_open_v2(cname, &db, C.int(openFlags), vfs) rv := C.sqlite3_open_v2(cname, &db, C.int(openFlags), vfs)
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
if db != nil { // try to extract futher details from db... err := OpenError{
err := OpenError{Code: Errno(rv), Code: Errno(rv),
ExtendedCode: int(C.sqlite3_extended_errcode(db)),
Msg: C.GoString(C.sqlite3_errmsg(db)),
Filename: filename, Filename: filename,
} }
if db != nil { // try to extract futher details from db...
err.ExtendedCode = int(C.sqlite3_extended_errcode(db))
err.Msg = C.GoString(C.sqlite3_errmsg(db))
C.sqlite3_close(db) C.sqlite3_close(db)
return nil, err return nil, err
} }
return nil, Errno(rv) return nil, err
} }
if db == nil { if db == nil {
return nil, errors.New("sqlite succeeded without returning a database") return nil, errors.New("sqlite succeeded without returning a database")
......
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