Skip to content

Commit

Permalink
Add support for database/sql Connector and OpenDB (#749)
Browse files Browse the repository at this point in the history
* Add support for database/sql Connector and OpenDB

What
===
Add support for `database/sql/driver` `Connector` and `database/sql`
`OpenDB` that were added in go1.10.

Why
===
To allow users to open a connection without using the registered drivers
interface, and instead explicitly getting a `Connector` from the this
driver and passing that connector to `database/sql` `OpenDB`.

Notes
===
- The new types and functions are only built for go1.10 or newer because
the `database/sql/driver` `Connector` interface and `database/sql`
`OpenDB` function are only available in go1.10 or later.
- The `NewConnector` has support for context, but the context isn't used
at this point. Use of it could be added if desired, but that could occur
separately to this change.
  • Loading branch information
leighmcculloch authored and maddyblue committed May 23, 2018
1 parent d34b9ff commit 0677bdd
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
43 changes: 43 additions & 0 deletions connector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// +build go1.10

package pq

import (
"context"
"database/sql/driver"
)

// Connector represents a fixed configuration for the pq driver with a given
// name. Connector satisfies the database/sql/driver Connector interface and
// can be used to create any number of DB Conn's via the database/sql OpenDB
// function.
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
type connector struct {
name string
}

// Connect returns a connection to the database using the fixed configuration
// of this Connector. Context is not used.
func (c *connector) Connect(_ context.Context) (driver.Conn, error) {
return (&Driver{}).Open(c.name)
}

// Driver returnst the underlying driver of this Connector.
func (c *connector) Driver() driver.Driver {
return &Driver{}
}

var _ driver.Connector = &connector{}

// NewConnector returns a connector for the pq driver in a fixed configuration
// with the given name. The returned connector can be used to create any number
// of equivalent Conn's. The returned connector is intended to be used with
// database/sql.OpenDB.
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
func NewConnector(name string) (driver.Connector, error) {
return &connector{name: name}, nil
}
33 changes: 33 additions & 0 deletions connector_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// +build go1.10

package pq_test

import (
"database/sql"
"fmt"

"github.com/lib/pq"
)

func ExampleNewConnector() {
name := ""
connector, err := pq.NewConnector(name)
if err != nil {
fmt.Println(err)
return
}
db := sql.OpenDB(connector)
if err != nil {
fmt.Println(err)
return
}
defer db.Close()

// Use the DB
txn, err := db.Begin()
if err != nil {
fmt.Println(err)
return
}
txn.Rollback()
}
67 changes: 67 additions & 0 deletions connector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// +build go1.10

package pq

import (
"context"
"database/sql"
"database/sql/driver"
"testing"
)

func TestNewConnector_WorksWithOpenDB(t *testing.T) {
name := ""
c, err := NewConnector(name)
if err != nil {
t.Fatal(err)
}
db := sql.OpenDB(c)
defer db.Close()
// database/sql might not call our Open at all unless we do something with
// the connection
txn, err := db.Begin()
if err != nil {
t.Fatal(err)
}
txn.Rollback()
}

func TestNewConnector_Connect(t *testing.T) {
name := ""
c, err := NewConnector(name)
if err != nil {
t.Fatal(err)
}
db, err := c.Connect(context.Background())
if err != nil {
t.Fatal(err)
}
defer db.Close()
// database/sql might not call our Open at all unless we do something with
// the connection
txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{})
if err != nil {
t.Fatal(err)
}
txn.Rollback()
}

func TestNewConnector_Driver(t *testing.T) {
name := ""
c, err := NewConnector(name)
if err != nil {
t.Fatal(err)
}
db, err := c.Driver().Open(name)
if err != nil {
t.Fatal(err)
}
defer db.Close()
// database/sql might not call our Open at all unless we do something with
// the connection
txn, err := db.(driver.ConnBeginTx).BeginTx(context.Background(), driver.TxOptions{})
if err != nil {
t.Fatal(err)
}
txn.Rollback()
}

0 comments on commit 0677bdd

Please sign in to comment.