Issue 1:
by john.corbett:

What steps will reproduce the problem?

Try to look up go, or any other stop word in a search engine.
Notice the results are garbage.

Please provide any additional information below.

Please do not name your thing after a common term or a term already
strongly associated with something else. Even if you succeed in displacing
a established meaning, you don't win--you just offend people.

Other examples of dumb names, in case you need to be hit over the head with
it: C, C++, X, widget, R, S, NeXT, and processing. I'm sure that now that
you have the idea you can generate more bad names yourself, but please don't.

Thanks,
John

Issue 2:
go version go1.4.2 windows/amd64

This issue was originally discovered while using github.com/alexbrainman/odbc, but it does not seem to be a problem specific to that driver. It is minimally reproducible with the below test program.

The program runs a query inside a transaction five times. The commit (or rollback) of the second attempt returns driver.ErrBadConn.

I expect the bad connection to get removed from the pool and subsequent transactions to occur on a fresh connection.

Instead database/sql keeps the bad connection in the pool and subsequent transactions reuse the bad connection and also fail.

package main

import (
"database/sql"
"database/sql/driver"
"log"
"reflect"
"runtime"
)

var opened, closed int

type MockDriver struct{}

func (d *MockDriver) Open(name string) (driver.Conn, error) {
opened++
return &MockConn{}, NextError()
}

type MockConn struct{ err error }

// NOTE: that this always succeeds, even if c.err != nil this simulates a
// driver that doesn't need to communicate the beginning of a transaction and
// therefore may not be able to discover a bad connection at this point.
func (c *MockConn) Begin() (driver.Tx, error) { return &MockTx{c}, nil }

func (c *MockConn) Close() error { closed++; return c.Err() }
func (c *MockConn) Prepare(query string) (driver.Stmt, error) { return &MockStmt{c}, c.Err() }
func (c *MockConn) Err() error {
if c.err == nil {
c.err = NextError()
}
return c.err
}

type MockTx struct{ c *MockConn }

func (tx *MockTx) Commit() error { return tx.c.Err() }
func (tx *MockTx) Rollback() error { return tx.c.Err() }

type MockStmt struct{ c *MockConn }

func (s *MockStmt) Close() error { return s.c.Err() }
func (s *MockStmt) NumInput() int { return -1 }
func (s *MockStmt) Exec(args []driver.Value) (driver.Result, error) {
return driver.ResultNoRows, s.c.Err()
}
func (s *MockStmt) Query(args []driver.Value) (driver.Rows, error) { return &MockRows{s}, s.c.Err() }

type MockRows struct{ s *MockStmt }

func (r *MockRows) Columns() []string { return []string{} }
func (r *MockRows) Close() error { return r.s.c.Err() }
func (r *MockRows) Next(dest []driver.Value) error { return r.s.c.Err() }

var nextError error

func NextError() (err error) {
err, nextError = nextError, nil
return
}

func main() {
drv := &MockDriver{}
sql.Register("mock", drv)
db, err := sql.Open("mock", "")
checkErr(0, err, nil)
for i := 0; i < 5; i++ {
// this always succeeds because that's the way some drivers may work
tx, err := db.Begin()
checkErr(i, err, nil)
if err != nil {
continue
}
rows, err := tx.Query("query")
checkErr(i, err, nil)
if err != nil {
err = tx.Rollback()
checkErr(i, err, nil)
continue
}
rows.Close()
var want error
if i == 1 {
nextError, want = driver.ErrBadConn, driver.ErrBadConn
}
// fails when i == 1, but the connection is not removed from the pool
err = tx.Commit()
checkErr(i, err, want)
log.Printf("i(%d), opened: %d, closed: %d", i, opened, closed)
}
log.Printf("final, opened: %d, closed: %d", opened, closed)
}

func checkErr(i int, got, want error) {
if !reflect.DeepEqual(got, want) {
_, _, line, _ := runtime.Caller(1)
log.Printf("i(%d), line %d: got %v, want %v", i, line, got, want)
}
}