summaryrefslogtreecommitdiff
path: root/src/pkg/database/sql/fakedb_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/database/sql/fakedb_test.go')
-rw-r--r--src/pkg/database/sql/fakedb_test.go50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/pkg/database/sql/fakedb_test.go b/src/pkg/database/sql/fakedb_test.go
index d900e2ceb..a8adfdd94 100644
--- a/src/pkg/database/sql/fakedb_test.go
+++ b/src/pkg/database/sql/fakedb_test.go
@@ -38,6 +38,8 @@ type fakeDriver struct {
mu sync.Mutex // guards 3 following fields
openCount int // conn opens
closeCount int // conn closes
+ waitCh chan struct{}
+ waitingCh chan struct{}
dbs map[string]*fakeDB
}
@@ -146,6 +148,12 @@ func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
if len(parts) >= 2 && parts[1] == "badConn" {
conn.bad = true
}
+ if d.waitCh != nil {
+ d.waitingCh <- struct{}{}
+ <-d.waitCh
+ d.waitCh = nil
+ d.waitingCh = nil
+ }
return conn, nil
}
@@ -447,6 +455,10 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
return c.prepareCreate(stmt, parts)
case "INSERT":
return c.prepareInsert(stmt, parts)
+ case "NOSERT":
+ // Do all the prep-work like for an INSERT but don't actually insert the row.
+ // Used for some of the concurrent tests.
+ return c.prepareInsert(stmt, parts)
default:
stmt.Close()
return nil, errf("unsupported command type %q", cmd)
@@ -497,13 +509,20 @@ func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
}
return driver.ResultNoRows, nil
case "INSERT":
- return s.execInsert(args)
+ return s.execInsert(args, true)
+ case "NOSERT":
+ // Do all the prep-work like for an INSERT but don't actually insert the row.
+ // Used for some of the concurrent tests.
+ return s.execInsert(args, false)
}
fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s)
return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd)
}
-func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
+// When doInsert is true, add the row to the table.
+// When doInsert is false do prep-work and error checking, but don't
+// actually add the row to the table.
+func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result, error) {
db := s.c.db
if len(args) != s.placeholders {
panic("error in pkg db; should only get here if size is correct")
@@ -518,7 +537,10 @@ func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
t.mu.Lock()
defer t.mu.Unlock()
- cols := make([]interface{}, len(t.colname))
+ var cols []interface{}
+ if doInsert {
+ cols = make([]interface{}, len(t.colname))
+ }
argPos := 0
for n, colname := range s.colName {
colidx := t.columnIndex(colname)
@@ -532,10 +554,14 @@ func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
} else {
val = s.colValue[n]
}
- cols[colidx] = val
+ if doInsert {
+ cols[colidx] = val
+ }
}
- t.rows = append(t.rows, &row{cols: cols})
+ if doInsert {
+ t.rows = append(t.rows, &row{cols: cols})
+ }
return driver.RowsAffected(1), nil
}
@@ -608,9 +634,10 @@ rows:
}
cursor := &rowsCursor{
- pos: -1,
- rows: mrows,
- cols: s.colName,
+ pos: -1,
+ rows: mrows,
+ cols: s.colName,
+ errPos: -1,
}
return cursor, nil
}
@@ -635,6 +662,10 @@ type rowsCursor struct {
rows []*row
closed bool
+ // errPos and err are for making Next return early with error.
+ errPos int
+ err error
+
// a clone of slices to give out to clients, indexed by the
// the original slice's first byte address. we clone them
// just so we're able to corrupt them on close.
@@ -660,6 +691,9 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
return errors.New("fakedb: cursor is closed")
}
rc.pos++
+ if rc.pos == rc.errPos {
+ return rc.err
+ }
if rc.pos >= len(rc.rows) {
return io.EOF // per interface spec
}