github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/database/sql/sql_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sql 6 7 import ( 8 "database/sql/driver" 9 "errors" 10 "fmt" 11 "math/rand" 12 "reflect" 13 "runtime" 14 "strings" 15 "sync" 16 "testing" 17 "time" 18 ) 19 20 func init() { 21 type dbConn struct { 22 db *DB 23 c *driverConn 24 } 25 freedFrom := make(map[dbConn]string) 26 putConnHook = func(db *DB, c *driverConn) { 27 idx := -1 28 for i, v := range db.freeConn { 29 if v == c { 30 idx = i 31 break 32 } 33 } 34 if idx >= 0 { 35 // print before panic, as panic may get lost due to conflicting panic 36 // (all goroutines asleep) elsewhere, since we might not unlock 37 // the mutex in freeConn here. 38 println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack()) 39 panic("double free of conn.") 40 } 41 freedFrom[dbConn{db, c}] = stack() 42 } 43 } 44 45 const fakeDBName = "foo" 46 47 var chrisBirthday = time.Unix(123456789, 0) 48 49 func newTestDB(t testing.TB, name string) *DB { 50 db, err := Open("test", fakeDBName) 51 if err != nil { 52 t.Fatalf("Open: %v", err) 53 } 54 if _, err := db.Exec("WIPE"); err != nil { 55 t.Fatalf("exec wipe: %v", err) 56 } 57 if name == "people" { 58 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime") 59 exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1) 60 exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2) 61 exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 62 } 63 if name == "magicquery" { 64 // Magic table name and column, known by fakedb_test.go. 65 exec(t, db, "CREATE|magicquery|op=string,millis=int32") 66 exec(t, db, "INSERT|magicquery|op=sleep,millis=10") 67 } 68 return db 69 } 70 71 func exec(t testing.TB, db *DB, query string, args ...interface{}) { 72 _, err := db.Exec(query, args...) 73 if err != nil { 74 t.Fatalf("Exec of %q: %v", query, err) 75 } 76 } 77 78 func closeDB(t testing.TB, db *DB) { 79 if e := recover(); e != nil { 80 fmt.Printf("Panic: %v\n", e) 81 panic(e) 82 } 83 defer setHookpostCloseConn(nil) 84 setHookpostCloseConn(func(_ *fakeConn, err error) { 85 if err != nil { 86 t.Errorf("Error closing fakeConn: %v", err) 87 } 88 }) 89 for i, dc := range db.freeConn { 90 if n := len(dc.openStmt); n > 0 { 91 // Just a sanity check. This is legal in 92 // general, but if we make the tests clean up 93 // their statements first, then we can safely 94 // verify this is always zero here, and any 95 // other value is a leak. 96 t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n) 97 } 98 } 99 err := db.Close() 100 if err != nil { 101 t.Fatalf("error closing DB: %v", err) 102 } 103 db.mu.Lock() 104 count := db.numOpen 105 db.mu.Unlock() 106 if count != 0 { 107 t.Fatalf("%d connections still open after closing DB", db.numOpen) 108 } 109 } 110 111 // numPrepares assumes that db has exactly 1 idle conn and returns 112 // its count of calls to Prepare 113 func numPrepares(t *testing.T, db *DB) int { 114 if n := len(db.freeConn); n != 1 { 115 t.Fatalf("free conns = %d; want 1", n) 116 } 117 return db.freeConn[0].ci.(*fakeConn).numPrepare 118 } 119 120 func (db *DB) numDeps() int { 121 db.mu.Lock() 122 defer db.mu.Unlock() 123 return len(db.dep) 124 } 125 126 // Dependencies are closed via a goroutine, so this polls waiting for 127 // numDeps to fall to want, waiting up to d. 128 func (db *DB) numDepsPollUntil(want int, d time.Duration) int { 129 deadline := time.Now().Add(d) 130 for { 131 n := db.numDeps() 132 if n <= want || time.Now().After(deadline) { 133 return n 134 } 135 time.Sleep(50 * time.Millisecond) 136 } 137 } 138 139 func (db *DB) numFreeConns() int { 140 db.mu.Lock() 141 defer db.mu.Unlock() 142 return len(db.freeConn) 143 } 144 145 func (db *DB) dumpDeps(t *testing.T) { 146 for fc := range db.dep { 147 db.dumpDep(t, 0, fc, map[finalCloser]bool{}) 148 } 149 } 150 151 func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) { 152 seen[dep] = true 153 indent := strings.Repeat(" ", depth) 154 ds := db.dep[dep] 155 for k := range ds { 156 t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k) 157 if fc, ok := k.(finalCloser); ok { 158 if !seen[fc] { 159 db.dumpDep(t, depth+1, fc, seen) 160 } 161 } 162 } 163 } 164 165 func TestQuery(t *testing.T) { 166 db := newTestDB(t, "people") 167 defer closeDB(t, db) 168 prepares0 := numPrepares(t, db) 169 rows, err := db.Query("SELECT|people|age,name|") 170 if err != nil { 171 t.Fatalf("Query: %v", err) 172 } 173 type row struct { 174 age int 175 name string 176 } 177 got := []row{} 178 for rows.Next() { 179 var r row 180 err = rows.Scan(&r.age, &r.name) 181 if err != nil { 182 t.Fatalf("Scan: %v", err) 183 } 184 got = append(got, r) 185 } 186 err = rows.Err() 187 if err != nil { 188 t.Fatalf("Err: %v", err) 189 } 190 want := []row{ 191 {age: 1, name: "Alice"}, 192 {age: 2, name: "Bob"}, 193 {age: 3, name: "Chris"}, 194 } 195 if !reflect.DeepEqual(got, want) { 196 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 197 } 198 199 // And verify that the final rows.Next() call, which hit EOF, 200 // also closed the rows connection. 201 if n := db.numFreeConns(); n != 1 { 202 t.Fatalf("free conns after query hitting EOF = %d; want 1", n) 203 } 204 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 205 t.Errorf("executed %d Prepare statements; want 1", prepares) 206 } 207 } 208 209 func TestByteOwnership(t *testing.T) { 210 db := newTestDB(t, "people") 211 defer closeDB(t, db) 212 rows, err := db.Query("SELECT|people|name,photo|") 213 if err != nil { 214 t.Fatalf("Query: %v", err) 215 } 216 type row struct { 217 name []byte 218 photo RawBytes 219 } 220 got := []row{} 221 for rows.Next() { 222 var r row 223 err = rows.Scan(&r.name, &r.photo) 224 if err != nil { 225 t.Fatalf("Scan: %v", err) 226 } 227 got = append(got, r) 228 } 229 corruptMemory := []byte("\xffPHOTO") 230 want := []row{ 231 {name: []byte("Alice"), photo: corruptMemory}, 232 {name: []byte("Bob"), photo: corruptMemory}, 233 {name: []byte("Chris"), photo: corruptMemory}, 234 } 235 if !reflect.DeepEqual(got, want) { 236 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 237 } 238 239 var photo RawBytes 240 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 241 if err == nil { 242 t.Error("want error scanning into RawBytes from QueryRow") 243 } 244 } 245 246 func TestRowsColumns(t *testing.T) { 247 db := newTestDB(t, "people") 248 defer closeDB(t, db) 249 rows, err := db.Query("SELECT|people|age,name|") 250 if err != nil { 251 t.Fatalf("Query: %v", err) 252 } 253 cols, err := rows.Columns() 254 if err != nil { 255 t.Fatalf("Columns: %v", err) 256 } 257 want := []string{"age", "name"} 258 if !reflect.DeepEqual(cols, want) { 259 t.Errorf("got %#v; want %#v", cols, want) 260 } 261 if err := rows.Close(); err != nil { 262 t.Errorf("error closing rows: %s", err) 263 } 264 } 265 266 func TestQueryRow(t *testing.T) { 267 db := newTestDB(t, "people") 268 defer closeDB(t, db) 269 var name string 270 var age int 271 var birthday time.Time 272 273 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age) 274 if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") { 275 t.Errorf("expected error from wrong number of arguments; actually got: %v", err) 276 } 277 278 err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday) 279 if err != nil || !birthday.Equal(chrisBirthday) { 280 t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday) 281 } 282 283 err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name) 284 if err != nil { 285 t.Fatalf("age QueryRow+Scan: %v", err) 286 } 287 if name != "Bob" { 288 t.Errorf("expected name Bob, got %q", name) 289 } 290 if age != 2 { 291 t.Errorf("expected age 2, got %d", age) 292 } 293 294 err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name) 295 if err != nil { 296 t.Fatalf("name QueryRow+Scan: %v", err) 297 } 298 if name != "Alice" { 299 t.Errorf("expected name Alice, got %q", name) 300 } 301 if age != 1 { 302 t.Errorf("expected age 1, got %d", age) 303 } 304 305 var photo []byte 306 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 307 if err != nil { 308 t.Fatalf("photo QueryRow+Scan: %v", err) 309 } 310 want := []byte("APHOTO") 311 if !reflect.DeepEqual(photo, want) { 312 t.Errorf("photo = %q; want %q", photo, want) 313 } 314 } 315 316 func TestStatementErrorAfterClose(t *testing.T) { 317 db := newTestDB(t, "people") 318 defer closeDB(t, db) 319 stmt, err := db.Prepare("SELECT|people|age|name=?") 320 if err != nil { 321 t.Fatalf("Prepare: %v", err) 322 } 323 err = stmt.Close() 324 if err != nil { 325 t.Fatalf("Close: %v", err) 326 } 327 var name string 328 err = stmt.QueryRow("foo").Scan(&name) 329 if err == nil { 330 t.Errorf("expected error from QueryRow.Scan after Stmt.Close") 331 } 332 } 333 334 func TestStatementQueryRow(t *testing.T) { 335 db := newTestDB(t, "people") 336 defer closeDB(t, db) 337 stmt, err := db.Prepare("SELECT|people|age|name=?") 338 if err != nil { 339 t.Fatalf("Prepare: %v", err) 340 } 341 defer stmt.Close() 342 var age int 343 for n, tt := range []struct { 344 name string 345 want int 346 }{ 347 {"Alice", 1}, 348 {"Bob", 2}, 349 {"Chris", 3}, 350 } { 351 if err := stmt.QueryRow(tt.name).Scan(&age); err != nil { 352 t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err) 353 } else if age != tt.want { 354 t.Errorf("%d: age=%d, want %d", n, age, tt.want) 355 } 356 } 357 } 358 359 type stubDriverStmt struct { 360 err error 361 } 362 363 func (s stubDriverStmt) Close() error { 364 return s.err 365 } 366 367 func (s stubDriverStmt) NumInput() int { 368 return -1 369 } 370 371 func (s stubDriverStmt) Exec(args []driver.Value) (driver.Result, error) { 372 return nil, nil 373 } 374 375 func (s stubDriverStmt) Query(args []driver.Value) (driver.Rows, error) { 376 return nil, nil 377 } 378 379 // golang.org/issue/12798 380 func TestStatementClose(t *testing.T) { 381 want := errors.New("STMT ERROR") 382 383 tests := []struct { 384 stmt *Stmt 385 msg string 386 }{ 387 {&Stmt{stickyErr: want}, "stickyErr not propagated"}, 388 {&Stmt{tx: &Tx{}, txsi: &driverStmt{&sync.Mutex{}, stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"}, 389 } 390 for _, test := range tests { 391 if err := test.stmt.Close(); err != want { 392 t.Errorf("%s. Got stmt.Close() = %v, want = %v", test.msg, err, want) 393 } 394 } 395 } 396 397 // golang.org/issue/3734 398 func TestStatementQueryRowConcurrent(t *testing.T) { 399 db := newTestDB(t, "people") 400 defer closeDB(t, db) 401 stmt, err := db.Prepare("SELECT|people|age|name=?") 402 if err != nil { 403 t.Fatalf("Prepare: %v", err) 404 } 405 defer stmt.Close() 406 407 const n = 10 408 ch := make(chan error, n) 409 for i := 0; i < n; i++ { 410 go func() { 411 var age int 412 err := stmt.QueryRow("Alice").Scan(&age) 413 if err == nil && age != 1 { 414 err = fmt.Errorf("unexpected age %d", age) 415 } 416 ch <- err 417 }() 418 } 419 for i := 0; i < n; i++ { 420 if err := <-ch; err != nil { 421 t.Error(err) 422 } 423 } 424 } 425 426 // just a test of fakedb itself 427 func TestBogusPreboundParameters(t *testing.T) { 428 db := newTestDB(t, "foo") 429 defer closeDB(t, db) 430 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 431 _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion") 432 if err == nil { 433 t.Fatalf("expected error") 434 } 435 if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` { 436 t.Errorf("unexpected error: %v", err) 437 } 438 } 439 440 func TestExec(t *testing.T) { 441 db := newTestDB(t, "foo") 442 defer closeDB(t, db) 443 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 444 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 445 if err != nil { 446 t.Errorf("Stmt, err = %v, %v", stmt, err) 447 } 448 defer stmt.Close() 449 450 type execTest struct { 451 args []interface{} 452 wantErr string 453 } 454 execTests := []execTest{ 455 // Okay: 456 {[]interface{}{"Brad", 31}, ""}, 457 {[]interface{}{"Brad", int64(31)}, ""}, 458 {[]interface{}{"Bob", "32"}, ""}, 459 {[]interface{}{7, 9}, ""}, 460 461 // Invalid conversions: 462 {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"}, 463 {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"}, 464 465 // Wrong number of args: 466 {[]interface{}{}, "sql: expected 2 arguments, got 0"}, 467 {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"}, 468 } 469 for n, et := range execTests { 470 _, err := stmt.Exec(et.args...) 471 errStr := "" 472 if err != nil { 473 errStr = err.Error() 474 } 475 if errStr != et.wantErr { 476 t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q", 477 n, et.args, errStr, et.wantErr) 478 } 479 } 480 } 481 482 func TestTxPrepare(t *testing.T) { 483 db := newTestDB(t, "") 484 defer closeDB(t, db) 485 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 486 tx, err := db.Begin() 487 if err != nil { 488 t.Fatalf("Begin = %v", err) 489 } 490 stmt, err := tx.Prepare("INSERT|t1|name=?,age=?") 491 if err != nil { 492 t.Fatalf("Stmt, err = %v, %v", stmt, err) 493 } 494 defer stmt.Close() 495 _, err = stmt.Exec("Bobby", 7) 496 if err != nil { 497 t.Fatalf("Exec = %v", err) 498 } 499 err = tx.Commit() 500 if err != nil { 501 t.Fatalf("Commit = %v", err) 502 } 503 // Commit() should have closed the statement 504 if !stmt.closed { 505 t.Fatal("Stmt not closed after Commit") 506 } 507 } 508 509 func TestTxStmt(t *testing.T) { 510 db := newTestDB(t, "") 511 defer closeDB(t, db) 512 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 513 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 514 if err != nil { 515 t.Fatalf("Stmt, err = %v, %v", stmt, err) 516 } 517 defer stmt.Close() 518 tx, err := db.Begin() 519 if err != nil { 520 t.Fatalf("Begin = %v", err) 521 } 522 txs := tx.Stmt(stmt) 523 defer txs.Close() 524 _, err = txs.Exec("Bobby", 7) 525 if err != nil { 526 t.Fatalf("Exec = %v", err) 527 } 528 err = tx.Commit() 529 if err != nil { 530 t.Fatalf("Commit = %v", err) 531 } 532 // Commit() should have closed the statement 533 if !txs.closed { 534 t.Fatal("Stmt not closed after Commit") 535 } 536 } 537 538 // Issue: https://golang.org/issue/2784 539 // This test didn't fail before because we got lucky with the fakedb driver. 540 // It was failing, and now not, in github.com/bradfitz/go-sql-test 541 func TestTxQuery(t *testing.T) { 542 db := newTestDB(t, "") 543 defer closeDB(t, db) 544 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 545 exec(t, db, "INSERT|t1|name=Alice") 546 547 tx, err := db.Begin() 548 if err != nil { 549 t.Fatal(err) 550 } 551 defer tx.Rollback() 552 553 r, err := tx.Query("SELECT|t1|name|") 554 if err != nil { 555 t.Fatal(err) 556 } 557 defer r.Close() 558 559 if !r.Next() { 560 if r.Err() != nil { 561 t.Fatal(r.Err()) 562 } 563 t.Fatal("expected one row") 564 } 565 566 var x string 567 err = r.Scan(&x) 568 if err != nil { 569 t.Fatal(err) 570 } 571 } 572 573 func TestTxQueryInvalid(t *testing.T) { 574 db := newTestDB(t, "") 575 defer closeDB(t, db) 576 577 tx, err := db.Begin() 578 if err != nil { 579 t.Fatal(err) 580 } 581 defer tx.Rollback() 582 583 _, err = tx.Query("SELECT|t1|name|") 584 if err == nil { 585 t.Fatal("Error expected") 586 } 587 } 588 589 // Tests fix for issue 4433, that retries in Begin happen when 590 // conn.Begin() returns ErrBadConn 591 func TestTxErrBadConn(t *testing.T) { 592 db, err := Open("test", fakeDBName+";badConn") 593 if err != nil { 594 t.Fatalf("Open: %v", err) 595 } 596 if _, err := db.Exec("WIPE"); err != nil { 597 t.Fatalf("exec wipe: %v", err) 598 } 599 defer closeDB(t, db) 600 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 601 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 602 if err != nil { 603 t.Fatalf("Stmt, err = %v, %v", stmt, err) 604 } 605 defer stmt.Close() 606 tx, err := db.Begin() 607 if err != nil { 608 t.Fatalf("Begin = %v", err) 609 } 610 txs := tx.Stmt(stmt) 611 defer txs.Close() 612 _, err = txs.Exec("Bobby", 7) 613 if err != nil { 614 t.Fatalf("Exec = %v", err) 615 } 616 err = tx.Commit() 617 if err != nil { 618 t.Fatalf("Commit = %v", err) 619 } 620 } 621 622 // Tests fix for issue 2542, that we release a lock when querying on 623 // a closed connection. 624 func TestIssue2542Deadlock(t *testing.T) { 625 db := newTestDB(t, "people") 626 closeDB(t, db) 627 for i := 0; i < 2; i++ { 628 _, err := db.Query("SELECT|people|age,name|") 629 if err == nil { 630 t.Fatalf("expected error") 631 } 632 } 633 } 634 635 // From golang.org/issue/3865 636 func TestCloseStmtBeforeRows(t *testing.T) { 637 db := newTestDB(t, "people") 638 defer closeDB(t, db) 639 640 s, err := db.Prepare("SELECT|people|name|") 641 if err != nil { 642 t.Fatal(err) 643 } 644 645 r, err := s.Query() 646 if err != nil { 647 s.Close() 648 t.Fatal(err) 649 } 650 651 err = s.Close() 652 if err != nil { 653 t.Fatal(err) 654 } 655 656 r.Close() 657 } 658 659 // Tests fix for issue 2788, that we bind nil to a []byte if the 660 // value in the column is sql null 661 func TestNullByteSlice(t *testing.T) { 662 db := newTestDB(t, "") 663 defer closeDB(t, db) 664 exec(t, db, "CREATE|t|id=int32,name=nullstring") 665 exec(t, db, "INSERT|t|id=10,name=?", nil) 666 667 var name []byte 668 669 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 670 if err != nil { 671 t.Fatal(err) 672 } 673 if name != nil { 674 t.Fatalf("name []byte should be nil for null column value, got: %#v", name) 675 } 676 677 exec(t, db, "INSERT|t|id=11,name=?", "bob") 678 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name) 679 if err != nil { 680 t.Fatal(err) 681 } 682 if string(name) != "bob" { 683 t.Fatalf("name []byte should be bob, got: %q", string(name)) 684 } 685 } 686 687 func TestPointerParamsAndScans(t *testing.T) { 688 db := newTestDB(t, "") 689 defer closeDB(t, db) 690 exec(t, db, "CREATE|t|id=int32,name=nullstring") 691 692 bob := "bob" 693 var name *string 694 695 name = &bob 696 exec(t, db, "INSERT|t|id=10,name=?", name) 697 name = nil 698 exec(t, db, "INSERT|t|id=20,name=?", name) 699 700 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 701 if err != nil { 702 t.Fatalf("querying id 10: %v", err) 703 } 704 if name == nil { 705 t.Errorf("id 10's name = nil; want bob") 706 } else if *name != "bob" { 707 t.Errorf("id 10's name = %q; want bob", *name) 708 } 709 710 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name) 711 if err != nil { 712 t.Fatalf("querying id 20: %v", err) 713 } 714 if name != nil { 715 t.Errorf("id 20 = %q; want nil", *name) 716 } 717 } 718 719 func TestQueryRowClosingStmt(t *testing.T) { 720 db := newTestDB(t, "people") 721 defer closeDB(t, db) 722 var name string 723 var age int 724 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name) 725 if err != nil { 726 t.Fatal(err) 727 } 728 if len(db.freeConn) != 1 { 729 t.Fatalf("expected 1 free conn") 730 } 731 fakeConn := db.freeConn[0].ci.(*fakeConn) 732 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed { 733 t.Errorf("statement close mismatch: made %d, closed %d", made, closed) 734 } 735 } 736 737 // Test issue 6651 738 func TestIssue6651(t *testing.T) { 739 db := newTestDB(t, "people") 740 defer closeDB(t, db) 741 742 var v string 743 744 want := "error in rows.Next" 745 rowsCursorNextHook = func(dest []driver.Value) error { 746 return fmt.Errorf(want) 747 } 748 defer func() { rowsCursorNextHook = nil }() 749 err := db.QueryRow("SELECT|people|name|").Scan(&v) 750 if err == nil || err.Error() != want { 751 t.Errorf("error = %q; want %q", err, want) 752 } 753 rowsCursorNextHook = nil 754 755 want = "error in rows.Close" 756 rowsCloseHook = func(rows *Rows, err *error) { 757 *err = fmt.Errorf(want) 758 } 759 defer func() { rowsCloseHook = nil }() 760 err = db.QueryRow("SELECT|people|name|").Scan(&v) 761 if err == nil || err.Error() != want { 762 t.Errorf("error = %q; want %q", err, want) 763 } 764 } 765 766 type nullTestRow struct { 767 nullParam interface{} 768 notNullParam interface{} 769 scanNullVal interface{} 770 } 771 772 type nullTestSpec struct { 773 nullType string 774 notNullType string 775 rows [6]nullTestRow 776 } 777 778 func TestNullStringParam(t *testing.T) { 779 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{ 780 {NullString{"aqua", true}, "", NullString{"aqua", true}}, 781 {NullString{"brown", false}, "", NullString{"", false}}, 782 {"chartreuse", "", NullString{"chartreuse", true}}, 783 {NullString{"darkred", true}, "", NullString{"darkred", true}}, 784 {NullString{"eel", false}, "", NullString{"", false}}, 785 {"foo", NullString{"black", false}, nil}, 786 }} 787 nullTestRun(t, spec) 788 } 789 790 func TestNullInt64Param(t *testing.T) { 791 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{ 792 {NullInt64{31, true}, 1, NullInt64{31, true}}, 793 {NullInt64{-22, false}, 1, NullInt64{0, false}}, 794 {22, 1, NullInt64{22, true}}, 795 {NullInt64{33, true}, 1, NullInt64{33, true}}, 796 {NullInt64{222, false}, 1, NullInt64{0, false}}, 797 {0, NullInt64{31, false}, nil}, 798 }} 799 nullTestRun(t, spec) 800 } 801 802 func TestNullFloat64Param(t *testing.T) { 803 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ 804 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, 805 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}}, 806 {-22.9, 1, NullFloat64{-22.9, true}}, 807 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}}, 808 {NullFloat64{222, false}, 1, NullFloat64{0, false}}, 809 {10, NullFloat64{31.2, false}, nil}, 810 }} 811 nullTestRun(t, spec) 812 } 813 814 func TestNullBoolParam(t *testing.T) { 815 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{ 816 {NullBool{false, true}, true, NullBool{false, true}}, 817 {NullBool{true, false}, false, NullBool{false, false}}, 818 {true, true, NullBool{true, true}}, 819 {NullBool{true, true}, false, NullBool{true, true}}, 820 {NullBool{true, false}, true, NullBool{false, false}}, 821 {true, NullBool{true, false}, nil}, 822 }} 823 nullTestRun(t, spec) 824 } 825 826 func nullTestRun(t *testing.T, spec nullTestSpec) { 827 db := newTestDB(t, "") 828 defer closeDB(t, db) 829 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType)) 830 831 // Inserts with db.Exec: 832 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam) 833 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam) 834 835 // Inserts with a prepared statement: 836 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?") 837 if err != nil { 838 t.Fatalf("prepare: %v", err) 839 } 840 defer stmt.Close() 841 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil { 842 t.Errorf("exec insert chris: %v", err) 843 } 844 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil { 845 t.Errorf("exec insert dave: %v", err) 846 } 847 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil { 848 t.Errorf("exec insert eleanor: %v", err) 849 } 850 851 // Can't put null val into non-null col 852 if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil { 853 t.Errorf("expected error inserting nil val with prepared statement Exec") 854 } 855 856 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil) 857 if err == nil { 858 // TODO: this test fails, but it's just because 859 // fakeConn implements the optional Execer interface, 860 // so arguably this is the correct behavior. But 861 // maybe I should flesh out the fakeConn.Exec 862 // implementation so this properly fails. 863 // t.Errorf("expected error inserting nil name with Exec") 864 } 865 866 paramtype := reflect.TypeOf(spec.rows[0].nullParam) 867 bindVal := reflect.New(paramtype).Interface() 868 869 for i := 0; i < 5; i++ { 870 id := i + 1 871 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil { 872 t.Errorf("id=%d Scan: %v", id, err) 873 } 874 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface() 875 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) { 876 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal) 877 } 878 } 879 } 880 881 // golang.org/issue/4859 882 func TestQueryRowNilScanDest(t *testing.T) { 883 db := newTestDB(t, "people") 884 defer closeDB(t, db) 885 var name *string // nil pointer 886 err := db.QueryRow("SELECT|people|name|").Scan(name) 887 want := "sql: Scan error on column index 0: destination pointer is nil" 888 if err == nil || err.Error() != want { 889 t.Errorf("error = %q; want %q", err.Error(), want) 890 } 891 } 892 893 func TestIssue4902(t *testing.T) { 894 db := newTestDB(t, "people") 895 defer closeDB(t, db) 896 897 driver := db.driver.(*fakeDriver) 898 opens0 := driver.openCount 899 900 var stmt *Stmt 901 var err error 902 for i := 0; i < 10; i++ { 903 stmt, err = db.Prepare("SELECT|people|name|") 904 if err != nil { 905 t.Fatal(err) 906 } 907 err = stmt.Close() 908 if err != nil { 909 t.Fatal(err) 910 } 911 } 912 913 opens := driver.openCount - opens0 914 if opens > 1 { 915 t.Errorf("opens = %d; want <= 1", opens) 916 t.Logf("db = %#v", db) 917 t.Logf("driver = %#v", driver) 918 t.Logf("stmt = %#v", stmt) 919 } 920 } 921 922 // Issue 3857 923 // This used to deadlock. 924 func TestSimultaneousQueries(t *testing.T) { 925 db := newTestDB(t, "people") 926 defer closeDB(t, db) 927 928 tx, err := db.Begin() 929 if err != nil { 930 t.Fatal(err) 931 } 932 defer tx.Rollback() 933 934 r1, err := tx.Query("SELECT|people|name|") 935 if err != nil { 936 t.Fatal(err) 937 } 938 defer r1.Close() 939 940 r2, err := tx.Query("SELECT|people|name|") 941 if err != nil { 942 t.Fatal(err) 943 } 944 defer r2.Close() 945 } 946 947 func TestMaxIdleConns(t *testing.T) { 948 db := newTestDB(t, "people") 949 defer closeDB(t, db) 950 951 tx, err := db.Begin() 952 if err != nil { 953 t.Fatal(err) 954 } 955 tx.Commit() 956 if got := len(db.freeConn); got != 1 { 957 t.Errorf("freeConns = %d; want 1", got) 958 } 959 960 db.SetMaxIdleConns(0) 961 962 if got := len(db.freeConn); got != 0 { 963 t.Errorf("freeConns after set to zero = %d; want 0", got) 964 } 965 966 tx, err = db.Begin() 967 if err != nil { 968 t.Fatal(err) 969 } 970 tx.Commit() 971 if got := len(db.freeConn); got != 0 { 972 t.Errorf("freeConns = %d; want 0", got) 973 } 974 } 975 976 func TestMaxOpenConns(t *testing.T) { 977 if testing.Short() { 978 t.Skip("skipping in short mode") 979 } 980 defer setHookpostCloseConn(nil) 981 setHookpostCloseConn(func(_ *fakeConn, err error) { 982 if err != nil { 983 t.Errorf("Error closing fakeConn: %v", err) 984 } 985 }) 986 987 db := newTestDB(t, "magicquery") 988 defer closeDB(t, db) 989 990 driver := db.driver.(*fakeDriver) 991 992 // Force the number of open connections to 0 so we can get an accurate 993 // count for the test 994 db.SetMaxIdleConns(0) 995 996 if g, w := db.numFreeConns(), 0; g != w { 997 t.Errorf("free conns = %d; want %d", g, w) 998 } 999 1000 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 1001 t.Errorf("number of dependencies = %d; expected 0", n) 1002 db.dumpDeps(t) 1003 } 1004 1005 driver.mu.Lock() 1006 opens0 := driver.openCount 1007 closes0 := driver.closeCount 1008 driver.mu.Unlock() 1009 1010 db.SetMaxIdleConns(10) 1011 db.SetMaxOpenConns(10) 1012 1013 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 1014 if err != nil { 1015 t.Fatal(err) 1016 } 1017 1018 // Start 50 parallel slow queries. 1019 const ( 1020 nquery = 50 1021 sleepMillis = 25 1022 nbatch = 2 1023 ) 1024 var wg sync.WaitGroup 1025 for batch := 0; batch < nbatch; batch++ { 1026 for i := 0; i < nquery; i++ { 1027 wg.Add(1) 1028 go func() { 1029 defer wg.Done() 1030 var op string 1031 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 1032 t.Error(err) 1033 } 1034 }() 1035 } 1036 // Sleep for twice the expected length of time for the 1037 // batch of 50 queries above to finish before starting 1038 // the next round. 1039 time.Sleep(2 * sleepMillis * time.Millisecond) 1040 } 1041 wg.Wait() 1042 1043 if g, w := db.numFreeConns(), 10; g != w { 1044 t.Errorf("free conns = %d; want %d", g, w) 1045 } 1046 1047 if n := db.numDepsPollUntil(20, time.Second); n > 20 { 1048 t.Errorf("number of dependencies = %d; expected <= 20", n) 1049 db.dumpDeps(t) 1050 } 1051 1052 driver.mu.Lock() 1053 opens := driver.openCount - opens0 1054 closes := driver.closeCount - closes0 1055 driver.mu.Unlock() 1056 1057 if opens > 10 { 1058 t.Logf("open calls = %d", opens) 1059 t.Logf("close calls = %d", closes) 1060 t.Errorf("db connections opened = %d; want <= 10", opens) 1061 db.dumpDeps(t) 1062 } 1063 1064 if err := stmt.Close(); err != nil { 1065 t.Fatal(err) 1066 } 1067 1068 if g, w := db.numFreeConns(), 10; g != w { 1069 t.Errorf("free conns = %d; want %d", g, w) 1070 } 1071 1072 if n := db.numDepsPollUntil(10, time.Second); n > 10 { 1073 t.Errorf("number of dependencies = %d; expected <= 10", n) 1074 db.dumpDeps(t) 1075 } 1076 1077 db.SetMaxOpenConns(5) 1078 1079 if g, w := db.numFreeConns(), 5; g != w { 1080 t.Errorf("free conns = %d; want %d", g, w) 1081 } 1082 1083 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 1084 t.Errorf("number of dependencies = %d; expected 0", n) 1085 db.dumpDeps(t) 1086 } 1087 1088 db.SetMaxOpenConns(0) 1089 1090 if g, w := db.numFreeConns(), 5; g != w { 1091 t.Errorf("free conns = %d; want %d", g, w) 1092 } 1093 1094 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 1095 t.Errorf("number of dependencies = %d; expected 0", n) 1096 db.dumpDeps(t) 1097 } 1098 1099 db.SetMaxIdleConns(0) 1100 1101 if g, w := db.numFreeConns(), 0; g != w { 1102 t.Errorf("free conns = %d; want %d", g, w) 1103 } 1104 1105 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 1106 t.Errorf("number of dependencies = %d; expected 0", n) 1107 db.dumpDeps(t) 1108 } 1109 } 1110 1111 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime 1112 // and affects the subsequent release of connections. 1113 func TestMaxOpenConnsOnBusy(t *testing.T) { 1114 defer setHookpostCloseConn(nil) 1115 setHookpostCloseConn(func(_ *fakeConn, err error) { 1116 if err != nil { 1117 t.Errorf("Error closing fakeConn: %v", err) 1118 } 1119 }) 1120 1121 db := newTestDB(t, "magicquery") 1122 defer closeDB(t, db) 1123 1124 db.SetMaxOpenConns(3) 1125 1126 conn0, err := db.conn(cachedOrNewConn) 1127 if err != nil { 1128 t.Fatalf("db open conn fail: %v", err) 1129 } 1130 1131 conn1, err := db.conn(cachedOrNewConn) 1132 if err != nil { 1133 t.Fatalf("db open conn fail: %v", err) 1134 } 1135 1136 conn2, err := db.conn(cachedOrNewConn) 1137 if err != nil { 1138 t.Fatalf("db open conn fail: %v", err) 1139 } 1140 1141 if g, w := db.numOpen, 3; g != w { 1142 t.Errorf("free conns = %d; want %d", g, w) 1143 } 1144 1145 db.SetMaxOpenConns(2) 1146 if g, w := db.numOpen, 3; g != w { 1147 t.Errorf("free conns = %d; want %d", g, w) 1148 } 1149 1150 conn0.releaseConn(nil) 1151 conn1.releaseConn(nil) 1152 if g, w := db.numOpen, 2; g != w { 1153 t.Errorf("free conns = %d; want %d", g, w) 1154 } 1155 1156 conn2.releaseConn(nil) 1157 if g, w := db.numOpen, 2; g != w { 1158 t.Errorf("free conns = %d; want %d", g, w) 1159 } 1160 } 1161 1162 func TestSingleOpenConn(t *testing.T) { 1163 db := newTestDB(t, "people") 1164 defer closeDB(t, db) 1165 1166 db.SetMaxOpenConns(1) 1167 1168 rows, err := db.Query("SELECT|people|name|") 1169 if err != nil { 1170 t.Fatal(err) 1171 } 1172 if err = rows.Close(); err != nil { 1173 t.Fatal(err) 1174 } 1175 // shouldn't deadlock 1176 rows, err = db.Query("SELECT|people|name|") 1177 if err != nil { 1178 t.Fatal(err) 1179 } 1180 if err = rows.Close(); err != nil { 1181 t.Fatal(err) 1182 } 1183 } 1184 1185 func TestStats(t *testing.T) { 1186 db := newTestDB(t, "people") 1187 stats := db.Stats() 1188 if got := stats.OpenConnections; got != 1 { 1189 t.Errorf("stats.OpenConnections = %d; want 1", got) 1190 } 1191 1192 tx, err := db.Begin() 1193 if err != nil { 1194 t.Fatal(err) 1195 } 1196 tx.Commit() 1197 1198 closeDB(t, db) 1199 stats = db.Stats() 1200 if got := stats.OpenConnections; got != 0 { 1201 t.Errorf("stats.OpenConnections = %d; want 0", got) 1202 } 1203 } 1204 1205 // golang.org/issue/5323 1206 func TestStmtCloseDeps(t *testing.T) { 1207 if testing.Short() { 1208 t.Skip("skipping in short mode") 1209 } 1210 defer setHookpostCloseConn(nil) 1211 setHookpostCloseConn(func(_ *fakeConn, err error) { 1212 if err != nil { 1213 t.Errorf("Error closing fakeConn: %v", err) 1214 } 1215 }) 1216 1217 db := newTestDB(t, "magicquery") 1218 defer closeDB(t, db) 1219 1220 driver := db.driver.(*fakeDriver) 1221 1222 driver.mu.Lock() 1223 opens0 := driver.openCount 1224 closes0 := driver.closeCount 1225 driver.mu.Unlock() 1226 openDelta0 := opens0 - closes0 1227 1228 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 1229 if err != nil { 1230 t.Fatal(err) 1231 } 1232 1233 // Start 50 parallel slow queries. 1234 const ( 1235 nquery = 50 1236 sleepMillis = 25 1237 nbatch = 2 1238 ) 1239 var wg sync.WaitGroup 1240 for batch := 0; batch < nbatch; batch++ { 1241 for i := 0; i < nquery; i++ { 1242 wg.Add(1) 1243 go func() { 1244 defer wg.Done() 1245 var op string 1246 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 1247 t.Error(err) 1248 } 1249 }() 1250 } 1251 // Sleep for twice the expected length of time for the 1252 // batch of 50 queries above to finish before starting 1253 // the next round. 1254 time.Sleep(2 * sleepMillis * time.Millisecond) 1255 } 1256 wg.Wait() 1257 1258 if g, w := db.numFreeConns(), 2; g != w { 1259 t.Errorf("free conns = %d; want %d", g, w) 1260 } 1261 1262 if n := db.numDepsPollUntil(4, time.Second); n > 4 { 1263 t.Errorf("number of dependencies = %d; expected <= 4", n) 1264 db.dumpDeps(t) 1265 } 1266 1267 driver.mu.Lock() 1268 opens := driver.openCount - opens0 1269 closes := driver.closeCount - closes0 1270 openDelta := (driver.openCount - driver.closeCount) - openDelta0 1271 driver.mu.Unlock() 1272 1273 if openDelta > 2 { 1274 t.Logf("open calls = %d", opens) 1275 t.Logf("close calls = %d", closes) 1276 t.Logf("open delta = %d", openDelta) 1277 t.Errorf("db connections opened = %d; want <= 2", openDelta) 1278 db.dumpDeps(t) 1279 } 1280 1281 if len(stmt.css) > nquery { 1282 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) 1283 } 1284 1285 if err := stmt.Close(); err != nil { 1286 t.Fatal(err) 1287 } 1288 1289 if g, w := db.numFreeConns(), 2; g != w { 1290 t.Errorf("free conns = %d; want %d", g, w) 1291 } 1292 1293 if n := db.numDepsPollUntil(2, time.Second); n > 2 { 1294 t.Errorf("number of dependencies = %d; expected <= 2", n) 1295 db.dumpDeps(t) 1296 } 1297 1298 db.SetMaxIdleConns(0) 1299 1300 if g, w := db.numFreeConns(), 0; g != w { 1301 t.Errorf("free conns = %d; want %d", g, w) 1302 } 1303 1304 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 1305 t.Errorf("number of dependencies = %d; expected 0", n) 1306 db.dumpDeps(t) 1307 } 1308 } 1309 1310 // golang.org/issue/5046 1311 func TestCloseConnBeforeStmts(t *testing.T) { 1312 db := newTestDB(t, "people") 1313 defer closeDB(t, db) 1314 1315 defer setHookpostCloseConn(nil) 1316 setHookpostCloseConn(func(_ *fakeConn, err error) { 1317 if err != nil { 1318 t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) 1319 db.dumpDeps(t) 1320 t.Errorf("DB = %#v", db) 1321 } 1322 }) 1323 1324 stmt, err := db.Prepare("SELECT|people|name|") 1325 if err != nil { 1326 t.Fatal(err) 1327 } 1328 1329 if len(db.freeConn) != 1 { 1330 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) 1331 } 1332 dc := db.freeConn[0] 1333 if dc.closed { 1334 t.Errorf("conn shouldn't be closed") 1335 } 1336 1337 if n := len(dc.openStmt); n != 1 { 1338 t.Errorf("driverConn num openStmt = %d; want 1", n) 1339 } 1340 err = db.Close() 1341 if err != nil { 1342 t.Errorf("db Close = %v", err) 1343 } 1344 if !dc.closed { 1345 t.Errorf("after db.Close, driverConn should be closed") 1346 } 1347 if n := len(dc.openStmt); n != 0 { 1348 t.Errorf("driverConn num openStmt = %d; want 0", n) 1349 } 1350 1351 err = stmt.Close() 1352 if err != nil { 1353 t.Errorf("Stmt close = %v", err) 1354 } 1355 1356 if !dc.closed { 1357 t.Errorf("conn should be closed") 1358 } 1359 if dc.ci != nil { 1360 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") 1361 } 1362 } 1363 1364 // golang.org/issue/5283: don't release the Rows' connection in Close 1365 // before calling Stmt.Close. 1366 func TestRowsCloseOrder(t *testing.T) { 1367 db := newTestDB(t, "people") 1368 defer closeDB(t, db) 1369 1370 db.SetMaxIdleConns(0) 1371 setStrictFakeConnClose(t) 1372 defer setStrictFakeConnClose(nil) 1373 1374 rows, err := db.Query("SELECT|people|age,name|") 1375 if err != nil { 1376 t.Fatal(err) 1377 } 1378 err = rows.Close() 1379 if err != nil { 1380 t.Fatal(err) 1381 } 1382 } 1383 1384 func TestRowsImplicitClose(t *testing.T) { 1385 db := newTestDB(t, "people") 1386 defer closeDB(t, db) 1387 1388 rows, err := db.Query("SELECT|people|age,name|") 1389 if err != nil { 1390 t.Fatal(err) 1391 } 1392 1393 want, fail := 2, errors.New("fail") 1394 r := rows.rowsi.(*rowsCursor) 1395 r.errPos, r.err = want, fail 1396 1397 got := 0 1398 for rows.Next() { 1399 got++ 1400 } 1401 if got != want { 1402 t.Errorf("got %d rows, want %d", got, want) 1403 } 1404 if err := rows.Err(); err != fail { 1405 t.Errorf("got error %v, want %v", err, fail) 1406 } 1407 if !r.closed { 1408 t.Errorf("r.closed is false, want true") 1409 } 1410 } 1411 1412 func TestStmtCloseOrder(t *testing.T) { 1413 db := newTestDB(t, "people") 1414 defer closeDB(t, db) 1415 1416 db.SetMaxIdleConns(0) 1417 setStrictFakeConnClose(t) 1418 defer setStrictFakeConnClose(nil) 1419 1420 _, err := db.Query("SELECT|non_existent|name|") 1421 if err == nil { 1422 t.Fatal("Quering non-existent table should fail") 1423 } 1424 } 1425 1426 // Test cases where there's more than maxBadConnRetries bad connections in the 1427 // pool (issue 8834) 1428 func TestManyErrBadConn(t *testing.T) { 1429 manyErrBadConnSetup := func() *DB { 1430 db := newTestDB(t, "people") 1431 1432 nconn := maxBadConnRetries + 1 1433 db.SetMaxIdleConns(nconn) 1434 db.SetMaxOpenConns(nconn) 1435 // open enough connections 1436 func() { 1437 for i := 0; i < nconn; i++ { 1438 rows, err := db.Query("SELECT|people|age,name|") 1439 if err != nil { 1440 t.Fatal(err) 1441 } 1442 defer rows.Close() 1443 } 1444 }() 1445 1446 if db.numOpen != nconn { 1447 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn) 1448 } else if len(db.freeConn) != nconn { 1449 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn) 1450 } 1451 for _, conn := range db.freeConn { 1452 conn.ci.(*fakeConn).stickyBad = true 1453 } 1454 return db 1455 } 1456 1457 // Query 1458 db := manyErrBadConnSetup() 1459 defer closeDB(t, db) 1460 rows, err := db.Query("SELECT|people|age,name|") 1461 if err != nil { 1462 t.Fatal(err) 1463 } 1464 if err = rows.Close(); err != nil { 1465 t.Fatal(err) 1466 } 1467 1468 // Exec 1469 db = manyErrBadConnSetup() 1470 defer closeDB(t, db) 1471 _, err = db.Exec("INSERT|people|name=Julia,age=19") 1472 if err != nil { 1473 t.Fatal(err) 1474 } 1475 1476 // Begin 1477 db = manyErrBadConnSetup() 1478 defer closeDB(t, db) 1479 tx, err := db.Begin() 1480 if err != nil { 1481 t.Fatal(err) 1482 } 1483 if err = tx.Rollback(); err != nil { 1484 t.Fatal(err) 1485 } 1486 1487 // Prepare 1488 db = manyErrBadConnSetup() 1489 defer closeDB(t, db) 1490 stmt, err := db.Prepare("SELECT|people|age,name|") 1491 if err != nil { 1492 t.Fatal(err) 1493 } 1494 if err = stmt.Close(); err != nil { 1495 t.Fatal(err) 1496 } 1497 } 1498 1499 // golang.org/issue/5718 1500 func TestErrBadConnReconnect(t *testing.T) { 1501 db := newTestDB(t, "foo") 1502 defer closeDB(t, db) 1503 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1504 1505 simulateBadConn := func(name string, hook *func() bool, op func() error) { 1506 broken, retried := false, false 1507 numOpen := db.numOpen 1508 1509 // simulate a broken connection on the first try 1510 *hook = func() bool { 1511 if !broken { 1512 broken = true 1513 return true 1514 } 1515 retried = true 1516 return false 1517 } 1518 1519 if err := op(); err != nil { 1520 t.Errorf(name+": %v", err) 1521 return 1522 } 1523 1524 if !broken || !retried { 1525 t.Error(name + ": Failed to simulate broken connection") 1526 } 1527 *hook = nil 1528 1529 if numOpen != db.numOpen { 1530 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 1531 numOpen = db.numOpen 1532 } 1533 } 1534 1535 // db.Exec 1536 dbExec := func() error { 1537 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 1538 return err 1539 } 1540 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec) 1541 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec) 1542 1543 // db.Query 1544 dbQuery := func() error { 1545 rows, err := db.Query("SELECT|t1|age,name|") 1546 if err == nil { 1547 err = rows.Close() 1548 } 1549 return err 1550 } 1551 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery) 1552 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery) 1553 1554 // db.Prepare 1555 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error { 1556 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 1557 if err != nil { 1558 return err 1559 } 1560 stmt.Close() 1561 return nil 1562 }) 1563 1564 // Provide a way to force a re-prepare of a statement on next execution 1565 forcePrepare := func(stmt *Stmt) { 1566 stmt.css = nil 1567 } 1568 1569 // stmt.Exec 1570 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 1571 if err != nil { 1572 t.Fatalf("prepare: %v", err) 1573 } 1574 defer stmt1.Close() 1575 // make sure we must prepare the stmt first 1576 forcePrepare(stmt1) 1577 1578 stmtExec := func() error { 1579 _, err := stmt1.Exec("Gopher", 3, false) 1580 return err 1581 } 1582 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec) 1583 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec) 1584 1585 // stmt.Query 1586 stmt2, err := db.Prepare("SELECT|t1|age,name|") 1587 if err != nil { 1588 t.Fatalf("prepare: %v", err) 1589 } 1590 defer stmt2.Close() 1591 // make sure we must prepare the stmt first 1592 forcePrepare(stmt2) 1593 1594 stmtQuery := func() error { 1595 rows, err := stmt2.Query() 1596 if err == nil { 1597 err = rows.Close() 1598 } 1599 return err 1600 } 1601 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery) 1602 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery) 1603 } 1604 1605 // golang.org/issue/11264 1606 func TestTxEndBadConn(t *testing.T) { 1607 db := newTestDB(t, "foo") 1608 defer closeDB(t, db) 1609 db.SetMaxIdleConns(0) 1610 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1611 db.SetMaxIdleConns(1) 1612 1613 simulateBadConn := func(name string, hook *func() bool, op func() error) { 1614 broken := false 1615 numOpen := db.numOpen 1616 1617 *hook = func() bool { 1618 if !broken { 1619 broken = true 1620 } 1621 return broken 1622 } 1623 1624 if err := op(); err != driver.ErrBadConn { 1625 t.Errorf(name+": %v", err) 1626 return 1627 } 1628 1629 if !broken { 1630 t.Error(name + ": Failed to simulate broken connection") 1631 } 1632 *hook = nil 1633 1634 if numOpen != db.numOpen { 1635 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 1636 } 1637 } 1638 1639 // db.Exec 1640 dbExec := func(endTx func(tx *Tx) error) func() error { 1641 return func() error { 1642 tx, err := db.Begin() 1643 if err != nil { 1644 return err 1645 } 1646 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 1647 if err != nil { 1648 return err 1649 } 1650 return endTx(tx) 1651 } 1652 } 1653 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit)) 1654 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback)) 1655 1656 // db.Query 1657 dbQuery := func(endTx func(tx *Tx) error) func() error { 1658 return func() error { 1659 tx, err := db.Begin() 1660 if err != nil { 1661 return err 1662 } 1663 rows, err := tx.Query("SELECT|t1|age,name|") 1664 if err == nil { 1665 err = rows.Close() 1666 } else { 1667 return err 1668 } 1669 return endTx(tx) 1670 } 1671 } 1672 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit)) 1673 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback)) 1674 } 1675 1676 type concurrentTest interface { 1677 init(t testing.TB, db *DB) 1678 finish(t testing.TB) 1679 test(t testing.TB) error 1680 } 1681 1682 type concurrentDBQueryTest struct { 1683 db *DB 1684 } 1685 1686 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) { 1687 c.db = db 1688 } 1689 1690 func (c *concurrentDBQueryTest) finish(t testing.TB) { 1691 c.db = nil 1692 } 1693 1694 func (c *concurrentDBQueryTest) test(t testing.TB) error { 1695 rows, err := c.db.Query("SELECT|people|name|") 1696 if err != nil { 1697 t.Error(err) 1698 return err 1699 } 1700 var name string 1701 for rows.Next() { 1702 rows.Scan(&name) 1703 } 1704 rows.Close() 1705 return nil 1706 } 1707 1708 type concurrentDBExecTest struct { 1709 db *DB 1710 } 1711 1712 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) { 1713 c.db = db 1714 } 1715 1716 func (c *concurrentDBExecTest) finish(t testing.TB) { 1717 c.db = nil 1718 } 1719 1720 func (c *concurrentDBExecTest) test(t testing.TB) error { 1721 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1722 if err != nil { 1723 t.Error(err) 1724 return err 1725 } 1726 return nil 1727 } 1728 1729 type concurrentStmtQueryTest struct { 1730 db *DB 1731 stmt *Stmt 1732 } 1733 1734 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) { 1735 c.db = db 1736 var err error 1737 c.stmt, err = db.Prepare("SELECT|people|name|") 1738 if err != nil { 1739 t.Fatal(err) 1740 } 1741 } 1742 1743 func (c *concurrentStmtQueryTest) finish(t testing.TB) { 1744 if c.stmt != nil { 1745 c.stmt.Close() 1746 c.stmt = nil 1747 } 1748 c.db = nil 1749 } 1750 1751 func (c *concurrentStmtQueryTest) test(t testing.TB) error { 1752 rows, err := c.stmt.Query() 1753 if err != nil { 1754 t.Errorf("error on query: %v", err) 1755 return err 1756 } 1757 1758 var name string 1759 for rows.Next() { 1760 rows.Scan(&name) 1761 } 1762 rows.Close() 1763 return nil 1764 } 1765 1766 type concurrentStmtExecTest struct { 1767 db *DB 1768 stmt *Stmt 1769 } 1770 1771 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) { 1772 c.db = db 1773 var err error 1774 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 1775 if err != nil { 1776 t.Fatal(err) 1777 } 1778 } 1779 1780 func (c *concurrentStmtExecTest) finish(t testing.TB) { 1781 if c.stmt != nil { 1782 c.stmt.Close() 1783 c.stmt = nil 1784 } 1785 c.db = nil 1786 } 1787 1788 func (c *concurrentStmtExecTest) test(t testing.TB) error { 1789 _, err := c.stmt.Exec(3, chrisBirthday) 1790 if err != nil { 1791 t.Errorf("error on exec: %v", err) 1792 return err 1793 } 1794 return nil 1795 } 1796 1797 type concurrentTxQueryTest struct { 1798 db *DB 1799 tx *Tx 1800 } 1801 1802 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) { 1803 c.db = db 1804 var err error 1805 c.tx, err = c.db.Begin() 1806 if err != nil { 1807 t.Fatal(err) 1808 } 1809 } 1810 1811 func (c *concurrentTxQueryTest) finish(t testing.TB) { 1812 if c.tx != nil { 1813 c.tx.Rollback() 1814 c.tx = nil 1815 } 1816 c.db = nil 1817 } 1818 1819 func (c *concurrentTxQueryTest) test(t testing.TB) error { 1820 rows, err := c.db.Query("SELECT|people|name|") 1821 if err != nil { 1822 t.Error(err) 1823 return err 1824 } 1825 var name string 1826 for rows.Next() { 1827 rows.Scan(&name) 1828 } 1829 rows.Close() 1830 return nil 1831 } 1832 1833 type concurrentTxExecTest struct { 1834 db *DB 1835 tx *Tx 1836 } 1837 1838 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) { 1839 c.db = db 1840 var err error 1841 c.tx, err = c.db.Begin() 1842 if err != nil { 1843 t.Fatal(err) 1844 } 1845 } 1846 1847 func (c *concurrentTxExecTest) finish(t testing.TB) { 1848 if c.tx != nil { 1849 c.tx.Rollback() 1850 c.tx = nil 1851 } 1852 c.db = nil 1853 } 1854 1855 func (c *concurrentTxExecTest) test(t testing.TB) error { 1856 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 1857 if err != nil { 1858 t.Error(err) 1859 return err 1860 } 1861 return nil 1862 } 1863 1864 type concurrentTxStmtQueryTest struct { 1865 db *DB 1866 tx *Tx 1867 stmt *Stmt 1868 } 1869 1870 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) { 1871 c.db = db 1872 var err error 1873 c.tx, err = c.db.Begin() 1874 if err != nil { 1875 t.Fatal(err) 1876 } 1877 c.stmt, err = c.tx.Prepare("SELECT|people|name|") 1878 if err != nil { 1879 t.Fatal(err) 1880 } 1881 } 1882 1883 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) { 1884 if c.stmt != nil { 1885 c.stmt.Close() 1886 c.stmt = nil 1887 } 1888 if c.tx != nil { 1889 c.tx.Rollback() 1890 c.tx = nil 1891 } 1892 c.db = nil 1893 } 1894 1895 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error { 1896 rows, err := c.stmt.Query() 1897 if err != nil { 1898 t.Errorf("error on query: %v", err) 1899 return err 1900 } 1901 1902 var name string 1903 for rows.Next() { 1904 rows.Scan(&name) 1905 } 1906 rows.Close() 1907 return nil 1908 } 1909 1910 type concurrentTxStmtExecTest struct { 1911 db *DB 1912 tx *Tx 1913 stmt *Stmt 1914 } 1915 1916 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) { 1917 c.db = db 1918 var err error 1919 c.tx, err = c.db.Begin() 1920 if err != nil { 1921 t.Fatal(err) 1922 } 1923 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 1924 if err != nil { 1925 t.Fatal(err) 1926 } 1927 } 1928 1929 func (c *concurrentTxStmtExecTest) finish(t testing.TB) { 1930 if c.stmt != nil { 1931 c.stmt.Close() 1932 c.stmt = nil 1933 } 1934 if c.tx != nil { 1935 c.tx.Rollback() 1936 c.tx = nil 1937 } 1938 c.db = nil 1939 } 1940 1941 func (c *concurrentTxStmtExecTest) test(t testing.TB) error { 1942 _, err := c.stmt.Exec(3, chrisBirthday) 1943 if err != nil { 1944 t.Errorf("error on exec: %v", err) 1945 return err 1946 } 1947 return nil 1948 } 1949 1950 type concurrentRandomTest struct { 1951 tests []concurrentTest 1952 } 1953 1954 func (c *concurrentRandomTest) init(t testing.TB, db *DB) { 1955 c.tests = []concurrentTest{ 1956 new(concurrentDBQueryTest), 1957 new(concurrentDBExecTest), 1958 new(concurrentStmtQueryTest), 1959 new(concurrentStmtExecTest), 1960 new(concurrentTxQueryTest), 1961 new(concurrentTxExecTest), 1962 new(concurrentTxStmtQueryTest), 1963 new(concurrentTxStmtExecTest), 1964 } 1965 for _, ct := range c.tests { 1966 ct.init(t, db) 1967 } 1968 } 1969 1970 func (c *concurrentRandomTest) finish(t testing.TB) { 1971 for _, ct := range c.tests { 1972 ct.finish(t) 1973 } 1974 } 1975 1976 func (c *concurrentRandomTest) test(t testing.TB) error { 1977 ct := c.tests[rand.Intn(len(c.tests))] 1978 return ct.test(t) 1979 } 1980 1981 func doConcurrentTest(t testing.TB, ct concurrentTest) { 1982 maxProcs, numReqs := 1, 500 1983 if testing.Short() { 1984 maxProcs, numReqs = 4, 50 1985 } 1986 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 1987 1988 db := newTestDB(t, "people") 1989 defer closeDB(t, db) 1990 1991 ct.init(t, db) 1992 defer ct.finish(t) 1993 1994 var wg sync.WaitGroup 1995 wg.Add(numReqs) 1996 1997 reqs := make(chan bool) 1998 defer close(reqs) 1999 2000 for i := 0; i < maxProcs*2; i++ { 2001 go func() { 2002 for range reqs { 2003 err := ct.test(t) 2004 if err != nil { 2005 wg.Done() 2006 continue 2007 } 2008 wg.Done() 2009 } 2010 }() 2011 } 2012 2013 for i := 0; i < numReqs; i++ { 2014 reqs <- true 2015 } 2016 2017 wg.Wait() 2018 } 2019 2020 func TestIssue6081(t *testing.T) { 2021 db := newTestDB(t, "people") 2022 defer closeDB(t, db) 2023 2024 drv := db.driver.(*fakeDriver) 2025 drv.mu.Lock() 2026 opens0 := drv.openCount 2027 closes0 := drv.closeCount 2028 drv.mu.Unlock() 2029 2030 stmt, err := db.Prepare("SELECT|people|name|") 2031 if err != nil { 2032 t.Fatal(err) 2033 } 2034 rowsCloseHook = func(rows *Rows, err *error) { 2035 *err = driver.ErrBadConn 2036 } 2037 defer func() { rowsCloseHook = nil }() 2038 for i := 0; i < 10; i++ { 2039 rows, err := stmt.Query() 2040 if err != nil { 2041 t.Fatal(err) 2042 } 2043 rows.Close() 2044 } 2045 if n := len(stmt.css); n > 1 { 2046 t.Errorf("len(css slice) = %d; want <= 1", n) 2047 } 2048 stmt.Close() 2049 if n := len(stmt.css); n != 0 { 2050 t.Errorf("len(css slice) after Close = %d; want 0", n) 2051 } 2052 2053 drv.mu.Lock() 2054 opens := drv.openCount - opens0 2055 closes := drv.closeCount - closes0 2056 drv.mu.Unlock() 2057 if opens < 9 { 2058 t.Errorf("opens = %d; want >= 9", opens) 2059 } 2060 if closes < 9 { 2061 t.Errorf("closes = %d; want >= 9", closes) 2062 } 2063 } 2064 2065 func TestConcurrency(t *testing.T) { 2066 doConcurrentTest(t, new(concurrentDBQueryTest)) 2067 doConcurrentTest(t, new(concurrentDBExecTest)) 2068 doConcurrentTest(t, new(concurrentStmtQueryTest)) 2069 doConcurrentTest(t, new(concurrentStmtExecTest)) 2070 doConcurrentTest(t, new(concurrentTxQueryTest)) 2071 doConcurrentTest(t, new(concurrentTxExecTest)) 2072 doConcurrentTest(t, new(concurrentTxStmtQueryTest)) 2073 doConcurrentTest(t, new(concurrentTxStmtExecTest)) 2074 doConcurrentTest(t, new(concurrentRandomTest)) 2075 } 2076 2077 func TestConnectionLeak(t *testing.T) { 2078 db := newTestDB(t, "people") 2079 defer closeDB(t, db) 2080 // Start by opening defaultMaxIdleConns 2081 rows := make([]*Rows, defaultMaxIdleConns) 2082 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open 2083 // a new connection and we can fill the idle queue with the released 2084 // connections. 2085 db.SetMaxOpenConns(len(rows) + 1) 2086 for ii := range rows { 2087 r, err := db.Query("SELECT|people|name|") 2088 if err != nil { 2089 t.Fatal(err) 2090 } 2091 r.Next() 2092 if err := r.Err(); err != nil { 2093 t.Fatal(err) 2094 } 2095 rows[ii] = r 2096 } 2097 // Now we have defaultMaxIdleConns busy connections. Open 2098 // a new one, but wait until the busy connections are released 2099 // before returning control to DB. 2100 drv := db.driver.(*fakeDriver) 2101 drv.waitCh = make(chan struct{}, 1) 2102 drv.waitingCh = make(chan struct{}, 1) 2103 var wg sync.WaitGroup 2104 wg.Add(1) 2105 go func() { 2106 r, err := db.Query("SELECT|people|name|") 2107 if err != nil { 2108 t.Fatal(err) 2109 } 2110 r.Close() 2111 wg.Done() 2112 }() 2113 // Wait until the goroutine we've just created has started waiting. 2114 <-drv.waitingCh 2115 // Now close the busy connections. This provides a connection for 2116 // the blocked goroutine and then fills up the idle queue. 2117 for _, v := range rows { 2118 v.Close() 2119 } 2120 // At this point we give the new connection to DB. This connection is 2121 // now useless, since the idle queue is full and there are no pending 2122 // requests. DB should deal with this situation without leaking the 2123 // connection. 2124 drv.waitCh <- struct{}{} 2125 wg.Wait() 2126 } 2127 2128 func BenchmarkConcurrentDBExec(b *testing.B) { 2129 b.ReportAllocs() 2130 ct := new(concurrentDBExecTest) 2131 for i := 0; i < b.N; i++ { 2132 doConcurrentTest(b, ct) 2133 } 2134 } 2135 2136 func BenchmarkConcurrentStmtQuery(b *testing.B) { 2137 b.ReportAllocs() 2138 ct := new(concurrentStmtQueryTest) 2139 for i := 0; i < b.N; i++ { 2140 doConcurrentTest(b, ct) 2141 } 2142 } 2143 2144 func BenchmarkConcurrentStmtExec(b *testing.B) { 2145 b.ReportAllocs() 2146 ct := new(concurrentStmtExecTest) 2147 for i := 0; i < b.N; i++ { 2148 doConcurrentTest(b, ct) 2149 } 2150 } 2151 2152 func BenchmarkConcurrentTxQuery(b *testing.B) { 2153 b.ReportAllocs() 2154 ct := new(concurrentTxQueryTest) 2155 for i := 0; i < b.N; i++ { 2156 doConcurrentTest(b, ct) 2157 } 2158 } 2159 2160 func BenchmarkConcurrentTxExec(b *testing.B) { 2161 b.ReportAllocs() 2162 ct := new(concurrentTxExecTest) 2163 for i := 0; i < b.N; i++ { 2164 doConcurrentTest(b, ct) 2165 } 2166 } 2167 2168 func BenchmarkConcurrentTxStmtQuery(b *testing.B) { 2169 b.ReportAllocs() 2170 ct := new(concurrentTxStmtQueryTest) 2171 for i := 0; i < b.N; i++ { 2172 doConcurrentTest(b, ct) 2173 } 2174 } 2175 2176 func BenchmarkConcurrentTxStmtExec(b *testing.B) { 2177 b.ReportAllocs() 2178 ct := new(concurrentTxStmtExecTest) 2179 for i := 0; i < b.N; i++ { 2180 doConcurrentTest(b, ct) 2181 } 2182 } 2183 2184 func BenchmarkConcurrentRandom(b *testing.B) { 2185 b.ReportAllocs() 2186 ct := new(concurrentRandomTest) 2187 for i := 0; i < b.N; i++ { 2188 doConcurrentTest(b, ct) 2189 } 2190 } 2191 2192 func BenchmarkManyConcurrentQueries(b *testing.B) { 2193 b.ReportAllocs() 2194 // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required. 2195 const parallelism = 16 2196 2197 db := newTestDB(b, "magicquery") 2198 defer closeDB(b, db) 2199 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism) 2200 2201 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2202 if err != nil { 2203 b.Fatal(err) 2204 } 2205 defer stmt.Close() 2206 2207 b.SetParallelism(parallelism) 2208 b.RunParallel(func(pb *testing.PB) { 2209 for pb.Next() { 2210 rows, err := stmt.Query("sleep", 1) 2211 if err != nil { 2212 b.Error(err) 2213 return 2214 } 2215 rows.Close() 2216 } 2217 }) 2218 }