aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/mattn/go-sqlite3/sqlite3.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattn/go-sqlite3/sqlite3.go')
-rw-r--r--vendor/github.com/mattn/go-sqlite3/sqlite3.go66
1 files changed, 57 insertions, 9 deletions
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3.go
index cbe3964..33b9b9c 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3.go
@@ -10,6 +10,7 @@ package sqlite3
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
+#cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC
#cgo CFLAGS: -Wno-deprecated-declarations
#ifndef USE_LIBSQLITE3
#include <sqlite3-binding.h>
@@ -382,14 +383,14 @@ func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) erro
if pure {
opts |= C.SQLITE_DETERMINISTIC
}
- rv := sqlite3_create_function(c.db, cname, C.int(numArgs), C.int(opts), newHandle(c, &fi), C.callbackTrampoline, nil, nil)
+ rv := sqlite3CreateFunction(c.db, cname, C.int(numArgs), C.int(opts), newHandle(c, &fi), C.callbackTrampoline, nil, nil)
if rv != C.SQLITE_OK {
return c.lastError()
}
return nil
}
-func sqlite3_create_function(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
+func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(unsafe.Pointer(xFunc)), (*[0]byte)(unsafe.Pointer(xStep)), (*[0]byte)(unsafe.Pointer(xFinal)))
}
@@ -398,11 +399,19 @@ func (c *SQLiteConn) AutoCommit() bool {
return int(C.sqlite3_get_autocommit(c.db)) != 0
}
-func (c *SQLiteConn) lastError() Error {
+func (c *SQLiteConn) lastError() error {
+ 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(C.sqlite3_errcode(c.db)),
- ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(c.db)),
- err: C.GoString(C.sqlite3_errmsg(c.db)),
+ Code: ErrNo(rv),
+ ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(db)),
+ err: C.GoString(C.sqlite3_errmsg(db)),
}
}
@@ -430,7 +439,7 @@ func (c *SQLiteConn) exec(ctx context.Context, query string, args []namedValue)
na := s.NumInput()
if len(args) < na {
s.Close()
- return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
+ return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
}
for i := 0; i < na; i++ {
args[i].Ordinal -= start
@@ -480,7 +489,7 @@ func (c *SQLiteConn) query(ctx context.Context, query string, args []namedValue)
s.(*SQLiteStmt).cls = true
na := s.NumInput()
if len(args) < na {
- return nil, fmt.Errorf("Not enough args to execute query. Expected %d, got %d.", na, len(args))
+ return nil, fmt.Errorf("not enough args to execute query: want %d got %d", na, len(args))
}
for i := 0; i < na; i++ {
args[i].Ordinal -= start
@@ -532,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")
@@ -540,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:])
@@ -582,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]
}
@@ -604,19 +628,43 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
rv = C.sqlite3_busy_timeout(db, C.int(busyTimeout))
if rv != C.SQLITE_OK {
+ C.sqlite3_close_v2(db)
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 {
if err := conn.loadExtensions(d.Extensions); err != nil {
+ conn.Close()
return nil, err
}
}
if d.ConnectHook != nil {
if err := d.ConnectHook(conn); err != nil {
+ conn.Close()
return nil, err
}
}
@@ -626,11 +674,11 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// Close the connection.
func (c *SQLiteConn) Close() error {
- deleteHandles(c)
rv := C.sqlite3_close_v2(c.db)
if rv != C.SQLITE_OK {
return c.lastError()
}
+ deleteHandles(c)
c.db = nil
runtime.SetFinalizer(c, nil)
return nil