@@ -183,6 +183,12 @@ static int _sqlite3_limit(sqlite3* db, int limitId, int newLimit) {
183183 return sqlite3_limit(db, limitId, newLimit);
184184#endif
185185}
186+
187+ #if SQLITE_VERSION_NUMBER < 3012000
188+ static int sqlite3_system_errno(sqlite3 *db) {
189+ return 0;
190+ }
191+ #endif
186192*/
187193import "C"
188194import (
@@ -198,6 +204,7 @@ import (
198204 "strconv"
199205 "strings"
200206 "sync"
207+ "syscall"
201208 "time"
202209 "unsafe"
203210)
@@ -749,15 +756,28 @@ func (c *SQLiteConn) lastError() error {
749756 return lastError (c .db )
750757}
751758
759+ // Note: may be called with db == nil
752760func lastError (db * C.sqlite3 ) error {
753- rv := C .sqlite3_errcode (db )
761+ rv := C .sqlite3_errcode (db ) // returns SQLITE_NOMEM if db == nil
754762 if rv == C .SQLITE_OK {
755763 return nil
756764 }
765+ extrv := C .sqlite3_extended_errcode (db ) // returns SQLITE_NOMEM if db == nil
766+ errStr := C .GoString (C .sqlite3_errmsg (db )) // returns "out of memory" if db == nil
767+
768+ // https://www.sqlite.org/c3ref/system_errno.html
769+ // sqlite3_system_errno is only meaningful if the error code was SQLITE_CANTOPEN,
770+ // or it was SQLITE_IOERR and the extended code was not SQLITE_IOERR_NOMEM
771+ var systemErrno syscall.Errno
772+ if rv == C .SQLITE_CANTOPEN || (rv == C .SQLITE_IOERR && extrv != C .SQLITE_IOERR_NOMEM ) {
773+ systemErrno = syscall .Errno (C .sqlite3_system_errno (db ))
774+ }
775+
757776 return Error {
758777 Code : ErrNo (rv ),
759- ExtendedCode : ErrNoExtended (C .sqlite3_extended_errcode (db )),
760- err : C .GoString (C .sqlite3_errmsg (db )),
778+ ExtendedCode : ErrNoExtended (extrv ),
779+ SystemErrno : systemErrno ,
780+ err : errStr ,
761781 }
762782}
763783
@@ -869,10 +889,6 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
869889 return & SQLiteTx {c }, nil
870890}
871891
872- func errorString (err Error ) string {
873- return C .GoString (C .sqlite3_errstr (C .int (err .Code )))
874- }
875-
876892// Open database and return a new connection.
877893//
878894// A pragma can take either zero or one argument.
@@ -1342,10 +1358,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
13421358 mutex | C .SQLITE_OPEN_READWRITE | C .SQLITE_OPEN_CREATE ,
13431359 nil )
13441360 if rv != 0 {
1361+ // Save off the error _before_ closing the database.
1362+ // This is safe even if db is nil.
1363+ err := lastError (db )
13451364 if db != nil {
13461365 C .sqlite3_close_v2 (db )
13471366 }
1348- return nil , Error { Code : ErrNo ( rv )}
1367+ return nil , err
13491368 }
13501369 if db == nil {
13511370 return nil , errors .New ("sqlite succeeded without returning a database" )
0 commit comments