|  | // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. | 
|  | // | 
|  | // Use of this source code is governed by an MIT-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package sqlite3 | 
|  |  | 
|  | import ( | 
|  | "database/sql" | 
|  | "io/ioutil" | 
|  | "os" | 
|  | "path" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | func TestSimpleError(t *testing.T) { | 
|  | e := ErrError.Error() | 
|  | if e != "SQL logic error or missing database" { | 
|  | t.Error("wrong error code:" + e) | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestCorruptDbErrors(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") | 
|  | } | 
|  |  | 
|  | sqliteErr := err.(Error) | 
|  | if sqliteErr.Code != ErrNotADB { | 
|  | t.Error("wrong error code for corrupted DB") | 
|  | } | 
|  | if err.Error() == "" { | 
|  | t.Error("wrong error string for corrupted DB") | 
|  | } | 
|  | db.Close() | 
|  | } | 
|  |  | 
|  | func TestSqlLogicErrors(t *testing.T) { | 
|  | dirName, err := ioutil.TempDir("", "sqlite3") | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | defer os.RemoveAll(dirName) | 
|  |  | 
|  | dbFileName := path.Join(dirName, "test.db") | 
|  | db, err := sql.Open("sqlite3", dbFileName) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  | defer db.Close() | 
|  |  | 
|  | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  |  | 
|  | const expectedErr = "table Foo already exists" | 
|  | _, err = db.Exec("CREATE TABLE Foo (id INTEGER PRIMARY KEY)") | 
|  | if err.Error() != expectedErr { | 
|  | t.Errorf("Unexpected error: %s, expected %s", err.Error(), expectedErr) | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | func TestExtendedErrorCodes_ForeignKey(t *testing.T) { | 
|  | dirName, err := ioutil.TempDir("", "sqlite3-err") | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | defer os.RemoveAll(dirName) | 
|  |  | 
|  | dbFileName := path.Join(dirName, "test.db") | 
|  | db, err := sql.Open("sqlite3", dbFileName) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  | defer db.Close() | 
|  |  | 
|  | _, err = db.Exec("PRAGMA foreign_keys=ON;") | 
|  | if err != nil { | 
|  | t.Errorf("PRAGMA foreign_keys=ON: %v", err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec(`CREATE TABLE Foo ( | 
|  | id INTEGER PRIMARY KEY AUTOINCREMENT, | 
|  | value INTEGER NOT NULL, | 
|  | ref INTEGER NULL REFERENCES Foo (id), | 
|  | UNIQUE(value) | 
|  | );`) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (100, 100);") | 
|  | if err == nil { | 
|  | t.Error("No error!") | 
|  | } else { | 
|  | sqliteErr := err.(Error) | 
|  | if sqliteErr.Code != ErrConstraint { | 
|  | t.Errorf("Wrong basic error code: %d != %d", | 
|  | sqliteErr.Code, ErrConstraint) | 
|  | } | 
|  | if sqliteErr.ExtendedCode != ErrConstraintForeignKey { | 
|  | t.Errorf("Wrong extended error code: %d != %d", | 
|  | sqliteErr.ExtendedCode, ErrConstraintForeignKey) | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | func TestExtendedErrorCodes_NotNull(t *testing.T) { | 
|  | dirName, err := ioutil.TempDir("", "sqlite3-err") | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | defer os.RemoveAll(dirName) | 
|  |  | 
|  | dbFileName := path.Join(dirName, "test.db") | 
|  | db, err := sql.Open("sqlite3", dbFileName) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  | defer db.Close() | 
|  |  | 
|  | _, err = db.Exec("PRAGMA foreign_keys=ON;") | 
|  | if err != nil { | 
|  | t.Errorf("PRAGMA foreign_keys=ON: %v", err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec(`CREATE TABLE Foo ( | 
|  | id INTEGER PRIMARY KEY AUTOINCREMENT, | 
|  | value INTEGER NOT NULL, | 
|  | ref INTEGER NULL REFERENCES Foo (id), | 
|  | UNIQUE(value) | 
|  | );`) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  |  | 
|  | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") | 
|  | if err != nil { | 
|  | t.Fatalf("Creating first row: %v", err) | 
|  | } | 
|  |  | 
|  | id, err := res.LastInsertId() | 
|  | if err != nil { | 
|  | t.Fatalf("Retrieving last insert id: %v", err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec("INSERT INTO Foo (ref) VALUES (?);", id) | 
|  | if err == nil { | 
|  | t.Error("No error!") | 
|  | } else { | 
|  | sqliteErr := err.(Error) | 
|  | if sqliteErr.Code != ErrConstraint { | 
|  | t.Errorf("Wrong basic error code: %d != %d", | 
|  | sqliteErr.Code, ErrConstraint) | 
|  | } | 
|  | if sqliteErr.ExtendedCode != ErrConstraintNotNull { | 
|  | t.Errorf("Wrong extended error code: %d != %d", | 
|  | sqliteErr.ExtendedCode, ErrConstraintNotNull) | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | func TestExtendedErrorCodes_Unique(t *testing.T) { | 
|  | dirName, err := ioutil.TempDir("", "sqlite3-err") | 
|  | if err != nil { | 
|  | t.Fatal(err) | 
|  | } | 
|  | defer os.RemoveAll(dirName) | 
|  |  | 
|  | dbFileName := path.Join(dirName, "test.db") | 
|  | db, err := sql.Open("sqlite3", dbFileName) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  | defer db.Close() | 
|  |  | 
|  | _, err = db.Exec("PRAGMA foreign_keys=ON;") | 
|  | if err != nil { | 
|  | t.Errorf("PRAGMA foreign_keys=ON: %v", err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec(`CREATE TABLE Foo ( | 
|  | id INTEGER PRIMARY KEY AUTOINCREMENT, | 
|  | value INTEGER NOT NULL, | 
|  | ref INTEGER NULL REFERENCES Foo (id), | 
|  | UNIQUE(value) | 
|  | );`) | 
|  | if err != nil { | 
|  | t.Error(err) | 
|  | } | 
|  |  | 
|  | res, err := db.Exec("INSERT INTO Foo (value) VALUES (100);") | 
|  | if err != nil { | 
|  | t.Fatalf("Creating first row: %v", err) | 
|  | } | 
|  |  | 
|  | id, err := res.LastInsertId() | 
|  | if err != nil { | 
|  | t.Fatalf("Retrieving last insert id: %v", err) | 
|  | } | 
|  |  | 
|  | _, err = db.Exec("INSERT INTO Foo (ref, value) VALUES (?, 100);", id) | 
|  | if err == nil { | 
|  | t.Error("No error!") | 
|  | } else { | 
|  | sqliteErr := err.(Error) | 
|  | if sqliteErr.Code != ErrConstraint { | 
|  | t.Errorf("Wrong basic error code: %d != %d", | 
|  | sqliteErr.Code, ErrConstraint) | 
|  | } | 
|  | if sqliteErr.ExtendedCode != ErrConstraintUnique { | 
|  | t.Errorf("Wrong extended error code: %d != %d", | 
|  | sqliteErr.ExtendedCode, ErrConstraintUnique) | 
|  | } | 
|  | extended := sqliteErr.Code.Extend(3).Error() | 
|  | expected := "constraint failed" | 
|  | if extended != expected { | 
|  | t.Errorf("Wrong basic error code: %q != %q", | 
|  | extended, expected) | 
|  | } | 
|  | } | 
|  |  | 
|  | } |