Commit 4435c8bf authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

exp/sql: close Rows on EOF

Fixes #2624

R=rsc
CC=golang-dev
https://golang.org/cl/5530068
parent 25cf9bde
...@@ -110,25 +110,34 @@ func init() { ...@@ -110,25 +110,34 @@ func init() {
// Supports dsn forms: // Supports dsn forms:
// <dbname> // <dbname>
// <dbname>;wipe // <dbname>;<opts> (no currently supported options)
func (d *fakeDriver) Open(dsn string) (driver.Conn, error) { func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
d.mu.Lock()
defer d.mu.Unlock()
d.openCount++
if d.dbs == nil {
d.dbs = make(map[string]*fakeDB)
}
parts := strings.Split(dsn, ";") parts := strings.Split(dsn, ";")
if len(parts) < 1 { if len(parts) < 1 {
return nil, errors.New("fakedb: no database name") return nil, errors.New("fakedb: no database name")
} }
name := parts[0] name := parts[0]
db := d.getDB(name)
d.mu.Lock()
d.openCount++
d.mu.Unlock()
return &fakeConn{db: db}, nil
}
func (d *fakeDriver) getDB(name string) *fakeDB {
d.mu.Lock()
defer d.mu.Unlock()
if d.dbs == nil {
d.dbs = make(map[string]*fakeDB)
}
db, ok := d.dbs[name] db, ok := d.dbs[name]
if !ok { if !ok {
db = &fakeDB{name: name} db = &fakeDB{name: name}
d.dbs[name] = db d.dbs[name] = db
} }
return &fakeConn{db: db}, nil return db
} }
func (db *fakeDB) wipe() { func (db *fakeDB) wipe() {
......
...@@ -549,8 +549,8 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) { ...@@ -549,8 +549,8 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
// statement, a function to call to release the connection, and a // statement, a function to call to release the connection, and a
// statement bound to that connection. // statement bound to that connection.
func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, err error) { func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, err error) {
if s.stickyErr != nil { if err = s.stickyErr; err != nil {
return nil, nil, nil, s.stickyErr return
} }
s.mu.Lock() s.mu.Lock()
if s.closed { if s.closed {
...@@ -726,6 +726,9 @@ func (rs *Rows) Next() bool { ...@@ -726,6 +726,9 @@ func (rs *Rows) Next() bool {
rs.lastcols = make([]interface{}, len(rs.rowsi.Columns())) rs.lastcols = make([]interface{}, len(rs.rowsi.Columns()))
} }
rs.lasterr = rs.rowsi.Next(rs.lastcols) rs.lasterr = rs.rowsi.Next(rs.lastcols)
if rs.lasterr == io.EOF {
rs.Close()
}
return rs.lasterr == nil return rs.lasterr == nil
} }
......
...@@ -10,8 +10,10 @@ import ( ...@@ -10,8 +10,10 @@ import (
"testing" "testing"
) )
const fakeDBName = "foo"
func newTestDB(t *testing.T, name string) *DB { func newTestDB(t *testing.T, name string) *DB {
db, err := Open("test", "foo") db, err := Open("test", fakeDBName)
if err != nil { if err != nil {
t.Fatalf("Open: %v", err) t.Fatalf("Open: %v", err)
} }
...@@ -73,6 +75,12 @@ func TestQuery(t *testing.T) { ...@@ -73,6 +75,12 @@ func TestQuery(t *testing.T) {
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Logf(" got: %#v\nwant: %#v", got, want) t.Logf(" got: %#v\nwant: %#v", got, want)
} }
// And verify that the final rows.Next() call, which hit EOF,
// also closed the rows connection.
if n := len(db.freeConn); n != 1 {
t.Errorf("free conns after query hitting EOF = %d; want 1", n)
}
} }
func TestRowsColumns(t *testing.T) { func TestRowsColumns(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment