diff options
author | rittneje <rittneje@gmail.com> | 2019-12-17 01:58:28 -0500 |
---|---|---|
committer | mattn <mattn.jp@gmail.com> | 2019-12-17 15:58:28 +0900 |
commit | b4f5cc77d1cca1470922e916c9f775ef17d2d78f (patch) | |
tree | f4c84d072f9b184a486c9d78edbe5e0cab21e2a2 /sqlite3.go | |
parent | Merge pull request #744 from azavorotnii/ctx_cancel (diff) | |
download | golite-b4f5cc77d1cca1470922e916c9f775ef17d2d78f.tar.gz golite-b4f5cc77d1cca1470922e916c9f775ef17d2d78f.tar.xz |
add SystemErrno to Error (#740)
* adding SystemErrno to Error, and fixing error logic when open fails
* fix for old versions of libsqlite3 that do not have sqlite3_system_errno defined
* fixing pre-processor logic
Diffstat (limited to 'sqlite3.go')
-rw-r--r-- | sqlite3.go | 35 |
1 files changed, 27 insertions, 8 deletions
@@ -183,6 +183,12 @@ static int _sqlite3_limit(sqlite3* db, int limitId, int newLimit) { return sqlite3_limit(db, limitId, newLimit); #endif } + +#if SQLITE_VERSION_NUMBER < 3012000 +static int sqlite3_system_errno(sqlite3 *db) { + return 0; +} +#endif */ import "C" import ( @@ -198,6 +204,7 @@ import ( "strconv" "strings" "sync" + "syscall" "time" "unsafe" ) @@ -749,15 +756,28 @@ func (c *SQLiteConn) lastError() error { return lastError(c.db) } +// Note: may be called with db == nil func lastError(db *C.sqlite3) error { - rv := C.sqlite3_errcode(db) + rv := C.sqlite3_errcode(db) // returns SQLITE_NOMEM if db == nil if rv == C.SQLITE_OK { return nil } + extrv := C.sqlite3_extended_errcode(db) // returns SQLITE_NOMEM if db == nil + errStr := C.GoString(C.sqlite3_errmsg(db)) // returns "out of memory" if db == nil + + // https://www.sqlite.org/c3ref/system_errno.html + // sqlite3_system_errno is only meaningful if the error code was SQLITE_CANTOPEN, + // or it was SQLITE_IOERR and the extended code was not SQLITE_IOERR_NOMEM + var systemErrno syscall.Errno + if rv == C.SQLITE_CANTOPEN || (rv == C.SQLITE_IOERR && extrv != C.SQLITE_IOERR_NOMEM) { + systemErrno = syscall.Errno(C.sqlite3_system_errno(db)) + } + return Error{ Code: ErrNo(rv), - ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(db)), - err: C.GoString(C.sqlite3_errmsg(db)), + ExtendedCode: ErrNoExtended(extrv), + SystemErrno: systemErrno, + err: errStr, } } @@ -869,10 +889,6 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) { return &SQLiteTx{c}, nil } -func errorString(err Error) string { - return C.GoString(C.sqlite3_errstr(C.int(err.Code))) -} - // Open database and return a new connection. // // A pragma can take either zero or one argument. @@ -1342,10 +1358,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE, nil) if rv != 0 { + // Save off the error _before_ closing the database. + // This is safe even if db is nil. + err := lastError(db) if db != nil { C.sqlite3_close_v2(db) } - return nil, Error{Code: ErrNo(rv)} + return nil, err } if db == nil { return nil, errors.New("sqlite succeeded without returning a database") |