]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: close driver.Connector if it implements io.Closer
authorIvan Trubach <mr.trubach@icloud.com>
Thu, 25 Feb 2021 19:15:04 +0000 (19:15 +0000)
committerEmmanuel Odeke <emmanuel@orijtech.com>
Thu, 25 Feb 2021 19:34:27 +0000 (19:34 +0000)
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>

src/database/sql/driver/driver.go
src/database/sql/fakedb_test.go
src/database/sql/sql.go
src/database/sql/sql_test.go

index 5bbcf20db2f07d90f91d1d3d2f82786b55b7d948..f09396175acf86099e5d902fb944d1f8131210e2 100644 (file)
@@ -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
index 7605a2a6d23e0327bcccaf1d8a8cd9d616a26a23..1bfd1118aad68b1ae24f207b0b8dcfe49f972631 100644 (file)
@@ -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
 }
index 726aadb8990e6871fdb1253e4f422e60b39f229f..37bcb0d09186457f3cea265fd2827fa7968f5e42 100644 (file)
@@ -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
 }
 
index 99bfd62491fa3beb3d4721b024ba93dc5b5181df..c06e565ea9c7a57d54b8dce533086391eb46ea63 100644 (file)
@@ -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 {