@@ -317,8 +317,7 @@ var ErrNoRows = errors.New("sql: no rows in result set")
317
317
// connection is returned to DB's idle connection pool. The pool size
318
318
// can be controlled with SetMaxIdleConns.
319
319
type DB struct {
320
- driver driver.Driver
321
- dsn string
320
+ connector driver.Connector
322
321
// numClosed is an atomic counter which represents a total number of
323
322
// closed connections. Stmt.openStmt checks it before cleaning closed
324
323
// connections in Stmt.css.
@@ -575,6 +574,48 @@ func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {
575
574
// to block until the connectionOpener can satisfy the backlog of requests.
576
575
var connectionRequestQueueSize = 1000000
577
576
577
+ type dsnConnector struct {
578
+ dsn string
579
+ driver driver.Driver
580
+ }
581
+
582
+ func (t dsnConnector ) Connect (_ context.Context ) (driver.Conn , error ) {
583
+ return t .driver .Open (t .dsn )
584
+ }
585
+
586
+ func (t dsnConnector ) Driver () driver.Driver {
587
+ return t .driver
588
+ }
589
+
590
+ // OpenDB opens a database using a Connector, allowing drivers to
591
+ // bypass a string based data source name.
592
+ //
593
+ // Most users will open a database via a driver-specific connection
594
+ // helper function that returns a *DB. No database drivers are included
595
+ // in the Go standard library. See https://golang.org/s/sqldrivers for
596
+ // a list of third-party drivers.
597
+ //
598
+ // OpenDB may just validate its arguments without creating a connection
599
+ // to the database. To verify that the data source name is valid, call
600
+ // Ping.
601
+ //
602
+ // The returned DB is safe for concurrent use by multiple goroutines
603
+ // and maintains its own pool of idle connections. Thus, the OpenDB
604
+ // function should be called just once. It is rarely necessary to
605
+ // close a DB.
606
+ func OpenDB (c driver.Connector ) * DB {
607
+ db := & DB {
608
+ connector : c ,
609
+ openerCh : make (chan struct {}, connectionRequestQueueSize ),
610
+ lastPut : make (map [* driverConn ]string ),
611
+ connRequests : make (map [uint64 ]chan connRequest ),
612
+ }
613
+
614
+ go db .connectionOpener ()
615
+
616
+ return db
617
+ }
618
+
578
619
// Open opens a database specified by its database driver name and a
579
620
// driver-specific data source name, usually consisting of at least a
580
621
// database name and connection information.
@@ -599,15 +640,8 @@ func Open(driverName, dataSourceName string) (*DB, error) {
599
640
if ! ok {
600
641
return nil , fmt .Errorf ("sql: unknown driver %q (forgotten import?)" , driverName )
601
642
}
602
- db := & DB {
603
- driver : driveri ,
604
- dsn : dataSourceName ,
605
- openerCh : make (chan struct {}, connectionRequestQueueSize ),
606
- lastPut : make (map [* driverConn ]string ),
607
- connRequests : make (map [uint64 ]chan connRequest ),
608
- }
609
- go db .connectionOpener ()
610
- return db , nil
643
+
644
+ return OpenDB (dsnConnector {dsn : dataSourceName , driver : driveri }), nil
611
645
}
612
646
613
647
func (db * DB ) pingDC (ctx context.Context , dc * driverConn , release func (error )) error {
@@ -878,7 +912,7 @@ func (db *DB) openNewConnection() {
878
912
// maybeOpenNewConnctions has already executed db.numOpen++ before it sent
879
913
// on db.openerCh. This function must execute db.numOpen-- if the
880
914
// connection fails or is closed before returning.
881
- ci , err := db .driver . Open ( db . dsn )
915
+ ci , err := db .connector . Connect ( context . Background () )
882
916
db .mu .Lock ()
883
917
defer db .mu .Unlock ()
884
918
if db .closed {
@@ -996,7 +1030,7 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn
996
1030
997
1031
db .numOpen ++ // optimistically
998
1032
db .mu .Unlock ()
999
- ci , err := db .driver . Open ( db . dsn )
1033
+ ci , err := db .connector . Connect ( ctx )
1000
1034
if err != nil {
1001
1035
db .mu .Lock ()
1002
1036
db .numOpen -- // correct for earlier optimism
@@ -1454,7 +1488,7 @@ func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error),
1454
1488
1455
1489
// Driver returns the database's underlying driver.
1456
1490
func (db * DB ) Driver () driver.Driver {
1457
- return db .driver
1491
+ return db .connector . Driver ()
1458
1492
}
1459
1493
1460
1494
// ErrConnDone is returned by any operation that is performed on a connection
0 commit comments