From ee720241fc5db8cf245ee588870940ad7a92863c Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Wed, 30 Aug 2017 13:19:01 +0900 Subject: [PATCH 1/4] support Solaris See #459 --- sqlite3_libsqlite3.go | 1 + sqlite3_other.go | 1 + 2 files changed, 2 insertions(+) diff --git a/sqlite3_libsqlite3.go b/sqlite3_libsqlite3.go index 135863e..e4557e6 100644 --- a/sqlite3_libsqlite3.go +++ b/sqlite3_libsqlite3.go @@ -10,5 +10,6 @@ package sqlite3 #cgo CFLAGS: -DUSE_LIBSQLITE3 #cgo linux LDFLAGS: -lsqlite3 #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 +#cgo solaris LDFLAGS: -lsqlite3 */ import "C" diff --git a/sqlite3_other.go b/sqlite3_other.go index a20d02c..f721b5e 100644 --- a/sqlite3_other.go +++ b/sqlite3_other.go @@ -9,5 +9,6 @@ package sqlite3 /* #cgo CFLAGS: -I. #cgo linux LDFLAGS: -ldl +#cgo solaris LDFLAGS: -lc */ import "C" From 911f1c4fa68b1823e76c909e777571f563bdb184 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Wed, 30 Aug 2017 13:29:47 +0900 Subject: [PATCH 2/4] fix lock --- sqlite3.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index 076c9bd..506a1b3 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -182,6 +182,7 @@ type SQLiteTx struct { // SQLiteStmt implement sql.Stmt. type SQLiteStmt struct { + mu sync.Mutex c *SQLiteConn s *C.sqlite3_stmt t string @@ -803,6 +804,8 @@ 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 } @@ -980,7 +983,9 @@ func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result // Close the rows. func (rc *SQLiteRows) Close() error { + rc.s.mu.Lock() if rc.s.closed || rc.closed { + rc.s.mu.Unlock() return nil } rc.closed = true @@ -988,18 +993,23 @@ func (rc *SQLiteRows) Close() error { 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))) @@ -1010,7 +1020,9 @@ func (rc *SQLiteRows) Columns() []string { // DeclTypes return column types. func (rc *SQLiteRows) DeclTypes() []string { - if rc.decltype == nil { + rc.s.mu.Lock() + defer rc.s.mu.Unlock() + 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)))) @@ -1021,20 +1033,30 @@ func (rc *SQLiteRows) DeclTypes() []string { // Next move cursor to next. func (rc *SQLiteRows) Next(dest []driver.Value) error { + if rc.s.closed { + return io.EOF + } + rc.s.mu.Lock() rv := C.sqlite3_step(rc.s.s) if rv == C.SQLITE_DONE { + rc.s.mu.Unlock() return io.EOF } if rv != C.SQLITE_ROW { + defer rc.s.mu.Unlock() rv = C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return rc.s.c.lastError() } + rc.s.mu.Unlock() return nil } rc.DeclTypes() + rc.s.mu.Lock() + defer rc.s.mu.Unlock() + for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) { case C.SQLITE_INTEGER: From 58ed4a0810db4a6757547ca36adf4cf2ffc18fdd Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Wed, 30 Aug 2017 19:30:53 +0900 Subject: [PATCH 3/4] fix race --- sqlite3.go | 1 - 1 file changed, 1 deletion(-) diff --git a/sqlite3.go b/sqlite3.go index 506a1b3..c345727 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -1048,7 +1048,6 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { if rv != C.SQLITE_OK { return rc.s.c.lastError() } - rc.s.mu.Unlock() return nil } From 8d81c2f1f8f4b00b487c668bb8c9df5daa112900 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Wed, 30 Aug 2017 19:37:57 +0900 Subject: [PATCH 4/4] fix race --- sqlite3.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index c345727..42a2e18 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -1018,10 +1018,7 @@ func (rc *SQLiteRows) Columns() []string { return rc.cols } -// DeclTypes return column types. -func (rc *SQLiteRows) DeclTypes() []string { - rc.s.mu.Lock() - defer rc.s.mu.Unlock() +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++ { @@ -1031,19 +1028,25 @@ 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 { - rc.s.mu.Unlock() return io.EOF } if rv != C.SQLITE_ROW { - defer rc.s.mu.Unlock() rv = C.sqlite3_reset(rc.s.s) if rv != C.SQLITE_OK { return rc.s.c.lastError() @@ -1051,10 +1054,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error { return nil } - rc.DeclTypes() - - rc.s.mu.Lock() - defer rc.s.mu.Unlock() + rc.declTypes() for i := range dest { switch C.sqlite3_column_type(rc.s.s, C.int(i)) {