-
Notifications
You must be signed in to change notification settings - Fork 18k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
database/sql: must call (*driver.Stmt).Close before correspondent (*driver.Conn).Close #5046
Labels
Comments
I don't think we should document every guarantee we DON'T make. We document the guarantees we DO make. You _can_ reproduce this in a test in the standard library with the fakeDB in fakedb_test.go. Just make it log calls to a public slice of events, and have a test which clears that slice, does some actions (open + prepare + exec + close + whatever), and then stringify the slice of events, looking for the right order. Now that we have the dependency track stuff, this should be easy to "fix" (or start guaranteeing) if you can write a stand-alone test. You don't have much time, though. |
Had to put panic in fakedb_test.go, because you ignore the error it returns. diff -r 0c029965805f src/pkg/database/sql/fakedb_test.go --- a/src/pkg/database/sql/fakedb_test.go Thu Mar 14 15:01:45 2013 -0700 +++ b/src/pkg/database/sql/fakedb_test.go Fri Mar 15 11:43:14 2013 +1100 @@ -237,7 +237,7 @@ return errors.New("can't close fakeConn; already closed") } if c.stmtsMade > c.stmtsClosed { - return errors.New("can't close; dangling statement(s)") + panic(errors.New("can't close; dangling statement(s)")) } c.db = nil return nil diff -r 0c029965805f src/pkg/database/sql/sql_test.go --- a/src/pkg/database/sql/sql_test.go Thu Mar 14 15:01:45 2013 -0700 +++ b/src/pkg/database/sql/sql_test.go Fri Mar 15 11:43:14 2013 +1100 @@ -736,3 +736,61 @@ t.Logf("stmt = %#v", stmt) } } + +func TestCloseConnBeforeStmts(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + stmt, err := db.Prepare("SELECT|people|name|") + if err != nil { + t.Fatal(err) + } + defer stmt.Close() + + eof := fmt.Errorf("eof") + query := func(ch chan error) (err2 error) { + defer func() { + ch <- err2 + }() + ch <- nil // wait for other goroutines + r, err := stmt.Query() + if err != nil { + return fmt.Errorf("%v", err) + } + defer r.Close() + i := 0 + ch <- nil // wait for other goroutines + for r.Next() { + ch <- nil // wait for other goroutines + var is string + err = r.Scan(&is) + if err != nil { + return fmt.Errorf("%v", err) + } + ch <- nil // wait for other goroutines + i++ + } + err = r.Err() + if err != nil { + return fmt.Errorf("%v", err) + } + return eof + } + + chs := make(map[int]chan error) + for i := 0; i < 3; i++ { + chs[i] = make(chan error) + go query(chs[i]) + } + for len(chs) > 0 { + for i, ch := range chs { + err := <-ch + if err != nil { + if err != eof { + t.Errorf("goroutine #%d failed: %v", i, err) + } + delete(chs, i) + } + } + } +} |
Mailed https://golang.org/cl/8016044 Status changed to Started. |
This issue was closed by revision 209f6b1. Status changed to Fixed. |
This issue was closed.
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
The text was updated successfully, but these errors were encountered: