aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sqlite3.go22
-rw-r--r--sqlite3_test.go58
2 files changed, 64 insertions, 16 deletions
diff --git a/sqlite3.go b/sqlite3.go
index 7506522..f731d20 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -990,6 +990,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
authPass := ""
authCrypt := ""
authSalt := ""
+ mutex := C.int(C.SQLITE_OPEN_FULLMUTEX)
txlock := "BEGIN"
// PRAGMA's
@@ -1006,7 +1007,6 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
secureDelete := "DEFAULT"
synchronousMode := "NORMAL"
writableSchema := -1
- flags := C.SQLITE_OPEN_READWRITE | C.SQLITE_OPEN_CREATE | C.SQLITE_OPEN_FULLMUTEX
pos := strings.IndexRune(dsn, '?')
if pos >= 1 {
@@ -1015,17 +1015,6 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, err
}
- if val := params.Get("mode"); val != "" {
- switch val {
- case "ro":
- flags |= C.SQLITE_OPEN_READONLY
- case "rw":
- flags ^= C.SQLITE_OPEN_CREATE
- case "rwc":
- flags |= C.SQLITE_OPEN_CREATE
- }
- }
-
// Authentication
if _, ok := params["_auth"]; ok {
authCreate = true
@@ -1060,9 +1049,9 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
if val := params.Get("_mutex"); val != "" {
switch strings.ToLower(val) {
case "no":
- flags |= C.SQLITE_OPEN_NOMUTEX
+ mutex = C.SQLITE_OPEN_NOMUTEX
case "full":
- flags |= C.SQLITE_OPEN_FULLMUTEX
+ mutex = C.SQLITE_OPEN_FULLMUTEX
default:
return nil, fmt.Errorf("Invalid _mutex: %v", val)
}
@@ -1349,8 +1338,9 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
var db *C.sqlite3
name := C.CString(dsn)
defer C.free(unsafe.Pointer(name))
-
- rv := C._sqlite3_open_v2(name, &db, C.int(flags), nil)
+ rv := C._sqlite3_open_v2(name, &db,
+ mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE,
+ nil)
if rv != 0 {
if db != nil {
C.sqlite3_close_v2(db)
diff --git a/sqlite3_test.go b/sqlite3_test.go
index 0667893..16bbb10 100644
--- a/sqlite3_test.go
+++ b/sqlite3_test.go
@@ -87,6 +87,64 @@ func TestOpen(t *testing.T) {
}
}
+func TestOpenNoCreate(t *testing.T) {
+ filename := t.Name() + ".sqlite"
+
+ if err := os.Remove(filename); err != nil && !os.IsNotExist(err) {
+ t.Fatal(err)
+ }
+ defer os.Remove(filename)
+
+ // https://golang.org/pkg/database/sql/#Open
+ // "Open may just validate its arguments without creating a connection
+ // to the database. To verify that the data source name is valid, call Ping."
+ db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?mode=rw", filename))
+ if err == nil {
+ defer db.Close()
+
+ err = db.Ping()
+ if err == nil {
+ t.Fatal("expected error from Open or Ping")
+ }
+ }
+
+ sqlErr, ok := err.(Error)
+ if !ok {
+ t.Fatalf("expected sqlite3.Error, but got %T", err)
+ }
+
+ if sqlErr.Code != ErrCantOpen {
+ t.Fatalf("expected SQLITE_CANTOPEN, but got %v", sqlErr)
+ }
+
+ // make sure database file truly was not created
+ if _, err := os.Stat(filename); !os.IsNotExist(err) {
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Fatal("expected database file to not exist")
+ }
+
+ // verify that it works if the mode is "rwc" instead
+ db, err = sql.Open("sqlite3", fmt.Sprintf("file:%s?mode=rwc", filename))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ if err := db.Ping(); err != nil {
+ t.Fatal(err)
+ }
+
+ // make sure database file truly was created
+ if _, err := os.Stat(filename); err != nil {
+ if !os.IsNotExist(err) {
+ t.Fatal(err)
+ }
+ t.Fatal("expected database file to exist")
+ }
+}
+
func TestReadonly(t *testing.T) {
tempFilename := TempFilename(t)
defer os.Remove(tempFilename)