diff --git a/sql/driver/driver.go b/sql/driver/driver.go index 26af9fb26..d7d9cb6c3 100644 --- a/sql/driver/driver.go +++ b/sql/driver/driver.go @@ -6,6 +6,7 @@ import ( "database/sql/driver" "errors" "io" + "runtime" "sync" "github.com/genjidb/genji" @@ -20,58 +21,68 @@ func init() { sql.Register("genji", sqlDriver{}) } +var ( + _ driver.Driver = (*sqlDriver)(nil) + _ driver.DriverContext = (*sqlDriver)(nil) +) + // sqlDriver is a driver.Driver that can open a new connection to a Genji database. // It is the driver used to register Genji against the database/sql package. type sqlDriver struct{} func (d sqlDriver) Open(name string) (driver.Conn, error) { + return nil, errors.New("requires go1.10 or greater") +} + +func (d sqlDriver) OpenConnector(name string) (driver.Connector, error) { db, err := genji.Open(name) if err != nil { return nil, err } - return &conn{db: db}, nil -} - -// proxyDriver is used to turn an existing DB into a driver.Driver. -type proxyDriver struct { - db *genji.DB -} - -func newDriver(db *genji.DB) driver.Driver { - return proxyDriver{ - db: db, + c := &connector{ + db: db, + driver: d, } -} + runtime.SetFinalizer(c, (*connector).Close) -func (d proxyDriver) Open(name string) (driver.Conn, error) { - return &conn{db: d.db}, nil + return c, nil } -type proxyConnector struct { +var ( + _ driver.Connector = (*connector)(nil) + _ io.Closer = (*connector)(nil) +) + +type connector struct { driver driver.Driver -} -func newProxyConnector(db *genji.DB) driver.Connector { - return proxyConnector{ - driver: newDriver(db), - } + db *genji.DB + + closeOnce sync.Once } -func (c proxyConnector) Connect(ctx context.Context) (driver.Conn, error) { - return c.driver.Open("") +func (c *connector) Connect(ctx context.Context) (driver.Conn, error) { + return &conn{db: c.db}, nil } -func (c proxyConnector) Driver() driver.Driver { +func (c *connector) Driver() driver.Driver { return c.driver } +func (c *connector) Close() error { + var err error + c.closeOnce.Do(func() { + err = c.db.Close() + }) + return err +} + // conn represents a connection to the Genji database. // It implements the database/sql/driver.Conn interface. type conn struct { - db *genji.DB - tx *genji.Tx - nonPromotable bool + db *genji.DB + tx *genji.Tx } // Prepare returns a prepared statement, bound to this connection.