diff options
Diffstat (limited to 'src/database/sql/sql.go')
| -rw-r--r-- | src/database/sql/sql.go | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index 27adf69122..5c5b7dc7e9 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -1792,6 +1792,8 @@ type Conn struct { done int32 } +// grabConn takes a context to implement stmtConnGrabber +// but the context is not used. func (c *Conn) grabConn(context.Context) (*driverConn, releaseConn, error) { if atomic.LoadInt32(&c.done) != 0 { return nil, nil, ErrConnDone @@ -1856,6 +1858,39 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) return c.db.prepareDC(ctx, dc, release, c, query) } +// Raw executes f exposing the underlying driver connection for the +// duration of f. The driverConn must not be used outside of f. +// +// Once f returns and err is nil, the Conn will continue to be usable +// until Conn.Close is called. +func (c *Conn) Raw(f func(driverConn interface{}) error) (err error) { + var dc *driverConn + var release releaseConn + + // grabConn takes a context to implement stmtConnGrabber, but the context is not used. + dc, release, err = c.grabConn(nil) + if err != nil { + return + } + fPanic := true + dc.Mutex.Lock() + defer func() { + dc.Mutex.Unlock() + + // If f panics fPanic will remain true. + // Ensure an error is passed to release so the connection + // may be discarded. + if fPanic { + err = driver.ErrBadConn + } + release(err) + }() + err = f(dc.ci) + fPanic = false + + return +} + // BeginTx starts a transaction. // // The provided context is used until the transaction is committed or rolled back. |
