]> Cypherpunks repositories - gostls13.git/commitdiff
database/sql: allow OpenConnector in a driver.Driver interface
authorDaniel Theophanes <kardianos@gmail.com>
Tue, 14 Nov 2017 16:53:56 +0000 (08:53 -0800)
committerDaniel Theophanes <kardianos@gmail.com>
Thu, 16 Nov 2017 22:36:07 +0000 (22:36 +0000)
While driver.Connector was previously added to allow non-string
connection arguments and access to the context, most users of
the sql package will continue to rely on a string DSN.

Allow drivers to implement a string DSN to Connector interface
that both allows a single parsing of the string DSN and uses
the Connector interface which passes available context to
the driver dialer.

Fixes #22713

Change-Id: Ia0b862262f4c4670effe2538d0d6d43733fea18d
Reviewed-on: https://go-review.googlesource.com/77550
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@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 b3f9d9c26c35c0af0579bc61fa4a4979521eb435..b9bf19c04d80599d82387e94bdd10ccbdcfa010d 100644 (file)
@@ -55,6 +55,17 @@ type Driver interface {
        Open(name string) (Conn, error)
 }
 
+// DriverContext enhances the Driver interface by returning a Connector
+// rather then a single Conn.
+// It separates out the name parsing step from actually connecting to the
+// database. It also gives dialers access to the context by using the
+// Connector.
+type DriverContext interface {
+       // OpenConnector must parse the name in the same format that Driver.Open
+       // parses the name parameter.
+       OpenConnector(name string) (Connector, error)
+}
+
 // Connector is an optional interface that drivers can implement.
 // It allows drivers to provide more flexible methods to open
 // database connections without requiring the use of a DSN string.
index 31e22a7a74343ad60868f136cc5d62955b969811..e795412de01c97c7cc4faf2d6d3cbe106713375a 100644 (file)
@@ -71,6 +71,16 @@ func (c *fakeConnector) Driver() driver.Driver {
        return fdriver
 }
 
+type fakeDriverCtx struct {
+       fakeDriver
+}
+
+var _ driver.DriverContext = &fakeDriverCtx{}
+
+func (cc *fakeDriverCtx) OpenConnector(name string) (driver.Connector, error) {
+       return &fakeConnector{name: name}, nil
+}
+
 type fakeDB struct {
        name string
 
index 30b4ad36093737fb2dca87c280124576ef4f1e01..1192eaae2606e7fe6330aa8d0eea1ee7e0d1a18d 100644 (file)
@@ -662,6 +662,14 @@ func Open(driverName, dataSourceName string) (*DB, error) {
                return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
        }
 
+       if driverCtx, ok := driveri.(driver.DriverContext); ok {
+               connector, err := driverCtx.OpenConnector(dataSourceName)
+               if err != nil {
+                       return nil, err
+               }
+               return OpenDB(connector), nil
+       }
+
        return OpenDB(dsnConnector{dsn: dataSourceName, driver: driveri}), nil
 }
 
index f7b7d988e1b80b9e0c579e235c9945c405ab3cd2..8137eff82b4ae1511bb63b11de4ff41e90b54b90 100644 (file)
@@ -3523,6 +3523,19 @@ func TestNamedValueCheckerSkip(t *testing.T) {
        }
 }
 
+func TestOpenConnector(t *testing.T) {
+       Register("testctx", &fakeDriverCtx{})
+       db, err := Open("testctx", "people")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer db.Close()
+
+       if _, is := db.connector.(*fakeConnector); !is {
+               t.Fatal("not using *fakeConnector")
+       }
+}
+
 type ctxOnlyDriver struct {
        fakeDriver
 }