mirror of
https://github.com/golang/go
synced 2024-11-23 04:00:03 -07:00
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: 962c785dfb
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>
This commit is contained in:
parent
4ebb6f5110
commit
194b636f8f
@ -115,6 +115,9 @@ type DriverContext interface {
|
|||||||
// DriverContext's OpenConnector method, to allow drivers
|
// DriverContext's OpenConnector method, to allow drivers
|
||||||
// access to context and to avoid repeated parsing of driver
|
// access to context and to avoid repeated parsing of driver
|
||||||
// configuration.
|
// 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 {
|
type Connector interface {
|
||||||
// Connect returns a connection to the database.
|
// Connect returns a connection to the database.
|
||||||
// Connect may return a cached connection (one previously
|
// Connect may return a cached connection (one previously
|
||||||
|
@ -56,6 +56,7 @@ type fakeConnector struct {
|
|||||||
name string
|
name string
|
||||||
|
|
||||||
waiter func(context.Context)
|
waiter func(context.Context)
|
||||||
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
|
func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
|
||||||
@ -68,6 +69,14 @@ func (c *fakeConnector) Driver() driver.Driver {
|
|||||||
return fdriver
|
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 {
|
type fakeDriverCtx struct {
|
||||||
fakeDriver
|
fakeDriver
|
||||||
}
|
}
|
||||||
|
@ -850,6 +850,12 @@ func (db *DB) Close() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.stop()
|
db.stop()
|
||||||
|
if c, ok := db.connector.(io.Closer); ok {
|
||||||
|
err1 := c.Close()
|
||||||
|
if err1 != nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4059,9 +4059,18 @@ func TestOpenConnector(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
if _, is := db.connector.(*fakeConnector); !is {
|
c, ok := db.connector.(*fakeConnector)
|
||||||
|
if !ok {
|
||||||
t.Fatal("not using *fakeConnector")
|
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 {
|
type ctxOnlyDriver struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user