1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:17:56 -07:00

database/sql: fix typo bug resulting in double-Prepare

Bug reported by Blake Mizerany found while writing
his new Postgres driver.

R=golang-dev, blake.mizerany
CC=golang-dev
https://golang.org/cl/5754057
This commit is contained in:
Brad Fitzpatrick 2012-03-06 14:10:58 -08:00
parent 97b13acb67
commit 48eacd90a8
3 changed files with 17 additions and 2 deletions

View File

@ -82,6 +82,7 @@ type fakeConn struct {
mu sync.Mutex mu sync.Mutex
stmtsMade int stmtsMade int
stmtsClosed int stmtsClosed int
numPrepare int
} }
func (c *fakeConn) incrStat(v *int) { func (c *fakeConn) incrStat(v *int) {
@ -339,6 +340,7 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e
} }
func (c *fakeConn) Prepare(query string) (driver.Stmt, error) { func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
c.numPrepare++
if c.db == nil { if c.db == nil {
panic("nil c.db; conn = " + fmt.Sprintf("%#v", c)) panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
} }

View File

@ -700,7 +700,7 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, e
for _, v := range s.css { for _, v := range s.css {
// TODO(bradfitz): lazily clean up entries in this // TODO(bradfitz): lazily clean up entries in this
// list with dead conns while enumerating // list with dead conns while enumerating
if _, match = s.db.connIfFree(cs.ci); match { if _, match = s.db.connIfFree(v.ci); match {
cs = v cs = v
break break
} }

View File

@ -47,9 +47,19 @@ func closeDB(t *testing.T, db *DB) {
} }
} }
// numPrepares assumes that db has exactly 1 idle conn and returns
// its count of calls to Prepare
func numPrepares(t *testing.T, db *DB) int {
if n := len(db.freeConn); n != 1 {
t.Fatalf("free conns = %d; want 1", n)
}
return db.freeConn[0].(*fakeConn).numPrepare
}
func TestQuery(t *testing.T) { func TestQuery(t *testing.T) {
db := newTestDB(t, "people") db := newTestDB(t, "people")
defer closeDB(t, db) defer closeDB(t, db)
prepares0 := numPrepares(t, db)
rows, err := db.Query("SELECT|people|age,name|") rows, err := db.Query("SELECT|people|age,name|")
if err != nil { if err != nil {
t.Fatalf("Query: %v", err) t.Fatalf("Query: %v", err)
@ -83,7 +93,10 @@ func TestQuery(t *testing.T) {
// And verify that the final rows.Next() call, which hit EOF, // And verify that the final rows.Next() call, which hit EOF,
// also closed the rows connection. // also closed the rows connection.
if n := len(db.freeConn); n != 1 { if n := len(db.freeConn); n != 1 {
t.Errorf("free conns after query hitting EOF = %d; want 1", n) t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
}
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
t.Errorf("executed %d Prepare statements; want 1", prepares)
} }
} }