// Supports dsn forms:
// <dbname>
-// <dbname>;wipe
+// <dbname>;<opts> (no currently supported options)
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, ";")
if len(parts) < 1 {
return nil, errors.New("fakedb: no database name")
}
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]
if !ok {
db = &fakeDB{name: name}
d.dbs[name] = db
}
- return &fakeConn{db: db}, nil
+ return db
}
func (db *fakeDB) wipe() {
// statement, a function to call to release the connection, and a
// statement bound to that connection.
func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, err error) {
- if s.stickyErr != nil {
- return nil, nil, nil, s.stickyErr
+ if err = s.stickyErr; err != nil {
+ return
}
s.mu.Lock()
if s.closed {
rs.lastcols = make([]interface{}, len(rs.rowsi.Columns()))
}
rs.lasterr = rs.rowsi.Next(rs.lastcols)
+ if rs.lasterr == io.EOF {
+ rs.Close()
+ }
return rs.lasterr == nil
}
"testing"
)
+const fakeDBName = "foo"
+
func newTestDB(t *testing.T, name string) *DB {
- db, err := Open("test", "foo")
+ db, err := Open("test", fakeDBName)
if err != nil {
t.Fatalf("Open: %v", err)
}
if !reflect.DeepEqual(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) {