summaryrefslogtreecommitdiff
path: root/src/database
diff options
context:
space:
mode:
authorIvan Trubach <mr.trubach@icloud.com>2021-02-25 19:15:04 +0000
committerEmmanuel Odeke <emmanuel@orijtech.com>2021-02-25 19:34:27 +0000
commit194b636f8f1ff7d6b709b5b9010d1d14b3919e66 (patch)
treefafdc7368e92f04ceff0708ff25be931635f2525 /src/database
parent4ebb6f5110af3e60455d8751b996b958afb25a36 (diff)
downloadgo-git-194b636f8f1ff7d6b709b5b9010d1d14b3919e66.tar.gz
database/sql: close driver.Connector if it implements io.Closer
This change allows driver implementations to manage resources in driver.Connector, e.g. to share the same underlying database handle between multiple connections. That is, it allows embedded databases with in-memory backends like SQLite and Genji to safely release the resources once the sql.DB is closed. This makes it possible to address oddities with in-memory stores in SQLite and Genji drivers without introducing too much complexity in the driver implementations. See also: - https://github.com/mattn/go-sqlite3/issues/204 - https://github.com/mattn/go-sqlite3/issues/511 - https://github.com/genjidb/genji/issues/210 Fixes #41790 Change-Id: Idbd19763134438ed38288b9d44f16608e4e97fd7 GitHub-Last-Rev: 962c785dfb3bb6ad98b2216bcedd84ba383fe872 GitHub-Pull-Request: golang/go#41710 Reviewed-on: https://go-review.googlesource.com/c/go/+/258360 Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com> Reviewed-by: Daniel Theophanes <kardianos@gmail.com> Trust: Emmanuel Odeke <emmanuel@orijtech.com> Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/database')
-rw-r--r--src/database/sql/driver/driver.go3
-rw-r--r--src/database/sql/fakedb_test.go9
-rw-r--r--src/database/sql/sql.go6
-rw-r--r--src/database/sql/sql_test.go11
4 files changed, 28 insertions, 1 deletions
diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go
index 5bbcf20db2..f09396175a 100644
--- a/src/database/sql/driver/driver.go
+++ b/src/database/sql/driver/driver.go
@@ -115,6 +115,9 @@ type DriverContext interface {
// DriverContext's OpenConnector method, to allow drivers
// access to context and to avoid repeated parsing of driver
// configuration.
+//
+// If a Connector implements io.Closer, the sql package's DB.Close
+// method will call Close and return error (if any).
type Connector interface {
// Connect returns a connection to the database.
// Connect may return a cached connection (one previously
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
index 7605a2a6d2..1bfd1118aa 100644
--- a/src/database/sql/fakedb_test.go
+++ b/src/database/sql/fakedb_test.go
@@ -56,6 +56,7 @@ type fakeConnector struct {
name string
waiter func(context.Context)
+ closed bool
}
func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
@@ -68,6 +69,14 @@ func (c *fakeConnector) Driver() driver.Driver {
return fdriver
}
+func (c *fakeConnector) Close() error {
+ if c.closed {
+ return errors.New("fakedb: connector is closed")
+ }
+ c.closed = true
+ return nil
+}
+
type fakeDriverCtx struct {
fakeDriver
}
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index 726aadb899..37bcb0d091 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -850,6 +850,12 @@ func (db *DB) Close() error {
}
}
db.stop()
+ if c, ok := db.connector.(io.Closer); ok {
+ err1 := c.Close()
+ if err1 != nil {
+ err = err1
+ }
+ }
return err
}
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 99bfd62491..c06e565ea9 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -4059,9 +4059,18 @@ func TestOpenConnector(t *testing.T) {
}
defer db.Close()
- if _, is := db.connector.(*fakeConnector); !is {
+ c, ok := db.connector.(*fakeConnector)
+ if !ok {
t.Fatal("not using *fakeConnector")
}
+
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ if !c.closed {
+ t.Fatal("connector is not closed")
+ }
}
type ctxOnlyDriver struct {