aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--error.go41
-rw-r--r--error_test.go34
-rw-r--r--sqlite3.go26
3 files changed, 90 insertions, 11 deletions
diff --git a/error.go b/error.go
new file mode 100644
index 0000000..15c843e
--- /dev/null
+++ b/error.go
@@ -0,0 +1,41 @@
+package sqlite3
+
+import "C"
+
+type ErrNo int
+
+// result codes from http://www.sqlite.org/c3ref/c_abort.html
+var (
+ ErrError error = ErrNo(1) /* SQL error or missing database */
+ ErrInternal error = ErrNo(2) /* Internal logic error in SQLite */
+ ErrPerm error = ErrNo(3) /* Access permission denied */
+ ErrAbort error = ErrNo(4) /* Callback routine requested an abort */
+ ErrBusy error = ErrNo(5) /* The database file is locked */
+ ErrLocked error = ErrNo(6) /* A table in the database is locked */
+ ErrNomem error = ErrNo(7) /* A malloc() failed */
+ ErrReadonly error = ErrNo(8) /* Attempt to write a readonly database */
+ ErrInterrupt error = ErrNo(9) /* Operation terminated by sqlite3_interrupt() */
+ ErrIoErr error = ErrNo(10) /* Some kind of disk I/O error occurred */
+ ErrCorrupt error = ErrNo(11) /* The database disk image is malformed */
+ ErrNotFound error = ErrNo(12) /* Unknown opcode in sqlite3_file_control() */
+ ErrFull error = ErrNo(13) /* Insertion failed because database is full */
+ ErrCantOpen error = ErrNo(14) /* Unable to open the database file */
+ ErrProtocol error = ErrNo(15) /* Database lock protocol error */
+ ErrEmpty error = ErrNo(16) /* Database is empty */
+ ErrSchema error = ErrNo(17) /* The database schema changed */
+ ErrTooBig error = ErrNo(18) /* String or BLOB exceeds size limit */
+ ErrConstraint error = ErrNo(19) /* Abort due to constraint violation */
+ ErrMismatch error = ErrNo(20) /* Data type mismatch */
+ ErrMisuse error = ErrNo(21) /* Library used incorrectly */
+ ErrNoLFS error = ErrNo(22) /* Uses OS features not supported on host */
+ ErrAuth error = ErrNo(23) /* Authorization denied */
+ ErrFormat error = ErrNo(24) /* Auxiliary database format error */
+ ErrRange error = ErrNo(25) /* 2nd parameter to sqlite3_bind out of range */
+ ErrNotADB error = ErrNo(26) /* File opened that is not a database file */
+ ErrNotice error = ErrNo(27) /* Notifications from sqlite3_log() */
+ ErrWarning error = ErrNo(28) /* Warnings from sqlite3_log() */
+)
+
+func (err ErrNo) Error() string {
+ return errorString(err)
+}
diff --git a/error_test.go b/error_test.go
new file mode 100644
index 0000000..197b2f0
--- /dev/null
+++ b/error_test.go
@@ -0,0 +1,34 @@
+package sqlite3
+
+import (
+ "database/sql"
+ "io/ioutil"
+ "os"
+ "path"
+ "testing"
+)
+
+func TestFailures(t *testing.T) {
+ dirName, err := ioutil.TempDir("", "sqlite3")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dirName)
+
+ dbFileName := path.Join(dirName, "test.db")
+ f, err := os.Create(dbFileName)
+ if err != nil {
+ t.Error(err)
+ }
+ f.Write([]byte{1, 2, 3, 4, 5})
+ f.Close()
+
+ db, err := sql.Open("sqlite3", dbFileName)
+ if err == nil {
+ _, err = db.Exec("drop table foo")
+ }
+ if err != ErrNotADB {
+ t.Error("wrong error code for corrupted DB")
+ }
+ db.Close()
+}
diff --git a/sqlite3.go b/sqlite3.go
index e7417ec..4ac45e1 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -138,7 +138,7 @@ func (c *SQLiteConn) exec(cmd string) error {
defer C.free(unsafe.Pointer(pcmd))
rv := C.sqlite3_exec(c.db, pcmd, nil, nil, nil)
if rv != C.SQLITE_OK {
- return errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
+ return ErrNo(rv)
}
return nil
}
@@ -151,6 +151,10 @@ func (c *SQLiteConn) Begin() (driver.Tx, error) {
return &SQLiteTx{c}, nil
}
+func errorString(err ErrNo) string {
+ return C.GoString(C.sqlite3_errstr(C.int(err)))
+}
+
// Open database and return a new connection.
// You can specify DSN string with URI filename.
// test.db
@@ -171,7 +175,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
C.SQLITE_OPEN_CREATE,
nil)
if rv != 0 {
- return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
+ return nil, ErrNo(rv)
}
if db == nil {
return nil, errors.New("sqlite succeeded without returning a database")
@@ -179,7 +183,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
rv = C.sqlite3_busy_timeout(db, 5000)
if rv != C.SQLITE_OK {
- return nil, errors.New(C.GoString(C.sqlite3_errmsg(db)))
+ return nil, ErrNo(rv)
}
conn := &SQLiteConn{db}
@@ -229,7 +233,7 @@ func (c *SQLiteConn) Close() error {
}
rv := C.sqlite3_close(c.db)
if rv != C.SQLITE_OK {
- return errors.New("error while closing sqlite database connection")
+ return ErrNo(rv)
}
c.db = nil
return nil
@@ -243,7 +247,7 @@ func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) {
var perror *C.char
rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &perror)
if rv != C.SQLITE_OK {
- return nil, errors.New(C.GoString(C.sqlite3_errmsg(c.db)))
+ return nil, ErrNo(rv)
}
var t string
if perror != nil && C.strlen(perror) > 0 {
@@ -263,7 +267,7 @@ func (s *SQLiteStmt) Close() error {
}
rv := C.sqlite3_finalize(s.s)
if rv != C.SQLITE_OK {
- return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
+ return ErrNo(rv)
}
return nil
}
@@ -276,7 +280,7 @@ func (s *SQLiteStmt) NumInput() int {
func (s *SQLiteStmt) bind(args []driver.Value) error {
rv := C.sqlite3_reset(s.s)
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
- return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
+ return ErrNo(rv)
}
for i, v := range args {
@@ -321,7 +325,7 @@ func (s *SQLiteStmt) bind(args []driver.Value) error {
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
}
if rv != C.SQLITE_OK {
- return errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
+ return ErrNo(rv)
}
}
return nil
@@ -352,7 +356,7 @@ func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
}
rv := C.sqlite3_step(s.s)
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
- return nil, errors.New(C.GoString(C.sqlite3_errmsg(s.c.db)))
+ return nil, ErrNo(rv)
}
res := &SQLiteResult{
@@ -366,7 +370,7 @@ func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
func (rc *SQLiteRows) Close() error {
rv := C.sqlite3_reset(rc.s.s)
if rv != C.SQLITE_OK {
- return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
+ return ErrNo(rv)
}
return nil
}
@@ -389,7 +393,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
return io.EOF
}
if rv != C.SQLITE_ROW {
- return errors.New(C.GoString(C.sqlite3_errmsg(rc.s.c.db)))
+ return ErrNo(rv)
}
if rc.decltype == nil {