diff --git a/all_test.go b/all_test.go index 4770e3e..9c869bb 100644 --- a/all_test.go +++ b/all_test.go @@ -1880,7 +1880,7 @@ func TestIssue66(t *testing.T) { // think that's correct (jnml). t.Logf("insert 2: %v", err) - if !strings.Contains(err.Error(), "SQLITE_BUSY") { + if !strings.Contains(err.Error(), "database is locked (5) (SQLITE_BUSY)") { t.Fatalf("insert 2: %v", err) } } @@ -2010,3 +2010,58 @@ func testIssue65(t *testing.T, db *sql.DB, canFail bool) { } } } + +// https://gitlab.com/cznic/sqlite/-/issues/73 +func TestConstraintPrimaryKeyError(t *testing.T) { + db, err := sql.Open(driverName, "file::memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + _, err = db.Exec(`CREATE TABLE IF NOT EXISTS hash (hashval TEXT PRIMARY KEY NOT NULL)`) + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("INSERT INTO hash (hashval) VALUES (?)", "somehashval") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("INSERT INTO hash (hashval) VALUES (?)", "somehashval") + if err == nil { + t.Fatal("wanted error") + } + + if errs, want := err.Error(), "constraint failed: UNIQUE constraint failed: hash.hashval (1555)"; errs != want { + t.Fatalf("got error string %q, want %q", errs, want) + } +} + +func TestConstraintUniqueError(t *testing.T) { + db, err := sql.Open(driverName, "file::memory:") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + _, err = db.Exec(`CREATE TABLE IF NOT EXISTS hash (hashval TEXT UNIQUE)`) + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("INSERT INTO hash (hashval) VALUES (?)", "somehashval") + if err != nil { + t.Fatal(err) + } + + _, err = db.Exec("INSERT INTO hash (hashval) VALUES (?)", "somehashval") + if err == nil { + t.Fatal("wanted error") + } + + if errs, want := err.Error(), "constraint failed: UNIQUE constraint failed: hash.hashval (2067)"; errs != want { + t.Fatalf("got error string %q, want %q", errs, want) + } +} diff --git a/sqlite.go b/sqlite.go index ccf079e..5383d12 100644 --- a/sqlite.go +++ b/sqlite.go @@ -11,7 +11,6 @@ import ( "context" "database/sql" "database/sql/driver" - "errors" "fmt" "io" "math" @@ -883,7 +882,7 @@ func (c *conn) step(pstmt uintptr) (int, error) { return int(rc), nil default: - return int(rc), errors.New(ErrorCodeString[int(rc)]) + return int(rc), c.errstr(rc) } } } @@ -1225,11 +1224,15 @@ func (c *conn) errstr(rc int32) error { p := sqlite3.Xsqlite3_errstr(c.tls, rc) str := libc.GoString(p) p = sqlite3.Xsqlite3_errmsg(c.tls, c.db) + var s string + if rc == sqlite3.SQLITE_BUSY { + s = " (SQLITE_BUSY)" + } switch msg := libc.GoString(p); { case msg == str: - return &Error{msg: fmt.Sprintf("%s (%v)", str, rc), code: int(rc)} + return &Error{msg: fmt.Sprintf("%s (%v)%s", str, rc, s), code: int(rc)} default: - return &Error{msg: fmt.Sprintf("%s: %s (%v)", str, msg, rc), code: int(rc)} + return &Error{msg: fmt.Sprintf("%s: %s (%v)%s", str, msg, rc, s), code: int(rc)} } }