From 7b320119ba532fd409ec7dade7ad02011c309599 Mon Sep 17 00:00:00 2001 From: Niall Sheridan Date: Wed, 18 Oct 2017 13:15:14 +0100 Subject: Update dependencies --- vendor/github.com/mattn/go-sqlite3/sqlite3.go | 177 +++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 16 deletions(-) (limited to 'vendor/github.com/mattn/go-sqlite3/sqlite3.go') diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3.go index 33b9b9c..1ff58c3 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3.go @@ -7,7 +7,7 @@ package sqlite3 /* #cgo CFLAGS: -std=gnu99 -#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE +#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE=1 #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 @@ -100,6 +100,11 @@ int _sqlite3_create_function( } void callbackTrampoline(sqlite3_context*, int, sqlite3_value**); + +int compareTrampoline(void*, int, char*, int, char*); +int commitHookTrampoline(void*); +void rollbackHookTrampoline(void*); +void updateHookTrampoline(void*, int, char*, char*, sqlite3_int64); */ import "C" import ( @@ -113,6 +118,7 @@ import ( "runtime" "strconv" "strings" + "sync" "time" "unsafe" @@ -149,6 +155,12 @@ func Version() (libVersion string, libVersionNumber int, sourceID string) { return libVersion, libVersionNumber, sourceID } +const ( + SQLITE_DELETE = C.SQLITE_DELETE + SQLITE_INSERT = C.SQLITE_INSERT + SQLITE_UPDATE = C.SQLITE_UPDATE +) + // SQLiteDriver implement sql.Driver. type SQLiteDriver struct { Extensions []string @@ -157,6 +169,7 @@ type SQLiteDriver struct { // SQLiteConn implement sql.Conn. type SQLiteConn struct { + mu sync.Mutex db *C.sqlite3 loc *time.Location txlock string @@ -171,6 +184,7 @@ type SQLiteTx struct { // SQLiteStmt implement sql.Stmt. type SQLiteStmt struct { + mu sync.Mutex c *SQLiteConn s *C.sqlite3_stmt t string @@ -191,6 +205,7 @@ type SQLiteRows struct { cols []string decltype []string cls bool + closed bool done chan struct{} } @@ -313,6 +328,74 @@ func (tx *SQLiteTx) Rollback() error { return err } +// RegisterCollation makes a Go function available as a collation. +// +// cmp receives two UTF-8 strings, a and b. The result should be 0 if +// a==b, -1 if a < b, and +1 if a > b. +// +// cmp must always return the same result given the same +// inputs. Additionally, it must have the following properties for all +// strings A, B and C: if A==B then B==A; if A==B and B==C then A==C; +// if AA; if A= 1 { params, err := url.ParseQuery(dsn[pos+1:]) @@ -606,6 +692,18 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { } } + // _recursive_triggers + if val := params.Get("_recursive_triggers"); val != "" { + switch val { + case "1": + recursiveTriggers = 1 + case "0": + recursiveTriggers = 0 + default: + return nil, fmt.Errorf("Invalid _recursive_triggers: %v", val) + } + } + if !strings.HasPrefix(dsn, "file:") { dsn = dsn[:pos] } @@ -652,6 +750,17 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { return nil, err } } + if recursiveTriggers == 0 { + if err := exec("PRAGMA recursive_triggers = OFF;"); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } else if recursiveTriggers == 1 { + if err := exec("PRAGMA recursive_triggers = ON;"); err != nil { + C.sqlite3_close_v2(db) + return nil, err + } + } conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} @@ -679,11 +788,22 @@ func (c *SQLiteConn) Close() error { return c.lastError() } deleteHandles(c) + c.mu.Lock() c.db = nil + c.mu.Unlock() runtime.SetFinalizer(c, nil) return nil } +func (c *SQLiteConn) dbConnOpen() bool { + if c == nil { + return false + } + c.mu.Lock() + defer c.mu.Unlock() + return c.db != nil +} + // Prepare the query string. Return a new statement. func (c *SQLiteConn) Prepare(query string) (driver.Stmt, error) { return c.prepare(context.Background(), query) @@ -709,14 +829,17 @@ func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, er // Close the statement. func (s *SQLiteStmt) Close() error { + s.mu.Lock() + defer s.mu.Unlock() if s.closed { return nil } s.closed = true - if s.c == nil || s.c.db == nil { + if !s.c.dbConnOpen() { return errors.New("sqlite statement with already closed database connection") } rv := C.sqlite3_finalize(s.s) + s.s = nil if rv != C.SQLITE_OK { return s.c.lastError() } @@ -734,6 +857,8 @@ type bindArg struct { v driver.Value } +var placeHolder = []byte{0} + func (s *SQLiteStmt) bind(args []namedValue) error { rv := C.sqlite3_reset(s.s) if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE { @@ -755,8 +880,7 @@ func (s *SQLiteStmt) bind(args []namedValue) error { rv = C.sqlite3_bind_null(s.s, n) case string: if len(v) == 0 { - b := []byte{0} - rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(0)) + rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&placeHolder[0])), C.int(0)) } else { b := []byte(v) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) @@ -772,11 +896,11 @@ func (s *SQLiteStmt) bind(args []namedValue) error { case float64: rv = C.sqlite3_bind_double(s.s, n, C.double(v)) case []byte: - if len(v) == 0 { - rv = C._sqlite3_bind_blob(s.s, n, nil, 0) - } else { - rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(len(v))) + ln := len(v) + if ln == 0 { + v = placeHolder } + rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln)) case time.Time: b := []byte(v.Format(SQLiteTimestampFormats[0])) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) @@ -811,6 +935,7 @@ func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows, cols: nil, decltype: nil, cls: s.cls, + closed: false, done: make(chan struct{}), } @@ -883,25 +1008,33 @@ func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result // Close the rows. func (rc *SQLiteRows) Close() error { - if rc.s.closed { + rc.s.mu.Lock() + if rc.s.closed || rc.closed { + rc.s.mu.Unlock() return nil } + rc.closed = true if rc.done != nil { close(rc.done) } if rc.cls { + rc.s.mu.Unlock() return rc.s.Close() } rv := C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { + rc.s.mu.Unlock() return rc.s.c.lastError() } + rc.s.mu.Unlock() return nil } // Columns return column names. func (rc *SQLiteRows) Columns() []string { - if rc.nc != len(rc.cols) { + rc.s.mu.Lock() + defer rc.s.mu.Unlock() + if rc.s.s != nil && rc.nc != len(rc.cols) { rc.cols = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.cols[i] = C.GoString(C.sqlite3_column_name(rc.s.s, C.int(i))) @@ -910,9 +1043,8 @@ func (rc *SQLiteRows) Columns() []string { return rc.cols } -// DeclTypes return column types. -func (rc *SQLiteRows) DeclTypes() []string { - if rc.decltype == nil { +func (rc *SQLiteRows) declTypes() []string { + if rc.s.s != nil && rc.decltype == nil { rc.decltype = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { rc.decltype[i] = strings.ToLower(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))) @@ -921,8 +1053,20 @@ func (rc *SQLiteRows) DeclTypes() []string { return rc.decltype } +// DeclTypes return column types. +func (rc *SQLiteRows) DeclTypes() []string { + rc.s.mu.Lock() + defer rc.s.mu.Unlock() + return rc.declTypes() +} + // Next move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { + if rc.s.closed { + return io.EOF + } + rc.s.mu.Lock() + defer rc.s.mu.Unlock() rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { return io.EOF @@ -935,7 +1079,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { return nil } - rc.DeclTypes() + rc.declTypes() for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { @@ -948,10 +1092,11 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { // large to be a reasonable timestamp in seconds. if val > 1e12 || val < -1e12 { val *= int64(time.Millisecond) // convert ms to nsec + t = time.Unix(0, val) } else { - val *= int64(time.Second) // convert sec to nsec + t = time.Unix(val, 0) } - t = time.Unix(0, val).UTC() + t = t.UTC() if rc.s.c.loc != nil { t = t.In(rc.s.c.loc) } -- cgit v1.2.3