aboutsummaryrefslogtreecommitdiff
path: root/sqlite3.go
diff options
context:
space:
mode:
authorRoss Light <light@google.com>2017-04-01 09:12:21 -0700
committerRoss Light <light@google.com>2017-04-01 11:06:59 -0700
commitc6d43c40e663785489630d0f9086bbae5f490394 (patch)
tree4334703ec74232625f578741c16a93b564117bd5 /sqlite3.go
parentMerge pull request #398 from mkungla/qfe1 (diff)
downloadgolite-c6d43c40e663785489630d0f9086bbae5f490394.tar.gz
golite-c6d43c40e663785489630d0f9086bbae5f490394.tar.xz
Add _foreign_keys connection parameter
Fixes #377 Updates #255
Diffstat (limited to 'sqlite3.go')
-rw-r--r--sqlite3.go46
1 files changed, 43 insertions, 3 deletions
diff --git a/sqlite3.go b/sqlite3.go
index cbde900..161eb22 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -400,14 +400,18 @@ func (c *SQLiteConn) AutoCommit() bool {
}
func (c *SQLiteConn) lastError() error {
- rv := C.sqlite3_errcode(c.db)
+ return lastError(c.db)
+}
+
+func lastError(db *C.sqlite3) error {
+ rv := C.sqlite3_errcode(db)
if rv == C.SQLITE_OK {
return nil
}
return Error{
Code: ErrNo(rv),
- ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)),
- err: C.GoString(C.sqlite3_errmsg(c.db)),
+ ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(db)),
+ err: C.GoString(C.sqlite3_errmsg(db)),
}
}
@@ -537,6 +541,8 @@ func errorString(err Error) string {
// _txlock=XXX
// Specify locking behavior for transactions. XXX can be "immediate",
// "deferred", "exclusive".
+// _foreign_keys=X
+// Enable or disable enforcement of foreign keys. X can be 1 or 0.
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
if C.sqlite3_threadsafe() == 0 {
return nil, errors.New("sqlite library was not compiled for thread-safe operation")
@@ -545,6 +551,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
var loc *time.Location
txlock := "BEGIN"
busyTimeout := 5000
+ foreignKeys := -1
pos := strings.IndexRune(dsn, '?')
if pos >= 1 {
params, err := url.ParseQuery(dsn[pos+1:])
@@ -587,6 +594,18 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
}
}
+ // _foreign_keys
+ if val := params.Get("_foreign_keys"); val != "" {
+ switch val {
+ case "1":
+ foreignKeys = 1
+ case "0":
+ foreignKeys = 0
+ default:
+ return nil, fmt.Errorf("Invalid _foreign_keys: %v", val)
+ }
+ }
+
if !strings.HasPrefix(dsn, "file:") {
dsn = dsn[:pos]
}
@@ -612,6 +631,27 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, Error{Code: ErrNo(rv)}
}
+ exec := func(s string) error {
+ cs := C.CString(s)
+ rv := C.sqlite3_exec(db, cs, nil, nil, nil)
+ C.free(unsafe.Pointer(cs))
+ if rv != C.SQLITE_OK {
+ return lastError(db)
+ }
+ return nil
+ }
+ if foreignKeys == 0 {
+ if err := exec("PRAGMA foreign_keys = OFF;"); err != nil {
+ C.sqlite3_close_v2(db)
+ return nil, err
+ }
+ } else if foreignKeys == 1 {
+ if err := exec("PRAGMA foreign_keys = ON;"); err != nil {
+ C.sqlite3_close_v2(db)
+ return nil, err
+ }
+ }
+
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
if len(d.Extensions) > 0 {