github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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 "context" 9 "database/sql/driver" 10 "errors" 11 "fmt" 12 "math/rand" 13 "reflect" 14 "runtime" 15 "strings" 16 "sync" 17 "sync/atomic" 18 "testing" 19 "time" 20 ) 21 22 func init() { 23 type dbConn struct { 24 db *DB 25 c *driverConn 26 } 27 freedFrom := make(map[dbConn]string) 28 var mu sync.Mutex 29 getFreedFrom := func(c dbConn) string { 30 mu.Lock() 31 defer mu.Unlock() 32 return freedFrom[c] 33 } 34 setFreedFrom := func(c dbConn, s string) { 35 mu.Lock() 36 defer mu.Unlock() 37 freedFrom[c] = s 38 } 39 putConnHook = func(db *DB, c *driverConn) { 40 idx := -1 41 for i, v := range db.freeConn { 42 if v == c { 43 idx = i 44 break 45 } 46 } 47 if idx >= 0 { 48 // print before panic, as panic may get lost due to conflicting panic 49 // (all goroutines asleep) elsewhere, since we might not unlock 50 // the mutex in freeConn here. 51 println("double free of conn. conflicts are:\nA) " + getFreedFrom(dbConn{db, c}) + "\n\nand\nB) " + stack()) 52 panic("double free of conn.") 53 } 54 setFreedFrom(dbConn{db, c}, stack()) 55 } 56 } 57 58 const fakeDBName = "foo" 59 60 var chrisBirthday = time.Unix(123456789, 0) 61 62 func newTestDB(t testing.TB, name string) *DB { 63 return newTestDBConnector(t, &fakeConnector{name: fakeDBName}, name) 64 } 65 66 func newTestDBConnector(t testing.TB, fc *fakeConnector, name string) *DB { 67 fc.name = fakeDBName 68 db := OpenDB(fc) 69 if _, err := db.Exec("WIPE"); err != nil { 70 t.Fatalf("exec wipe: %v", err) 71 } 72 if name == "people" { 73 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime") 74 exec(t, db, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1) 75 exec(t, db, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2) 76 exec(t, db, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 77 } 78 if name == "magicquery" { 79 // Magic table name and column, known by fakedb_test.go. 80 exec(t, db, "CREATE|magicquery|op=string,millis=int32") 81 exec(t, db, "INSERT|magicquery|op=sleep,millis=10") 82 } 83 if name == "tx_status" { 84 // Magic table name and column, known by fakedb_test.go. 85 exec(t, db, "CREATE|tx_status|tx_status=string") 86 exec(t, db, "INSERT|tx_status|tx_status=invalid") 87 } 88 return db 89 } 90 91 func TestOpenDB(t *testing.T) { 92 db := OpenDB(dsnConnector{dsn: fakeDBName, driver: fdriver}) 93 if db.Driver() != fdriver { 94 t.Fatalf("OpenDB should return the driver of the Connector") 95 } 96 } 97 98 func TestDriverPanic(t *testing.T) { 99 // Test that if driver panics, database/sql does not deadlock. 100 db, err := Open("test", fakeDBName) 101 if err != nil { 102 t.Fatalf("Open: %v", err) 103 } 104 expectPanic := func(name string, f func()) { 105 defer func() { 106 err := recover() 107 if err == nil { 108 t.Fatalf("%s did not panic", name) 109 } 110 }() 111 f() 112 } 113 114 expectPanic("Exec Exec", func() { db.Exec("PANIC|Exec|WIPE") }) 115 exec(t, db, "WIPE") // check not deadlocked 116 expectPanic("Exec NumInput", func() { db.Exec("PANIC|NumInput|WIPE") }) 117 exec(t, db, "WIPE") // check not deadlocked 118 expectPanic("Exec Close", func() { db.Exec("PANIC|Close|WIPE") }) 119 exec(t, db, "WIPE") // check not deadlocked 120 exec(t, db, "PANIC|Query|WIPE") // should run successfully: Exec does not call Query 121 exec(t, db, "WIPE") // check not deadlocked 122 123 exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime") 124 125 expectPanic("Query Query", func() { db.Query("PANIC|Query|SELECT|people|age,name|") }) 126 expectPanic("Query NumInput", func() { db.Query("PANIC|NumInput|SELECT|people|age,name|") }) 127 expectPanic("Query Close", func() { 128 rows, err := db.Query("PANIC|Close|SELECT|people|age,name|") 129 if err != nil { 130 t.Fatal(err) 131 } 132 rows.Close() 133 }) 134 db.Query("PANIC|Exec|SELECT|people|age,name|") // should run successfully: Query does not call Exec 135 exec(t, db, "WIPE") // check not deadlocked 136 } 137 138 func exec(t testing.TB, db *DB, query string, args ...interface{}) { 139 t.Helper() 140 _, err := db.Exec(query, args...) 141 if err != nil { 142 t.Fatalf("Exec of %q: %v", query, err) 143 } 144 } 145 146 func closeDB(t testing.TB, db *DB) { 147 if e := recover(); e != nil { 148 fmt.Printf("Panic: %v\n", e) 149 panic(e) 150 } 151 defer setHookpostCloseConn(nil) 152 setHookpostCloseConn(func(_ *fakeConn, err error) { 153 if err != nil { 154 t.Errorf("Error closing fakeConn: %v", err) 155 } 156 }) 157 db.mu.Lock() 158 for i, dc := range db.freeConn { 159 if n := len(dc.openStmt); n > 0 { 160 // Just a sanity check. This is legal in 161 // general, but if we make the tests clean up 162 // their statements first, then we can safely 163 // verify this is always zero here, and any 164 // other value is a leak. 165 t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n) 166 } 167 } 168 db.mu.Unlock() 169 170 err := db.Close() 171 if err != nil { 172 t.Fatalf("error closing DB: %v", err) 173 } 174 175 var numOpen int 176 if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool { 177 numOpen = db.numOpenConns() 178 return numOpen == 0 179 }) { 180 t.Fatalf("%d connections still open after closing DB", numOpen) 181 } 182 } 183 184 // numPrepares assumes that db has exactly 1 idle conn and returns 185 // its count of calls to Prepare 186 func numPrepares(t *testing.T, db *DB) int { 187 if n := len(db.freeConn); n != 1 { 188 t.Fatalf("free conns = %d; want 1", n) 189 } 190 return db.freeConn[0].ci.(*fakeConn).numPrepare 191 } 192 193 func (db *DB) numDeps() int { 194 db.mu.Lock() 195 defer db.mu.Unlock() 196 return len(db.dep) 197 } 198 199 // Dependencies are closed via a goroutine, so this polls waiting for 200 // numDeps to fall to want, waiting up to d. 201 func (db *DB) numDepsPollUntil(want int, d time.Duration) int { 202 deadline := time.Now().Add(d) 203 for { 204 n := db.numDeps() 205 if n <= want || time.Now().After(deadline) { 206 return n 207 } 208 time.Sleep(50 * time.Millisecond) 209 } 210 } 211 212 func (db *DB) numFreeConns() int { 213 db.mu.Lock() 214 defer db.mu.Unlock() 215 return len(db.freeConn) 216 } 217 218 func (db *DB) numOpenConns() int { 219 db.mu.Lock() 220 defer db.mu.Unlock() 221 return db.numOpen 222 } 223 224 // clearAllConns closes all connections in db. 225 func (db *DB) clearAllConns(t *testing.T) { 226 db.SetMaxIdleConns(0) 227 228 if g, w := db.numFreeConns(), 0; g != w { 229 t.Errorf("free conns = %d; want %d", g, w) 230 } 231 232 if n := db.numDepsPollUntil(0, time.Second); n > 0 { 233 t.Errorf("number of dependencies = %d; expected 0", n) 234 db.dumpDeps(t) 235 } 236 } 237 238 func (db *DB) dumpDeps(t *testing.T) { 239 for fc := range db.dep { 240 db.dumpDep(t, 0, fc, map[finalCloser]bool{}) 241 } 242 } 243 244 func (db *DB) dumpDep(t *testing.T, depth int, dep finalCloser, seen map[finalCloser]bool) { 245 seen[dep] = true 246 indent := strings.Repeat(" ", depth) 247 ds := db.dep[dep] 248 for k := range ds { 249 t.Logf("%s%T (%p) waiting for -> %T (%p)", indent, dep, dep, k, k) 250 if fc, ok := k.(finalCloser); ok { 251 if !seen[fc] { 252 db.dumpDep(t, depth+1, fc, seen) 253 } 254 } 255 } 256 } 257 258 func TestQuery(t *testing.T) { 259 db := newTestDB(t, "people") 260 defer closeDB(t, db) 261 prepares0 := numPrepares(t, db) 262 rows, err := db.Query("SELECT|people|age,name|") 263 if err != nil { 264 t.Fatalf("Query: %v", err) 265 } 266 type row struct { 267 age int 268 name string 269 } 270 got := []row{} 271 for rows.Next() { 272 var r row 273 err = rows.Scan(&r.age, &r.name) 274 if err != nil { 275 t.Fatalf("Scan: %v", err) 276 } 277 got = append(got, r) 278 } 279 err = rows.Err() 280 if err != nil { 281 t.Fatalf("Err: %v", err) 282 } 283 want := []row{ 284 {age: 1, name: "Alice"}, 285 {age: 2, name: "Bob"}, 286 {age: 3, name: "Chris"}, 287 } 288 if !reflect.DeepEqual(got, want) { 289 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 290 } 291 292 // And verify that the final rows.Next() call, which hit EOF, 293 // also closed the rows connection. 294 if n := db.numFreeConns(); n != 1 { 295 t.Fatalf("free conns after query hitting EOF = %d; want 1", n) 296 } 297 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 298 t.Errorf("executed %d Prepare statements; want 1", prepares) 299 } 300 } 301 302 // TestQueryContext tests canceling the context while scanning the rows. 303 func TestQueryContext(t *testing.T) { 304 db := newTestDB(t, "people") 305 defer closeDB(t, db) 306 prepares0 := numPrepares(t, db) 307 308 ctx, cancel := context.WithCancel(context.Background()) 309 defer cancel() 310 311 rows, err := db.QueryContext(ctx, "SELECT|people|age,name|") 312 if err != nil { 313 t.Fatalf("Query: %v", err) 314 } 315 type row struct { 316 age int 317 name string 318 } 319 got := []row{} 320 index := 0 321 for rows.Next() { 322 if index == 2 { 323 cancel() 324 waitForRowsClose(t, rows, 5*time.Second) 325 } 326 var r row 327 err = rows.Scan(&r.age, &r.name) 328 if err != nil { 329 if index == 2 { 330 break 331 } 332 t.Fatalf("Scan: %v", err) 333 } 334 if index == 2 && err != context.Canceled { 335 t.Fatalf("Scan: %v; want context.Canceled", err) 336 } 337 got = append(got, r) 338 index++ 339 } 340 select { 341 case <-ctx.Done(): 342 if err := ctx.Err(); err != context.Canceled { 343 t.Fatalf("context err = %v; want context.Canceled", err) 344 } 345 default: 346 t.Fatalf("context err = nil; want context.Canceled") 347 } 348 want := []row{ 349 {age: 1, name: "Alice"}, 350 {age: 2, name: "Bob"}, 351 } 352 if !reflect.DeepEqual(got, want) { 353 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 354 } 355 356 // And verify that the final rows.Next() call, which hit EOF, 357 // also closed the rows connection. 358 waitForRowsClose(t, rows, 5*time.Second) 359 waitForFree(t, db, 5*time.Second, 1) 360 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 361 t.Errorf("executed %d Prepare statements; want 1", prepares) 362 } 363 } 364 365 func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool { 366 deadline := time.Now().Add(waitFor) 367 for time.Now().Before(deadline) { 368 if fn() { 369 return true 370 } 371 time.Sleep(checkEvery) 372 } 373 return false 374 } 375 376 // waitForFree checks db.numFreeConns until either it equals want or 377 // the maxWait time elapses. 378 func waitForFree(t *testing.T, db *DB, maxWait time.Duration, want int) { 379 var numFree int 380 if !waitCondition(maxWait, 5*time.Millisecond, func() bool { 381 numFree = db.numFreeConns() 382 return numFree == want 383 }) { 384 t.Fatalf("free conns after hitting EOF = %d; want %d", numFree, want) 385 } 386 } 387 388 func waitForRowsClose(t *testing.T, rows *Rows, maxWait time.Duration) { 389 if !waitCondition(maxWait, 5*time.Millisecond, func() bool { 390 rows.closemu.RLock() 391 defer rows.closemu.RUnlock() 392 return rows.closed 393 }) { 394 t.Fatal("failed to close rows") 395 } 396 } 397 398 // TestQueryContextWait ensures that rows and all internal statements are closed when 399 // a query context is closed during execution. 400 func TestQueryContextWait(t *testing.T) { 401 db := newTestDB(t, "people") 402 defer closeDB(t, db) 403 prepares0 := numPrepares(t, db) 404 405 // TODO(kardianos): convert this from using a timeout to using an explicit 406 // cancel when the query signals that it is "executing" the query. 407 ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond) 408 defer cancel() 409 410 // This will trigger the *fakeConn.Prepare method which will take time 411 // performing the query. The ctxDriverPrepare func will check the context 412 // after this and close the rows and return an error. 413 _, err := db.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|") 414 if err != context.DeadlineExceeded { 415 t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) 416 } 417 418 // Verify closed rows connection after error condition. 419 waitForFree(t, db, 5*time.Second, 1) 420 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 421 // TODO(kardianos): if the context timeouts before the db.QueryContext 422 // executes this check may fail. After adjusting how the context 423 // is canceled above revert this back to a Fatal error. 424 t.Logf("executed %d Prepare statements; want 1", prepares) 425 } 426 } 427 428 // TestTxContextWait tests the transaction behavior when the tx context is canceled 429 // during execution of the query. 430 func TestTxContextWait(t *testing.T) { 431 db := newTestDB(t, "people") 432 defer closeDB(t, db) 433 434 ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond) 435 defer cancel() 436 437 tx, err := db.BeginTx(ctx, nil) 438 if err != nil { 439 // Guard against the context being canceled before BeginTx completes. 440 if err == context.DeadlineExceeded { 441 t.Skip("tx context canceled prior to first use") 442 } 443 t.Fatal(err) 444 } 445 tx.keepConnOnRollback = false 446 447 // This will trigger the *fakeConn.Prepare method which will take time 448 // performing the query. The ctxDriverPrepare func will check the context 449 // after this and close the rows and return an error. 450 _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|") 451 if err != context.DeadlineExceeded { 452 t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) 453 } 454 455 waitForFree(t, db, 5*time.Second, 0) 456 } 457 458 // TestTxContextWaitNoDiscard is the same as TestTxContextWait, but should not discard 459 // the final connection. 460 func TestTxContextWaitNoDiscard(t *testing.T) { 461 db := newTestDB(t, "people") 462 defer closeDB(t, db) 463 464 ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond) 465 defer cancel() 466 467 tx, err := db.BeginTx(ctx, nil) 468 if err != nil { 469 // Guard against the context being canceled before BeginTx completes. 470 if err == context.DeadlineExceeded { 471 t.Skip("tx context canceled prior to first use") 472 } 473 t.Fatal(err) 474 } 475 476 // This will trigger the *fakeConn.Prepare method which will take time 477 // performing the query. The ctxDriverPrepare func will check the context 478 // after this and close the rows and return an error. 479 _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|") 480 if err != context.DeadlineExceeded { 481 t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err) 482 } 483 484 waitForFree(t, db, 5*time.Second, 1) 485 } 486 487 // TestUnsupportedOptions checks that the database fails when a driver that 488 // doesn't implement ConnBeginTx is used with non-default options and an 489 // un-cancellable context. 490 func TestUnsupportedOptions(t *testing.T) { 491 db := newTestDB(t, "people") 492 defer closeDB(t, db) 493 _, err := db.BeginTx(context.Background(), &TxOptions{ 494 Isolation: LevelSerializable, ReadOnly: true, 495 }) 496 if err == nil { 497 t.Fatal("expected error when using unsupported options, got nil") 498 } 499 } 500 501 func TestMultiResultSetQuery(t *testing.T) { 502 db := newTestDB(t, "people") 503 defer closeDB(t, db) 504 prepares0 := numPrepares(t, db) 505 rows, err := db.Query("SELECT|people|age,name|;SELECT|people|name|") 506 if err != nil { 507 t.Fatalf("Query: %v", err) 508 } 509 type row1 struct { 510 age int 511 name string 512 } 513 type row2 struct { 514 name string 515 } 516 got1 := []row1{} 517 for rows.Next() { 518 var r row1 519 err = rows.Scan(&r.age, &r.name) 520 if err != nil { 521 t.Fatalf("Scan: %v", err) 522 } 523 got1 = append(got1, r) 524 } 525 err = rows.Err() 526 if err != nil { 527 t.Fatalf("Err: %v", err) 528 } 529 want1 := []row1{ 530 {age: 1, name: "Alice"}, 531 {age: 2, name: "Bob"}, 532 {age: 3, name: "Chris"}, 533 } 534 if !reflect.DeepEqual(got1, want1) { 535 t.Errorf("mismatch.\n got1: %#v\nwant: %#v", got1, want1) 536 } 537 538 if !rows.NextResultSet() { 539 t.Errorf("expected another result set") 540 } 541 542 got2 := []row2{} 543 for rows.Next() { 544 var r row2 545 err = rows.Scan(&r.name) 546 if err != nil { 547 t.Fatalf("Scan: %v", err) 548 } 549 got2 = append(got2, r) 550 } 551 err = rows.Err() 552 if err != nil { 553 t.Fatalf("Err: %v", err) 554 } 555 want2 := []row2{ 556 {name: "Alice"}, 557 {name: "Bob"}, 558 {name: "Chris"}, 559 } 560 if !reflect.DeepEqual(got2, want2) { 561 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got2, want2) 562 } 563 if rows.NextResultSet() { 564 t.Errorf("expected no more result sets") 565 } 566 567 // And verify that the final rows.Next() call, which hit EOF, 568 // also closed the rows connection. 569 waitForFree(t, db, 5*time.Second, 1) 570 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 571 t.Errorf("executed %d Prepare statements; want 1", prepares) 572 } 573 } 574 575 func TestQueryNamedArg(t *testing.T) { 576 db := newTestDB(t, "people") 577 defer closeDB(t, db) 578 prepares0 := numPrepares(t, db) 579 rows, err := db.Query( 580 // Ensure the name and age parameters only match on placeholder name, not position. 581 "SELECT|people|age,name|name=?name,age=?age", 582 Named("age", 2), 583 Named("name", "Bob"), 584 ) 585 if err != nil { 586 t.Fatalf("Query: %v", err) 587 } 588 type row struct { 589 age int 590 name string 591 } 592 got := []row{} 593 for rows.Next() { 594 var r row 595 err = rows.Scan(&r.age, &r.name) 596 if err != nil { 597 t.Fatalf("Scan: %v", err) 598 } 599 got = append(got, r) 600 } 601 err = rows.Err() 602 if err != nil { 603 t.Fatalf("Err: %v", err) 604 } 605 want := []row{ 606 {age: 2, name: "Bob"}, 607 } 608 if !reflect.DeepEqual(got, want) { 609 t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) 610 } 611 612 // And verify that the final rows.Next() call, which hit EOF, 613 // also closed the rows connection. 614 if n := db.numFreeConns(); n != 1 { 615 t.Fatalf("free conns after query hitting EOF = %d; want 1", n) 616 } 617 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 618 t.Errorf("executed %d Prepare statements; want 1", prepares) 619 } 620 } 621 622 func TestPoolExhaustOnCancel(t *testing.T) { 623 if testing.Short() { 624 t.Skip("long test") 625 } 626 627 max := 3 628 var saturate, saturateDone sync.WaitGroup 629 saturate.Add(max) 630 saturateDone.Add(max) 631 632 donePing := make(chan bool) 633 state := 0 634 635 // waiter will be called for all queries, including 636 // initial setup queries. The state is only assigned when 637 // no queries are made. 638 // 639 // Only allow the first batch of queries to finish once the 640 // second batch of Ping queries have finished. 641 waiter := func(ctx context.Context) { 642 switch state { 643 case 0: 644 // Nothing. Initial database setup. 645 case 1: 646 saturate.Done() 647 select { 648 case <-ctx.Done(): 649 case <-donePing: 650 } 651 case 2: 652 } 653 } 654 db := newTestDBConnector(t, &fakeConnector{waiter: waiter}, "people") 655 defer closeDB(t, db) 656 657 db.SetMaxOpenConns(max) 658 659 // First saturate the connection pool. 660 // Then start new requests for a connection that is cancelled after it is requested. 661 662 state = 1 663 for i := 0; i < max; i++ { 664 go func() { 665 rows, err := db.Query("SELECT|people|name,photo|") 666 if err != nil { 667 t.Errorf("Query: %v", err) 668 return 669 } 670 rows.Close() 671 saturateDone.Done() 672 }() 673 } 674 675 saturate.Wait() 676 if t.Failed() { 677 t.FailNow() 678 } 679 state = 2 680 681 // Now cancel the request while it is waiting. 682 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 683 defer cancel() 684 685 for i := 0; i < max; i++ { 686 ctxReq, cancelReq := context.WithCancel(ctx) 687 go func() { 688 time.Sleep(100 * time.Millisecond) 689 cancelReq() 690 }() 691 err := db.PingContext(ctxReq) 692 if err != context.Canceled { 693 t.Fatalf("PingContext (Exhaust): %v", err) 694 } 695 } 696 close(donePing) 697 saturateDone.Wait() 698 699 // Now try to open a normal connection. 700 err := db.PingContext(ctx) 701 if err != nil { 702 t.Fatalf("PingContext (Normal): %v", err) 703 } 704 } 705 706 func TestRowsColumns(t *testing.T) { 707 db := newTestDB(t, "people") 708 defer closeDB(t, db) 709 rows, err := db.Query("SELECT|people|age,name|") 710 if err != nil { 711 t.Fatalf("Query: %v", err) 712 } 713 cols, err := rows.Columns() 714 if err != nil { 715 t.Fatalf("Columns: %v", err) 716 } 717 want := []string{"age", "name"} 718 if !reflect.DeepEqual(cols, want) { 719 t.Errorf("got %#v; want %#v", cols, want) 720 } 721 if err := rows.Close(); err != nil { 722 t.Errorf("error closing rows: %s", err) 723 } 724 } 725 726 func TestRowsColumnTypes(t *testing.T) { 727 db := newTestDB(t, "people") 728 defer closeDB(t, db) 729 rows, err := db.Query("SELECT|people|age,name|") 730 if err != nil { 731 t.Fatalf("Query: %v", err) 732 } 733 tt, err := rows.ColumnTypes() 734 if err != nil { 735 t.Fatalf("ColumnTypes: %v", err) 736 } 737 738 types := make([]reflect.Type, len(tt)) 739 for i, tp := range tt { 740 st := tp.ScanType() 741 if st == nil { 742 t.Errorf("scantype is null for column %q", tp.Name()) 743 continue 744 } 745 types[i] = st 746 } 747 values := make([]interface{}, len(tt)) 748 for i := range values { 749 values[i] = reflect.New(types[i]).Interface() 750 } 751 ct := 0 752 for rows.Next() { 753 err = rows.Scan(values...) 754 if err != nil { 755 t.Fatalf("failed to scan values in %v", err) 756 } 757 if ct == 1 { 758 if age := *values[0].(*int32); age != 2 { 759 t.Errorf("Expected 2, got %v", age) 760 } 761 if name := *values[1].(*string); name != "Bob" { 762 t.Errorf("Expected Bob, got %v", name) 763 } 764 } 765 ct++ 766 } 767 if ct != 3 { 768 t.Errorf("expected 3 rows, got %d", ct) 769 } 770 771 if err := rows.Close(); err != nil { 772 t.Errorf("error closing rows: %s", err) 773 } 774 } 775 776 func TestQueryRow(t *testing.T) { 777 db := newTestDB(t, "people") 778 defer closeDB(t, db) 779 var name string 780 var age int 781 var birthday time.Time 782 783 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age) 784 if err == nil || !strings.Contains(err.Error(), "expected 2 destination arguments") { 785 t.Errorf("expected error from wrong number of arguments; actually got: %v", err) 786 } 787 788 err = db.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday) 789 if err != nil || !birthday.Equal(chrisBirthday) { 790 t.Errorf("chris birthday = %v, err = %v; want %v", birthday, err, chrisBirthday) 791 } 792 793 err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name) 794 if err != nil { 795 t.Fatalf("age QueryRow+Scan: %v", err) 796 } 797 if name != "Bob" { 798 t.Errorf("expected name Bob, got %q", name) 799 } 800 if age != 2 { 801 t.Errorf("expected age 2, got %d", age) 802 } 803 804 err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name) 805 if err != nil { 806 t.Fatalf("name QueryRow+Scan: %v", err) 807 } 808 if name != "Alice" { 809 t.Errorf("expected name Alice, got %q", name) 810 } 811 if age != 1 { 812 t.Errorf("expected age 1, got %d", age) 813 } 814 815 var photo []byte 816 err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) 817 if err != nil { 818 t.Fatalf("photo QueryRow+Scan: %v", err) 819 } 820 want := []byte("APHOTO") 821 if !reflect.DeepEqual(photo, want) { 822 t.Errorf("photo = %q; want %q", photo, want) 823 } 824 } 825 826 func TestRowErr(t *testing.T) { 827 db := newTestDB(t, "people") 828 829 err := db.QueryRowContext(context.Background(), "SELECT|people|bdate|age=?", 3).Err() 830 if err != nil { 831 t.Errorf("Unexpected err = %v; want %v", err, nil) 832 } 833 834 ctx, cancel := context.WithCancel(context.Background()) 835 cancel() 836 837 err = db.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 3).Err() 838 exp := "context canceled" 839 if err == nil || !strings.Contains(err.Error(), exp) { 840 t.Errorf("Expected err = %v; got %v", exp, err) 841 } 842 } 843 844 func TestTxRollbackCommitErr(t *testing.T) { 845 db := newTestDB(t, "people") 846 defer closeDB(t, db) 847 848 tx, err := db.Begin() 849 if err != nil { 850 t.Fatal(err) 851 } 852 err = tx.Rollback() 853 if err != nil { 854 t.Errorf("expected nil error from Rollback; got %v", err) 855 } 856 err = tx.Commit() 857 if err != ErrTxDone { 858 t.Errorf("expected %q from Commit; got %q", ErrTxDone, err) 859 } 860 861 tx, err = db.Begin() 862 if err != nil { 863 t.Fatal(err) 864 } 865 err = tx.Commit() 866 if err != nil { 867 t.Errorf("expected nil error from Commit; got %v", err) 868 } 869 err = tx.Rollback() 870 if err != ErrTxDone { 871 t.Errorf("expected %q from Rollback; got %q", ErrTxDone, err) 872 } 873 } 874 875 func TestStatementErrorAfterClose(t *testing.T) { 876 db := newTestDB(t, "people") 877 defer closeDB(t, db) 878 stmt, err := db.Prepare("SELECT|people|age|name=?") 879 if err != nil { 880 t.Fatalf("Prepare: %v", err) 881 } 882 err = stmt.Close() 883 if err != nil { 884 t.Fatalf("Close: %v", err) 885 } 886 var name string 887 err = stmt.QueryRow("foo").Scan(&name) 888 if err == nil { 889 t.Errorf("expected error from QueryRow.Scan after Stmt.Close") 890 } 891 } 892 893 func TestStatementQueryRow(t *testing.T) { 894 db := newTestDB(t, "people") 895 defer closeDB(t, db) 896 stmt, err := db.Prepare("SELECT|people|age|name=?") 897 if err != nil { 898 t.Fatalf("Prepare: %v", err) 899 } 900 defer stmt.Close() 901 var age int 902 for n, tt := range []struct { 903 name string 904 want int 905 }{ 906 {"Alice", 1}, 907 {"Bob", 2}, 908 {"Chris", 3}, 909 } { 910 if err := stmt.QueryRow(tt.name).Scan(&age); err != nil { 911 t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err) 912 } else if age != tt.want { 913 t.Errorf("%d: age=%d, want %d", n, age, tt.want) 914 } 915 } 916 } 917 918 type stubDriverStmt struct { 919 err error 920 } 921 922 func (s stubDriverStmt) Close() error { 923 return s.err 924 } 925 926 func (s stubDriverStmt) NumInput() int { 927 return -1 928 } 929 930 func (s stubDriverStmt) Exec(args []driver.Value) (driver.Result, error) { 931 return nil, nil 932 } 933 934 func (s stubDriverStmt) Query(args []driver.Value) (driver.Rows, error) { 935 return nil, nil 936 } 937 938 // golang.org/issue/12798 939 func TestStatementClose(t *testing.T) { 940 want := errors.New("STMT ERROR") 941 942 tests := []struct { 943 stmt *Stmt 944 msg string 945 }{ 946 {&Stmt{stickyErr: want}, "stickyErr not propagated"}, 947 {&Stmt{cg: &Tx{}, cgds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"}, 948 } 949 for _, test := range tests { 950 if err := test.stmt.Close(); err != want { 951 t.Errorf("%s. Got stmt.Close() = %v, want = %v", test.msg, err, want) 952 } 953 } 954 } 955 956 // golang.org/issue/3734 957 func TestStatementQueryRowConcurrent(t *testing.T) { 958 db := newTestDB(t, "people") 959 defer closeDB(t, db) 960 stmt, err := db.Prepare("SELECT|people|age|name=?") 961 if err != nil { 962 t.Fatalf("Prepare: %v", err) 963 } 964 defer stmt.Close() 965 966 const n = 10 967 ch := make(chan error, n) 968 for i := 0; i < n; i++ { 969 go func() { 970 var age int 971 err := stmt.QueryRow("Alice").Scan(&age) 972 if err == nil && age != 1 { 973 err = fmt.Errorf("unexpected age %d", age) 974 } 975 ch <- err 976 }() 977 } 978 for i := 0; i < n; i++ { 979 if err := <-ch; err != nil { 980 t.Error(err) 981 } 982 } 983 } 984 985 // just a test of fakedb itself 986 func TestBogusPreboundParameters(t *testing.T) { 987 db := newTestDB(t, "foo") 988 defer closeDB(t, db) 989 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 990 _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion") 991 if err == nil { 992 t.Fatalf("expected error") 993 } 994 if err.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` { 995 t.Errorf("unexpected error: %v", err) 996 } 997 } 998 999 func TestExec(t *testing.T) { 1000 db := newTestDB(t, "foo") 1001 defer closeDB(t, db) 1002 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1003 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1004 if err != nil { 1005 t.Errorf("Stmt, err = %v, %v", stmt, err) 1006 } 1007 defer stmt.Close() 1008 1009 type execTest struct { 1010 args []interface{} 1011 wantErr string 1012 } 1013 execTests := []execTest{ 1014 // Okay: 1015 {[]interface{}{"Brad", 31}, ""}, 1016 {[]interface{}{"Brad", int64(31)}, ""}, 1017 {[]interface{}{"Bob", "32"}, ""}, 1018 {[]interface{}{7, 9}, ""}, 1019 1020 // Invalid conversions: 1021 {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"}, 1022 {[]interface{}{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`}, 1023 1024 // Wrong number of args: 1025 {[]interface{}{}, "sql: expected 2 arguments, got 0"}, 1026 {[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"}, 1027 } 1028 for n, et := range execTests { 1029 _, err := stmt.Exec(et.args...) 1030 errStr := "" 1031 if err != nil { 1032 errStr = err.Error() 1033 } 1034 if errStr != et.wantErr { 1035 t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q", 1036 n, et.args, errStr, et.wantErr) 1037 } 1038 } 1039 } 1040 1041 func TestTxPrepare(t *testing.T) { 1042 db := newTestDB(t, "") 1043 defer closeDB(t, db) 1044 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1045 tx, err := db.Begin() 1046 if err != nil { 1047 t.Fatalf("Begin = %v", err) 1048 } 1049 stmt, err := tx.Prepare("INSERT|t1|name=?,age=?") 1050 if err != nil { 1051 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1052 } 1053 defer stmt.Close() 1054 _, err = stmt.Exec("Bobby", 7) 1055 if err != nil { 1056 t.Fatalf("Exec = %v", err) 1057 } 1058 err = tx.Commit() 1059 if err != nil { 1060 t.Fatalf("Commit = %v", err) 1061 } 1062 // Commit() should have closed the statement 1063 if !stmt.closed { 1064 t.Fatal("Stmt not closed after Commit") 1065 } 1066 } 1067 1068 func TestTxStmt(t *testing.T) { 1069 db := newTestDB(t, "") 1070 defer closeDB(t, db) 1071 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1072 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1073 if err != nil { 1074 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1075 } 1076 defer stmt.Close() 1077 tx, err := db.Begin() 1078 if err != nil { 1079 t.Fatalf("Begin = %v", err) 1080 } 1081 txs := tx.Stmt(stmt) 1082 defer txs.Close() 1083 _, err = txs.Exec("Bobby", 7) 1084 if err != nil { 1085 t.Fatalf("Exec = %v", err) 1086 } 1087 err = tx.Commit() 1088 if err != nil { 1089 t.Fatalf("Commit = %v", err) 1090 } 1091 // Commit() should have closed the statement 1092 if !txs.closed { 1093 t.Fatal("Stmt not closed after Commit") 1094 } 1095 } 1096 1097 func TestTxStmtPreparedOnce(t *testing.T) { 1098 db := newTestDB(t, "") 1099 defer closeDB(t, db) 1100 exec(t, db, "CREATE|t1|name=string,age=int32") 1101 1102 prepares0 := numPrepares(t, db) 1103 1104 // db.Prepare increments numPrepares. 1105 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1106 if err != nil { 1107 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1108 } 1109 defer stmt.Close() 1110 1111 tx, err := db.Begin() 1112 if err != nil { 1113 t.Fatalf("Begin = %v", err) 1114 } 1115 1116 txs1 := tx.Stmt(stmt) 1117 txs2 := tx.Stmt(stmt) 1118 1119 _, err = txs1.Exec("Go", 7) 1120 if err != nil { 1121 t.Fatalf("Exec = %v", err) 1122 } 1123 txs1.Close() 1124 1125 _, err = txs2.Exec("Gopher", 8) 1126 if err != nil { 1127 t.Fatalf("Exec = %v", err) 1128 } 1129 txs2.Close() 1130 1131 err = tx.Commit() 1132 if err != nil { 1133 t.Fatalf("Commit = %v", err) 1134 } 1135 1136 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 1137 t.Errorf("executed %d Prepare statements; want 1", prepares) 1138 } 1139 } 1140 1141 func TestTxStmtClosedRePrepares(t *testing.T) { 1142 db := newTestDB(t, "") 1143 defer closeDB(t, db) 1144 exec(t, db, "CREATE|t1|name=string,age=int32") 1145 1146 prepares0 := numPrepares(t, db) 1147 1148 // db.Prepare increments numPrepares. 1149 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1150 if err != nil { 1151 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1152 } 1153 tx, err := db.Begin() 1154 if err != nil { 1155 t.Fatalf("Begin = %v", err) 1156 } 1157 err = stmt.Close() 1158 if err != nil { 1159 t.Fatalf("stmt.Close() = %v", err) 1160 } 1161 // tx.Stmt increments numPrepares because stmt is closed. 1162 txs := tx.Stmt(stmt) 1163 if txs.stickyErr != nil { 1164 t.Fatal(txs.stickyErr) 1165 } 1166 if txs.parentStmt != nil { 1167 t.Fatal("expected nil parentStmt") 1168 } 1169 _, err = txs.Exec(`Eric`, 82) 1170 if err != nil { 1171 t.Fatalf("txs.Exec = %v", err) 1172 } 1173 1174 err = txs.Close() 1175 if err != nil { 1176 t.Fatalf("txs.Close = %v", err) 1177 } 1178 1179 tx.Rollback() 1180 1181 if prepares := numPrepares(t, db) - prepares0; prepares != 2 { 1182 t.Errorf("executed %d Prepare statements; want 2", prepares) 1183 } 1184 } 1185 1186 func TestParentStmtOutlivesTxStmt(t *testing.T) { 1187 db := newTestDB(t, "") 1188 defer closeDB(t, db) 1189 exec(t, db, "CREATE|t1|name=string,age=int32") 1190 1191 // Make sure everything happens on the same connection. 1192 db.SetMaxOpenConns(1) 1193 1194 prepares0 := numPrepares(t, db) 1195 1196 // db.Prepare increments numPrepares. 1197 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1198 if err != nil { 1199 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1200 } 1201 defer stmt.Close() 1202 tx, err := db.Begin() 1203 if err != nil { 1204 t.Fatalf("Begin = %v", err) 1205 } 1206 txs := tx.Stmt(stmt) 1207 if len(stmt.css) != 1 { 1208 t.Fatalf("len(stmt.css) = %v; want 1", len(stmt.css)) 1209 } 1210 err = txs.Close() 1211 if err != nil { 1212 t.Fatalf("txs.Close() = %v", err) 1213 } 1214 err = tx.Rollback() 1215 if err != nil { 1216 t.Fatalf("tx.Rollback() = %v", err) 1217 } 1218 // txs must not be valid. 1219 _, err = txs.Exec("Suzan", 30) 1220 if err == nil { 1221 t.Fatalf("txs.Exec(), expected err") 1222 } 1223 // Stmt must still be valid. 1224 _, err = stmt.Exec("Janina", 25) 1225 if err != nil { 1226 t.Fatalf("stmt.Exec() = %v", err) 1227 } 1228 1229 if prepares := numPrepares(t, db) - prepares0; prepares != 1 { 1230 t.Errorf("executed %d Prepare statements; want 1", prepares) 1231 } 1232 } 1233 1234 // Test that tx.Stmt called with a statement already 1235 // associated with tx as argument re-prepares the same 1236 // statement again. 1237 func TestTxStmtFromTxStmtRePrepares(t *testing.T) { 1238 db := newTestDB(t, "") 1239 defer closeDB(t, db) 1240 exec(t, db, "CREATE|t1|name=string,age=int32") 1241 prepares0 := numPrepares(t, db) 1242 // db.Prepare increments numPrepares. 1243 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1244 if err != nil { 1245 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1246 } 1247 defer stmt.Close() 1248 1249 tx, err := db.Begin() 1250 if err != nil { 1251 t.Fatalf("Begin = %v", err) 1252 } 1253 txs1 := tx.Stmt(stmt) 1254 1255 // tx.Stmt(txs1) increments numPrepares because txs1 already 1256 // belongs to a transaction (albeit the same transaction). 1257 txs2 := tx.Stmt(txs1) 1258 if txs2.stickyErr != nil { 1259 t.Fatal(txs2.stickyErr) 1260 } 1261 if txs2.parentStmt != nil { 1262 t.Fatal("expected nil parentStmt") 1263 } 1264 _, err = txs2.Exec(`Eric`, 82) 1265 if err != nil { 1266 t.Fatal(err) 1267 } 1268 1269 err = txs1.Close() 1270 if err != nil { 1271 t.Fatalf("txs1.Close = %v", err) 1272 } 1273 err = txs2.Close() 1274 if err != nil { 1275 t.Fatalf("txs1.Close = %v", err) 1276 } 1277 err = tx.Rollback() 1278 if err != nil { 1279 t.Fatalf("tx.Rollback = %v", err) 1280 } 1281 1282 if prepares := numPrepares(t, db) - prepares0; prepares != 2 { 1283 t.Errorf("executed %d Prepare statements; want 2", prepares) 1284 } 1285 } 1286 1287 // Issue: https://golang.org/issue/2784 1288 // This test didn't fail before because we got lucky with the fakedb driver. 1289 // It was failing, and now not, in github.com/bradfitz/go-sql-test 1290 func TestTxQuery(t *testing.T) { 1291 db := newTestDB(t, "") 1292 defer closeDB(t, db) 1293 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1294 exec(t, db, "INSERT|t1|name=Alice") 1295 1296 tx, err := db.Begin() 1297 if err != nil { 1298 t.Fatal(err) 1299 } 1300 defer tx.Rollback() 1301 1302 r, err := tx.Query("SELECT|t1|name|") 1303 if err != nil { 1304 t.Fatal(err) 1305 } 1306 defer r.Close() 1307 1308 if !r.Next() { 1309 if r.Err() != nil { 1310 t.Fatal(r.Err()) 1311 } 1312 t.Fatal("expected one row") 1313 } 1314 1315 var x string 1316 err = r.Scan(&x) 1317 if err != nil { 1318 t.Fatal(err) 1319 } 1320 } 1321 1322 func TestTxQueryInvalid(t *testing.T) { 1323 db := newTestDB(t, "") 1324 defer closeDB(t, db) 1325 1326 tx, err := db.Begin() 1327 if err != nil { 1328 t.Fatal(err) 1329 } 1330 defer tx.Rollback() 1331 1332 _, err = tx.Query("SELECT|t1|name|") 1333 if err == nil { 1334 t.Fatal("Error expected") 1335 } 1336 } 1337 1338 // Tests fix for issue 4433, that retries in Begin happen when 1339 // conn.Begin() returns ErrBadConn 1340 func TestTxErrBadConn(t *testing.T) { 1341 db, err := Open("test", fakeDBName+";badConn") 1342 if err != nil { 1343 t.Fatalf("Open: %v", err) 1344 } 1345 if _, err := db.Exec("WIPE"); err != nil { 1346 t.Fatalf("exec wipe: %v", err) 1347 } 1348 defer closeDB(t, db) 1349 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 1350 stmt, err := db.Prepare("INSERT|t1|name=?,age=?") 1351 if err != nil { 1352 t.Fatalf("Stmt, err = %v, %v", stmt, err) 1353 } 1354 defer stmt.Close() 1355 tx, err := db.Begin() 1356 if err != nil { 1357 t.Fatalf("Begin = %v", err) 1358 } 1359 txs := tx.Stmt(stmt) 1360 defer txs.Close() 1361 _, err = txs.Exec("Bobby", 7) 1362 if err != nil { 1363 t.Fatalf("Exec = %v", err) 1364 } 1365 err = tx.Commit() 1366 if err != nil { 1367 t.Fatalf("Commit = %v", err) 1368 } 1369 } 1370 1371 func TestConnQuery(t *testing.T) { 1372 db := newTestDB(t, "people") 1373 defer closeDB(t, db) 1374 1375 ctx, cancel := context.WithCancel(context.Background()) 1376 defer cancel() 1377 conn, err := db.Conn(ctx) 1378 if err != nil { 1379 t.Fatal(err) 1380 } 1381 conn.dc.ci.(*fakeConn).skipDirtySession = true 1382 defer conn.Close() 1383 1384 var name string 1385 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", 3).Scan(&name) 1386 if err != nil { 1387 t.Fatal(err) 1388 } 1389 if name != "Chris" { 1390 t.Fatalf("unexpected result, got %q want Chris", name) 1391 } 1392 1393 err = conn.PingContext(ctx) 1394 if err != nil { 1395 t.Fatal(err) 1396 } 1397 } 1398 1399 func TestConnRaw(t *testing.T) { 1400 db := newTestDB(t, "people") 1401 defer closeDB(t, db) 1402 1403 ctx, cancel := context.WithCancel(context.Background()) 1404 defer cancel() 1405 conn, err := db.Conn(ctx) 1406 if err != nil { 1407 t.Fatal(err) 1408 } 1409 conn.dc.ci.(*fakeConn).skipDirtySession = true 1410 defer conn.Close() 1411 1412 sawFunc := false 1413 err = conn.Raw(func(dc interface{}) error { 1414 sawFunc = true 1415 if _, ok := dc.(*fakeConn); !ok { 1416 return fmt.Errorf("got %T want *fakeConn", dc) 1417 } 1418 return nil 1419 }) 1420 if err != nil { 1421 t.Fatal(err) 1422 } 1423 if !sawFunc { 1424 t.Fatal("Raw func not called") 1425 } 1426 1427 func() { 1428 defer func() { 1429 x := recover() 1430 if x == nil { 1431 t.Fatal("expected panic") 1432 } 1433 conn.closemu.Lock() 1434 closed := conn.dc == nil 1435 conn.closemu.Unlock() 1436 if !closed { 1437 t.Fatal("expected connection to be closed after panic") 1438 } 1439 }() 1440 err = conn.Raw(func(dc interface{}) error { 1441 panic("Conn.Raw panic should return an error") 1442 }) 1443 t.Fatal("expected panic from Raw func") 1444 }() 1445 } 1446 1447 func TestCursorFake(t *testing.T) { 1448 db := newTestDB(t, "people") 1449 defer closeDB(t, db) 1450 1451 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) 1452 defer cancel() 1453 1454 exec(t, db, "CREATE|peoplecursor|list=table") 1455 exec(t, db, "INSERT|peoplecursor|list=people!name!age") 1456 1457 rows, err := db.QueryContext(ctx, `SELECT|peoplecursor|list|`) 1458 if err != nil { 1459 t.Fatal(err) 1460 } 1461 defer rows.Close() 1462 1463 if !rows.Next() { 1464 t.Fatal("no rows") 1465 } 1466 var cursor = &Rows{} 1467 err = rows.Scan(cursor) 1468 if err != nil { 1469 t.Fatal(err) 1470 } 1471 defer cursor.Close() 1472 1473 const expectedRows = 3 1474 var currentRow int64 1475 1476 var n int64 1477 var s string 1478 for cursor.Next() { 1479 currentRow++ 1480 err = cursor.Scan(&s, &n) 1481 if err != nil { 1482 t.Fatal(err) 1483 } 1484 if n != currentRow { 1485 t.Errorf("expected number(Age)=%d, got %d", currentRow, n) 1486 } 1487 } 1488 if currentRow != expectedRows { 1489 t.Errorf("expected %d rows, got %d rows", expectedRows, currentRow) 1490 } 1491 } 1492 1493 func TestInvalidNilValues(t *testing.T) { 1494 var date1 time.Time 1495 var date2 int 1496 1497 tests := []struct { 1498 name string 1499 input interface{} 1500 expectedError string 1501 }{ 1502 { 1503 name: "time.Time", 1504 input: &date1, 1505 expectedError: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type <nil> into type *time.Time`, 1506 }, 1507 { 1508 name: "int", 1509 input: &date2, 1510 expectedError: `sql: Scan error on column index 0, name "bdate": converting NULL to int is unsupported`, 1511 }, 1512 } 1513 1514 for _, tt := range tests { 1515 t.Run(tt.name, func(t *testing.T) { 1516 db := newTestDB(t, "people") 1517 defer closeDB(t, db) 1518 1519 ctx, cancel := context.WithCancel(context.Background()) 1520 defer cancel() 1521 conn, err := db.Conn(ctx) 1522 if err != nil { 1523 t.Fatal(err) 1524 } 1525 conn.dc.ci.(*fakeConn).skipDirtySession = true 1526 defer conn.Close() 1527 1528 err = conn.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 1).Scan(tt.input) 1529 if err == nil { 1530 t.Fatal("expected error when querying nil column, but succeeded") 1531 } 1532 if err.Error() != tt.expectedError { 1533 t.Fatalf("Expected error: %s\nReceived: %s", tt.expectedError, err.Error()) 1534 } 1535 1536 err = conn.PingContext(ctx) 1537 if err != nil { 1538 t.Fatal(err) 1539 } 1540 }) 1541 } 1542 } 1543 1544 func TestConnTx(t *testing.T) { 1545 db := newTestDB(t, "people") 1546 defer closeDB(t, db) 1547 1548 ctx, cancel := context.WithCancel(context.Background()) 1549 defer cancel() 1550 conn, err := db.Conn(ctx) 1551 if err != nil { 1552 t.Fatal(err) 1553 } 1554 conn.dc.ci.(*fakeConn).skipDirtySession = true 1555 defer conn.Close() 1556 1557 tx, err := conn.BeginTx(ctx, nil) 1558 if err != nil { 1559 t.Fatal(err) 1560 } 1561 insertName, insertAge := "Nancy", 33 1562 _, err = tx.ExecContext(ctx, "INSERT|people|name=?,age=?,photo=APHOTO", insertName, insertAge) 1563 if err != nil { 1564 t.Fatal(err) 1565 } 1566 err = tx.Commit() 1567 if err != nil { 1568 t.Fatal(err) 1569 } 1570 1571 var selectName string 1572 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", insertAge).Scan(&selectName) 1573 if err != nil { 1574 t.Fatal(err) 1575 } 1576 if selectName != insertName { 1577 t.Fatalf("got %q want %q", selectName, insertName) 1578 } 1579 } 1580 1581 // TestConnIsValid verifies that a database connection that should be discarded, 1582 // is actually discarded and does not re-enter the connection pool. 1583 // If the IsValid method from *fakeConn is removed, this test will fail. 1584 func TestConnIsValid(t *testing.T) { 1585 db := newTestDB(t, "people") 1586 defer closeDB(t, db) 1587 1588 db.SetMaxOpenConns(1) 1589 1590 ctx := context.Background() 1591 1592 c, err := db.Conn(ctx) 1593 if err != nil { 1594 t.Fatal(err) 1595 } 1596 1597 err = c.Raw(func(raw interface{}) error { 1598 dc := raw.(*fakeConn) 1599 dc.stickyBad = true 1600 return nil 1601 }) 1602 if err != nil { 1603 t.Fatal(err) 1604 } 1605 c.Close() 1606 1607 if len(db.freeConn) > 0 && db.freeConn[0].ci.(*fakeConn).stickyBad { 1608 t.Fatal("bad connection returned to pool; expected bad connection to be discarded") 1609 } 1610 } 1611 1612 // Tests fix for issue 2542, that we release a lock when querying on 1613 // a closed connection. 1614 func TestIssue2542Deadlock(t *testing.T) { 1615 db := newTestDB(t, "people") 1616 closeDB(t, db) 1617 for i := 0; i < 2; i++ { 1618 _, err := db.Query("SELECT|people|age,name|") 1619 if err == nil { 1620 t.Fatalf("expected error") 1621 } 1622 } 1623 } 1624 1625 // From golang.org/issue/3865 1626 func TestCloseStmtBeforeRows(t *testing.T) { 1627 db := newTestDB(t, "people") 1628 defer closeDB(t, db) 1629 1630 s, err := db.Prepare("SELECT|people|name|") 1631 if err != nil { 1632 t.Fatal(err) 1633 } 1634 1635 r, err := s.Query() 1636 if err != nil { 1637 s.Close() 1638 t.Fatal(err) 1639 } 1640 1641 err = s.Close() 1642 if err != nil { 1643 t.Fatal(err) 1644 } 1645 1646 r.Close() 1647 } 1648 1649 // Tests fix for issue 2788, that we bind nil to a []byte if the 1650 // value in the column is sql null 1651 func TestNullByteSlice(t *testing.T) { 1652 db := newTestDB(t, "") 1653 defer closeDB(t, db) 1654 exec(t, db, "CREATE|t|id=int32,name=nullstring") 1655 exec(t, db, "INSERT|t|id=10,name=?", nil) 1656 1657 var name []byte 1658 1659 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 1660 if err != nil { 1661 t.Fatal(err) 1662 } 1663 if name != nil { 1664 t.Fatalf("name []byte should be nil for null column value, got: %#v", name) 1665 } 1666 1667 exec(t, db, "INSERT|t|id=11,name=?", "bob") 1668 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name) 1669 if err != nil { 1670 t.Fatal(err) 1671 } 1672 if string(name) != "bob" { 1673 t.Fatalf("name []byte should be bob, got: %q", string(name)) 1674 } 1675 } 1676 1677 func TestPointerParamsAndScans(t *testing.T) { 1678 db := newTestDB(t, "") 1679 defer closeDB(t, db) 1680 exec(t, db, "CREATE|t|id=int32,name=nullstring") 1681 1682 bob := "bob" 1683 var name *string 1684 1685 name = &bob 1686 exec(t, db, "INSERT|t|id=10,name=?", name) 1687 name = nil 1688 exec(t, db, "INSERT|t|id=20,name=?", name) 1689 1690 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name) 1691 if err != nil { 1692 t.Fatalf("querying id 10: %v", err) 1693 } 1694 if name == nil { 1695 t.Errorf("id 10's name = nil; want bob") 1696 } else if *name != "bob" { 1697 t.Errorf("id 10's name = %q; want bob", *name) 1698 } 1699 1700 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name) 1701 if err != nil { 1702 t.Fatalf("querying id 20: %v", err) 1703 } 1704 if name != nil { 1705 t.Errorf("id 20 = %q; want nil", *name) 1706 } 1707 } 1708 1709 func TestQueryRowClosingStmt(t *testing.T) { 1710 db := newTestDB(t, "people") 1711 defer closeDB(t, db) 1712 var name string 1713 var age int 1714 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name) 1715 if err != nil { 1716 t.Fatal(err) 1717 } 1718 if len(db.freeConn) != 1 { 1719 t.Fatalf("expected 1 free conn") 1720 } 1721 fakeConn := db.freeConn[0].ci.(*fakeConn) 1722 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed { 1723 t.Errorf("statement close mismatch: made %d, closed %d", made, closed) 1724 } 1725 } 1726 1727 var atomicRowsCloseHook atomic.Value // of func(*Rows, *error) 1728 1729 func init() { 1730 rowsCloseHook = func() func(*Rows, *error) { 1731 fn, _ := atomicRowsCloseHook.Load().(func(*Rows, *error)) 1732 return fn 1733 } 1734 } 1735 1736 func setRowsCloseHook(fn func(*Rows, *error)) { 1737 if fn == nil { 1738 // Can't change an atomic.Value back to nil, so set it to this 1739 // no-op func instead. 1740 fn = func(*Rows, *error) {} 1741 } 1742 atomicRowsCloseHook.Store(fn) 1743 } 1744 1745 // Test issue 6651 1746 func TestIssue6651(t *testing.T) { 1747 db := newTestDB(t, "people") 1748 defer closeDB(t, db) 1749 1750 var v string 1751 1752 want := "error in rows.Next" 1753 rowsCursorNextHook = func(dest []driver.Value) error { 1754 return fmt.Errorf(want) 1755 } 1756 defer func() { rowsCursorNextHook = nil }() 1757 1758 err := db.QueryRow("SELECT|people|name|").Scan(&v) 1759 if err == nil || err.Error() != want { 1760 t.Errorf("error = %q; want %q", err, want) 1761 } 1762 rowsCursorNextHook = nil 1763 1764 want = "error in rows.Close" 1765 setRowsCloseHook(func(rows *Rows, err *error) { 1766 *err = fmt.Errorf(want) 1767 }) 1768 defer setRowsCloseHook(nil) 1769 err = db.QueryRow("SELECT|people|name|").Scan(&v) 1770 if err == nil || err.Error() != want { 1771 t.Errorf("error = %q; want %q", err, want) 1772 } 1773 } 1774 1775 type nullTestRow struct { 1776 nullParam interface{} 1777 notNullParam interface{} 1778 scanNullVal interface{} 1779 } 1780 1781 type nullTestSpec struct { 1782 nullType string 1783 notNullType string 1784 rows [6]nullTestRow 1785 } 1786 1787 func TestNullStringParam(t *testing.T) { 1788 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{ 1789 {NullString{"aqua", true}, "", NullString{"aqua", true}}, 1790 {NullString{"brown", false}, "", NullString{"", false}}, 1791 {"chartreuse", "", NullString{"chartreuse", true}}, 1792 {NullString{"darkred", true}, "", NullString{"darkred", true}}, 1793 {NullString{"eel", false}, "", NullString{"", false}}, 1794 {"foo", NullString{"black", false}, nil}, 1795 }} 1796 nullTestRun(t, spec) 1797 } 1798 1799 func TestNullInt64Param(t *testing.T) { 1800 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{ 1801 {NullInt64{31, true}, 1, NullInt64{31, true}}, 1802 {NullInt64{-22, false}, 1, NullInt64{0, false}}, 1803 {22, 1, NullInt64{22, true}}, 1804 {NullInt64{33, true}, 1, NullInt64{33, true}}, 1805 {NullInt64{222, false}, 1, NullInt64{0, false}}, 1806 {0, NullInt64{31, false}, nil}, 1807 }} 1808 nullTestRun(t, spec) 1809 } 1810 1811 func TestNullInt32Param(t *testing.T) { 1812 spec := nullTestSpec{"nullint32", "int32", [6]nullTestRow{ 1813 {NullInt32{31, true}, 1, NullInt32{31, true}}, 1814 {NullInt32{-22, false}, 1, NullInt32{0, false}}, 1815 {22, 1, NullInt32{22, true}}, 1816 {NullInt32{33, true}, 1, NullInt32{33, true}}, 1817 {NullInt32{222, false}, 1, NullInt32{0, false}}, 1818 {0, NullInt32{31, false}, nil}, 1819 }} 1820 nullTestRun(t, spec) 1821 } 1822 1823 func TestNullFloat64Param(t *testing.T) { 1824 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{ 1825 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}}, 1826 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}}, 1827 {-22.9, 1, NullFloat64{-22.9, true}}, 1828 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}}, 1829 {NullFloat64{222, false}, 1, NullFloat64{0, false}}, 1830 {10, NullFloat64{31.2, false}, nil}, 1831 }} 1832 nullTestRun(t, spec) 1833 } 1834 1835 func TestNullBoolParam(t *testing.T) { 1836 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{ 1837 {NullBool{false, true}, true, NullBool{false, true}}, 1838 {NullBool{true, false}, false, NullBool{false, false}}, 1839 {true, true, NullBool{true, true}}, 1840 {NullBool{true, true}, false, NullBool{true, true}}, 1841 {NullBool{true, false}, true, NullBool{false, false}}, 1842 {true, NullBool{true, false}, nil}, 1843 }} 1844 nullTestRun(t, spec) 1845 } 1846 1847 func TestNullTimeParam(t *testing.T) { 1848 t0 := time.Time{} 1849 t1 := time.Date(2000, 1, 1, 8, 9, 10, 11, time.UTC) 1850 t2 := time.Date(2010, 1, 1, 8, 9, 10, 11, time.UTC) 1851 spec := nullTestSpec{"nulldatetime", "datetime", [6]nullTestRow{ 1852 {NullTime{t1, true}, t2, NullTime{t1, true}}, 1853 {NullTime{t1, false}, t2, NullTime{t0, false}}, 1854 {t1, t2, NullTime{t1, true}}, 1855 {NullTime{t1, true}, t2, NullTime{t1, true}}, 1856 {NullTime{t1, false}, t2, NullTime{t0, false}}, 1857 {t2, NullTime{t1, false}, nil}, 1858 }} 1859 nullTestRun(t, spec) 1860 } 1861 1862 func nullTestRun(t *testing.T, spec nullTestSpec) { 1863 db := newTestDB(t, "") 1864 defer closeDB(t, db) 1865 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType)) 1866 1867 // Inserts with db.Exec: 1868 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam) 1869 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam) 1870 1871 // Inserts with a prepared statement: 1872 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?") 1873 if err != nil { 1874 t.Fatalf("prepare: %v", err) 1875 } 1876 defer stmt.Close() 1877 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil { 1878 t.Errorf("exec insert chris: %v", err) 1879 } 1880 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil { 1881 t.Errorf("exec insert dave: %v", err) 1882 } 1883 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil { 1884 t.Errorf("exec insert eleanor: %v", err) 1885 } 1886 1887 // Can't put null val into non-null col 1888 if _, err := stmt.Exec(6, "bob", spec.rows[5].nullParam, spec.rows[5].notNullParam); err == nil { 1889 t.Errorf("expected error inserting nil val with prepared statement Exec") 1890 } 1891 1892 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil) 1893 if err == nil { 1894 // TODO: this test fails, but it's just because 1895 // fakeConn implements the optional Execer interface, 1896 // so arguably this is the correct behavior. But 1897 // maybe I should flesh out the fakeConn.Exec 1898 // implementation so this properly fails. 1899 // t.Errorf("expected error inserting nil name with Exec") 1900 } 1901 1902 paramtype := reflect.TypeOf(spec.rows[0].nullParam) 1903 bindVal := reflect.New(paramtype).Interface() 1904 1905 for i := 0; i < 5; i++ { 1906 id := i + 1 1907 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil { 1908 t.Errorf("id=%d Scan: %v", id, err) 1909 } 1910 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface() 1911 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) { 1912 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal) 1913 } 1914 } 1915 } 1916 1917 // golang.org/issue/4859 1918 func TestQueryRowNilScanDest(t *testing.T) { 1919 db := newTestDB(t, "people") 1920 defer closeDB(t, db) 1921 var name *string // nil pointer 1922 err := db.QueryRow("SELECT|people|name|").Scan(name) 1923 want := `sql: Scan error on column index 0, name "name": destination pointer is nil` 1924 if err == nil || err.Error() != want { 1925 t.Errorf("error = %q; want %q", err.Error(), want) 1926 } 1927 } 1928 1929 func TestIssue4902(t *testing.T) { 1930 db := newTestDB(t, "people") 1931 defer closeDB(t, db) 1932 1933 driver := db.Driver().(*fakeDriver) 1934 opens0 := driver.openCount 1935 1936 var stmt *Stmt 1937 var err error 1938 for i := 0; i < 10; i++ { 1939 stmt, err = db.Prepare("SELECT|people|name|") 1940 if err != nil { 1941 t.Fatal(err) 1942 } 1943 err = stmt.Close() 1944 if err != nil { 1945 t.Fatal(err) 1946 } 1947 } 1948 1949 opens := driver.openCount - opens0 1950 if opens > 1 { 1951 t.Errorf("opens = %d; want <= 1", opens) 1952 t.Logf("db = %#v", db) 1953 t.Logf("driver = %#v", driver) 1954 t.Logf("stmt = %#v", stmt) 1955 } 1956 } 1957 1958 // Issue 3857 1959 // This used to deadlock. 1960 func TestSimultaneousQueries(t *testing.T) { 1961 db := newTestDB(t, "people") 1962 defer closeDB(t, db) 1963 1964 tx, err := db.Begin() 1965 if err != nil { 1966 t.Fatal(err) 1967 } 1968 defer tx.Rollback() 1969 1970 r1, err := tx.Query("SELECT|people|name|") 1971 if err != nil { 1972 t.Fatal(err) 1973 } 1974 defer r1.Close() 1975 1976 r2, err := tx.Query("SELECT|people|name|") 1977 if err != nil { 1978 t.Fatal(err) 1979 } 1980 defer r2.Close() 1981 } 1982 1983 func TestMaxIdleConns(t *testing.T) { 1984 db := newTestDB(t, "people") 1985 defer closeDB(t, db) 1986 1987 tx, err := db.Begin() 1988 if err != nil { 1989 t.Fatal(err) 1990 } 1991 tx.Commit() 1992 if got := len(db.freeConn); got != 1 { 1993 t.Errorf("freeConns = %d; want 1", got) 1994 } 1995 1996 db.SetMaxIdleConns(0) 1997 1998 if got := len(db.freeConn); got != 0 { 1999 t.Errorf("freeConns after set to zero = %d; want 0", got) 2000 } 2001 2002 tx, err = db.Begin() 2003 if err != nil { 2004 t.Fatal(err) 2005 } 2006 tx.Commit() 2007 if got := len(db.freeConn); got != 0 { 2008 t.Errorf("freeConns = %d; want 0", got) 2009 } 2010 } 2011 2012 func TestMaxOpenConns(t *testing.T) { 2013 if testing.Short() { 2014 t.Skip("skipping in short mode") 2015 } 2016 defer setHookpostCloseConn(nil) 2017 setHookpostCloseConn(func(_ *fakeConn, err error) { 2018 if err != nil { 2019 t.Errorf("Error closing fakeConn: %v", err) 2020 } 2021 }) 2022 2023 db := newTestDB(t, "magicquery") 2024 defer closeDB(t, db) 2025 2026 driver := db.Driver().(*fakeDriver) 2027 2028 // Force the number of open connections to 0 so we can get an accurate 2029 // count for the test 2030 db.clearAllConns(t) 2031 2032 driver.mu.Lock() 2033 opens0 := driver.openCount 2034 closes0 := driver.closeCount 2035 driver.mu.Unlock() 2036 2037 db.SetMaxIdleConns(10) 2038 db.SetMaxOpenConns(10) 2039 2040 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2041 if err != nil { 2042 t.Fatal(err) 2043 } 2044 2045 // Start 50 parallel slow queries. 2046 const ( 2047 nquery = 50 2048 sleepMillis = 25 2049 nbatch = 2 2050 ) 2051 var wg sync.WaitGroup 2052 for batch := 0; batch < nbatch; batch++ { 2053 for i := 0; i < nquery; i++ { 2054 wg.Add(1) 2055 go func() { 2056 defer wg.Done() 2057 var op string 2058 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 2059 t.Error(err) 2060 } 2061 }() 2062 } 2063 // Sleep for twice the expected length of time for the 2064 // batch of 50 queries above to finish before starting 2065 // the next round. 2066 time.Sleep(2 * sleepMillis * time.Millisecond) 2067 } 2068 wg.Wait() 2069 2070 if g, w := db.numFreeConns(), 10; g != w { 2071 t.Errorf("free conns = %d; want %d", g, w) 2072 } 2073 2074 if n := db.numDepsPollUntil(20, time.Second); n > 20 { 2075 t.Errorf("number of dependencies = %d; expected <= 20", n) 2076 db.dumpDeps(t) 2077 } 2078 2079 driver.mu.Lock() 2080 opens := driver.openCount - opens0 2081 closes := driver.closeCount - closes0 2082 driver.mu.Unlock() 2083 2084 if opens > 10 { 2085 t.Logf("open calls = %d", opens) 2086 t.Logf("close calls = %d", closes) 2087 t.Errorf("db connections opened = %d; want <= 10", opens) 2088 db.dumpDeps(t) 2089 } 2090 2091 if err := stmt.Close(); err != nil { 2092 t.Fatal(err) 2093 } 2094 2095 if g, w := db.numFreeConns(), 10; g != w { 2096 t.Errorf("free conns = %d; want %d", g, w) 2097 } 2098 2099 if n := db.numDepsPollUntil(10, time.Second); n > 10 { 2100 t.Errorf("number of dependencies = %d; expected <= 10", n) 2101 db.dumpDeps(t) 2102 } 2103 2104 db.SetMaxOpenConns(5) 2105 2106 if g, w := db.numFreeConns(), 5; g != w { 2107 t.Errorf("free conns = %d; want %d", g, w) 2108 } 2109 2110 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 2111 t.Errorf("number of dependencies = %d; expected 0", n) 2112 db.dumpDeps(t) 2113 } 2114 2115 db.SetMaxOpenConns(0) 2116 2117 if g, w := db.numFreeConns(), 5; g != w { 2118 t.Errorf("free conns = %d; want %d", g, w) 2119 } 2120 2121 if n := db.numDepsPollUntil(5, time.Second); n > 5 { 2122 t.Errorf("number of dependencies = %d; expected 0", n) 2123 db.dumpDeps(t) 2124 } 2125 2126 db.clearAllConns(t) 2127 } 2128 2129 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime 2130 // and affects the subsequent release of connections. 2131 func TestMaxOpenConnsOnBusy(t *testing.T) { 2132 defer setHookpostCloseConn(nil) 2133 setHookpostCloseConn(func(_ *fakeConn, err error) { 2134 if err != nil { 2135 t.Errorf("Error closing fakeConn: %v", err) 2136 } 2137 }) 2138 2139 db := newTestDB(t, "magicquery") 2140 defer closeDB(t, db) 2141 2142 db.SetMaxOpenConns(3) 2143 2144 ctx := context.Background() 2145 2146 conn0, err := db.conn(ctx, cachedOrNewConn) 2147 if err != nil { 2148 t.Fatalf("db open conn fail: %v", err) 2149 } 2150 2151 conn1, err := db.conn(ctx, cachedOrNewConn) 2152 if err != nil { 2153 t.Fatalf("db open conn fail: %v", err) 2154 } 2155 2156 conn2, err := db.conn(ctx, cachedOrNewConn) 2157 if err != nil { 2158 t.Fatalf("db open conn fail: %v", err) 2159 } 2160 2161 if g, w := db.numOpen, 3; g != w { 2162 t.Errorf("free conns = %d; want %d", g, w) 2163 } 2164 2165 db.SetMaxOpenConns(2) 2166 if g, w := db.numOpen, 3; g != w { 2167 t.Errorf("free conns = %d; want %d", g, w) 2168 } 2169 2170 conn0.releaseConn(nil) 2171 conn1.releaseConn(nil) 2172 if g, w := db.numOpen, 2; g != w { 2173 t.Errorf("free conns = %d; want %d", g, w) 2174 } 2175 2176 conn2.releaseConn(nil) 2177 if g, w := db.numOpen, 2; g != w { 2178 t.Errorf("free conns = %d; want %d", g, w) 2179 } 2180 } 2181 2182 // Issue 10886: tests that all connection attempts return when more than 2183 // DB.maxOpen connections are in flight and the first DB.maxOpen fail. 2184 func TestPendingConnsAfterErr(t *testing.T) { 2185 const ( 2186 maxOpen = 2 2187 tryOpen = maxOpen*2 + 2 2188 ) 2189 2190 // No queries will be run. 2191 db, err := Open("test", fakeDBName) 2192 if err != nil { 2193 t.Fatalf("Open: %v", err) 2194 } 2195 defer closeDB(t, db) 2196 defer func() { 2197 for k, v := range db.lastPut { 2198 t.Logf("%p: %v", k, v) 2199 } 2200 }() 2201 2202 db.SetMaxOpenConns(maxOpen) 2203 db.SetMaxIdleConns(0) 2204 2205 errOffline := errors.New("db offline") 2206 2207 defer func() { setHookOpenErr(nil) }() 2208 2209 errs := make(chan error, tryOpen) 2210 2211 var opening sync.WaitGroup 2212 opening.Add(tryOpen) 2213 2214 setHookOpenErr(func() error { 2215 // Wait for all connections to enqueue. 2216 opening.Wait() 2217 return errOffline 2218 }) 2219 2220 for i := 0; i < tryOpen; i++ { 2221 go func() { 2222 opening.Done() // signal one connection is in flight 2223 _, err := db.Exec("will never run") 2224 errs <- err 2225 }() 2226 } 2227 2228 opening.Wait() // wait for all workers to begin running 2229 2230 const timeout = 5 * time.Second 2231 to := time.NewTimer(timeout) 2232 defer to.Stop() 2233 2234 // check that all connections fail without deadlock 2235 for i := 0; i < tryOpen; i++ { 2236 select { 2237 case err := <-errs: 2238 if got, want := err, errOffline; got != want { 2239 t.Errorf("unexpected err: got %v, want %v", got, want) 2240 } 2241 case <-to.C: 2242 t.Fatalf("orphaned connection request(s), still waiting after %v", timeout) 2243 } 2244 } 2245 2246 // Wait a reasonable time for the database to close all connections. 2247 tick := time.NewTicker(3 * time.Millisecond) 2248 defer tick.Stop() 2249 for { 2250 select { 2251 case <-tick.C: 2252 db.mu.Lock() 2253 if db.numOpen == 0 { 2254 db.mu.Unlock() 2255 return 2256 } 2257 db.mu.Unlock() 2258 case <-to.C: 2259 // Closing the database will check for numOpen and fail the test. 2260 return 2261 } 2262 } 2263 } 2264 2265 func TestSingleOpenConn(t *testing.T) { 2266 db := newTestDB(t, "people") 2267 defer closeDB(t, db) 2268 2269 db.SetMaxOpenConns(1) 2270 2271 rows, err := db.Query("SELECT|people|name|") 2272 if err != nil { 2273 t.Fatal(err) 2274 } 2275 if err = rows.Close(); err != nil { 2276 t.Fatal(err) 2277 } 2278 // shouldn't deadlock 2279 rows, err = db.Query("SELECT|people|name|") 2280 if err != nil { 2281 t.Fatal(err) 2282 } 2283 if err = rows.Close(); err != nil { 2284 t.Fatal(err) 2285 } 2286 } 2287 2288 func TestStats(t *testing.T) { 2289 db := newTestDB(t, "people") 2290 stats := db.Stats() 2291 if got := stats.OpenConnections; got != 1 { 2292 t.Errorf("stats.OpenConnections = %d; want 1", got) 2293 } 2294 2295 tx, err := db.Begin() 2296 if err != nil { 2297 t.Fatal(err) 2298 } 2299 tx.Commit() 2300 2301 closeDB(t, db) 2302 stats = db.Stats() 2303 if got := stats.OpenConnections; got != 0 { 2304 t.Errorf("stats.OpenConnections = %d; want 0", got) 2305 } 2306 } 2307 2308 func TestConnMaxLifetime(t *testing.T) { 2309 t0 := time.Unix(1000000, 0) 2310 offset := time.Duration(0) 2311 2312 nowFunc = func() time.Time { return t0.Add(offset) } 2313 defer func() { nowFunc = time.Now }() 2314 2315 db := newTestDB(t, "magicquery") 2316 defer closeDB(t, db) 2317 2318 driver := db.Driver().(*fakeDriver) 2319 2320 // Force the number of open connections to 0 so we can get an accurate 2321 // count for the test 2322 db.clearAllConns(t) 2323 2324 driver.mu.Lock() 2325 opens0 := driver.openCount 2326 closes0 := driver.closeCount 2327 driver.mu.Unlock() 2328 2329 db.SetMaxIdleConns(10) 2330 db.SetMaxOpenConns(10) 2331 2332 tx, err := db.Begin() 2333 if err != nil { 2334 t.Fatal(err) 2335 } 2336 2337 offset = time.Second 2338 tx2, err := db.Begin() 2339 if err != nil { 2340 t.Fatal(err) 2341 } 2342 2343 tx.Commit() 2344 tx2.Commit() 2345 2346 driver.mu.Lock() 2347 opens := driver.openCount - opens0 2348 closes := driver.closeCount - closes0 2349 driver.mu.Unlock() 2350 2351 if opens != 2 { 2352 t.Errorf("opens = %d; want 2", opens) 2353 } 2354 if closes != 0 { 2355 t.Errorf("closes = %d; want 0", closes) 2356 } 2357 if g, w := db.numFreeConns(), 2; g != w { 2358 t.Errorf("free conns = %d; want %d", g, w) 2359 } 2360 2361 // Expire first conn 2362 offset = 11 * time.Second 2363 db.SetConnMaxLifetime(10 * time.Second) 2364 if err != nil { 2365 t.Fatal(err) 2366 } 2367 2368 tx, err = db.Begin() 2369 if err != nil { 2370 t.Fatal(err) 2371 } 2372 tx2, err = db.Begin() 2373 if err != nil { 2374 t.Fatal(err) 2375 } 2376 tx.Commit() 2377 tx2.Commit() 2378 2379 driver.mu.Lock() 2380 opens = driver.openCount - opens0 2381 closes = driver.closeCount - closes0 2382 driver.mu.Unlock() 2383 2384 if opens != 3 { 2385 t.Errorf("opens = %d; want 3", opens) 2386 } 2387 if closes != 1 { 2388 t.Errorf("closes = %d; want 1", closes) 2389 } 2390 } 2391 2392 // golang.org/issue/5323 2393 func TestStmtCloseDeps(t *testing.T) { 2394 if testing.Short() { 2395 t.Skip("skipping in short mode") 2396 } 2397 defer setHookpostCloseConn(nil) 2398 setHookpostCloseConn(func(_ *fakeConn, err error) { 2399 if err != nil { 2400 t.Errorf("Error closing fakeConn: %v", err) 2401 } 2402 }) 2403 2404 db := newTestDB(t, "magicquery") 2405 defer closeDB(t, db) 2406 2407 driver := db.Driver().(*fakeDriver) 2408 2409 driver.mu.Lock() 2410 opens0 := driver.openCount 2411 closes0 := driver.closeCount 2412 driver.mu.Unlock() 2413 openDelta0 := opens0 - closes0 2414 2415 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 2416 if err != nil { 2417 t.Fatal(err) 2418 } 2419 2420 // Start 50 parallel slow queries. 2421 const ( 2422 nquery = 50 2423 sleepMillis = 25 2424 nbatch = 2 2425 ) 2426 var wg sync.WaitGroup 2427 for batch := 0; batch < nbatch; batch++ { 2428 for i := 0; i < nquery; i++ { 2429 wg.Add(1) 2430 go func() { 2431 defer wg.Done() 2432 var op string 2433 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows { 2434 t.Error(err) 2435 } 2436 }() 2437 } 2438 // Sleep for twice the expected length of time for the 2439 // batch of 50 queries above to finish before starting 2440 // the next round. 2441 time.Sleep(2 * sleepMillis * time.Millisecond) 2442 } 2443 wg.Wait() 2444 2445 if g, w := db.numFreeConns(), 2; g != w { 2446 t.Errorf("free conns = %d; want %d", g, w) 2447 } 2448 2449 if n := db.numDepsPollUntil(4, time.Second); n > 4 { 2450 t.Errorf("number of dependencies = %d; expected <= 4", n) 2451 db.dumpDeps(t) 2452 } 2453 2454 driver.mu.Lock() 2455 opens := driver.openCount - opens0 2456 closes := driver.closeCount - closes0 2457 openDelta := (driver.openCount - driver.closeCount) - openDelta0 2458 driver.mu.Unlock() 2459 2460 if openDelta > 2 { 2461 t.Logf("open calls = %d", opens) 2462 t.Logf("close calls = %d", closes) 2463 t.Logf("open delta = %d", openDelta) 2464 t.Errorf("db connections opened = %d; want <= 2", openDelta) 2465 db.dumpDeps(t) 2466 } 2467 2468 if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool { 2469 return len(stmt.css) <= nquery 2470 }) { 2471 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery) 2472 } 2473 2474 if err := stmt.Close(); err != nil { 2475 t.Fatal(err) 2476 } 2477 2478 if g, w := db.numFreeConns(), 2; g != w { 2479 t.Errorf("free conns = %d; want %d", g, w) 2480 } 2481 2482 if n := db.numDepsPollUntil(2, time.Second); n > 2 { 2483 t.Errorf("number of dependencies = %d; expected <= 2", n) 2484 db.dumpDeps(t) 2485 } 2486 2487 db.clearAllConns(t) 2488 } 2489 2490 // golang.org/issue/5046 2491 func TestCloseConnBeforeStmts(t *testing.T) { 2492 db := newTestDB(t, "people") 2493 defer closeDB(t, db) 2494 2495 defer setHookpostCloseConn(nil) 2496 setHookpostCloseConn(func(_ *fakeConn, err error) { 2497 if err != nil { 2498 t.Errorf("Error closing fakeConn: %v; from %s", err, stack()) 2499 db.dumpDeps(t) 2500 t.Errorf("DB = %#v", db) 2501 } 2502 }) 2503 2504 stmt, err := db.Prepare("SELECT|people|name|") 2505 if err != nil { 2506 t.Fatal(err) 2507 } 2508 2509 if len(db.freeConn) != 1 { 2510 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) 2511 } 2512 dc := db.freeConn[0] 2513 if dc.closed { 2514 t.Errorf("conn shouldn't be closed") 2515 } 2516 2517 if n := len(dc.openStmt); n != 1 { 2518 t.Errorf("driverConn num openStmt = %d; want 1", n) 2519 } 2520 err = db.Close() 2521 if err != nil { 2522 t.Errorf("db Close = %v", err) 2523 } 2524 if !dc.closed { 2525 t.Errorf("after db.Close, driverConn should be closed") 2526 } 2527 if n := len(dc.openStmt); n != 0 { 2528 t.Errorf("driverConn num openStmt = %d; want 0", n) 2529 } 2530 2531 err = stmt.Close() 2532 if err != nil { 2533 t.Errorf("Stmt close = %v", err) 2534 } 2535 2536 if !dc.closed { 2537 t.Errorf("conn should be closed") 2538 } 2539 if dc.ci != nil { 2540 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil") 2541 } 2542 } 2543 2544 // golang.org/issue/5283: don't release the Rows' connection in Close 2545 // before calling Stmt.Close. 2546 func TestRowsCloseOrder(t *testing.T) { 2547 db := newTestDB(t, "people") 2548 defer closeDB(t, db) 2549 2550 db.SetMaxIdleConns(0) 2551 setStrictFakeConnClose(t) 2552 defer setStrictFakeConnClose(nil) 2553 2554 rows, err := db.Query("SELECT|people|age,name|") 2555 if err != nil { 2556 t.Fatal(err) 2557 } 2558 err = rows.Close() 2559 if err != nil { 2560 t.Fatal(err) 2561 } 2562 } 2563 2564 func TestRowsImplicitClose(t *testing.T) { 2565 db := newTestDB(t, "people") 2566 defer closeDB(t, db) 2567 2568 rows, err := db.Query("SELECT|people|age,name|") 2569 if err != nil { 2570 t.Fatal(err) 2571 } 2572 2573 want, fail := 2, errors.New("fail") 2574 r := rows.rowsi.(*rowsCursor) 2575 r.errPos, r.err = want, fail 2576 2577 got := 0 2578 for rows.Next() { 2579 got++ 2580 } 2581 if got != want { 2582 t.Errorf("got %d rows, want %d", got, want) 2583 } 2584 if err := rows.Err(); err != fail { 2585 t.Errorf("got error %v, want %v", err, fail) 2586 } 2587 if !r.closed { 2588 t.Errorf("r.closed is false, want true") 2589 } 2590 } 2591 2592 func TestStmtCloseOrder(t *testing.T) { 2593 db := newTestDB(t, "people") 2594 defer closeDB(t, db) 2595 2596 db.SetMaxIdleConns(0) 2597 setStrictFakeConnClose(t) 2598 defer setStrictFakeConnClose(nil) 2599 2600 _, err := db.Query("SELECT|non_existent|name|") 2601 if err == nil { 2602 t.Fatal("Querying non-existent table should fail") 2603 } 2604 } 2605 2606 // Test cases where there's more than maxBadConnRetries bad connections in the 2607 // pool (issue 8834) 2608 func TestManyErrBadConn(t *testing.T) { 2609 manyErrBadConnSetup := func(first ...func(db *DB)) *DB { 2610 db := newTestDB(t, "people") 2611 2612 for _, f := range first { 2613 f(db) 2614 } 2615 2616 nconn := maxBadConnRetries + 1 2617 db.SetMaxIdleConns(nconn) 2618 db.SetMaxOpenConns(nconn) 2619 // open enough connections 2620 func() { 2621 for i := 0; i < nconn; i++ { 2622 rows, err := db.Query("SELECT|people|age,name|") 2623 if err != nil { 2624 t.Fatal(err) 2625 } 2626 defer rows.Close() 2627 } 2628 }() 2629 2630 db.mu.Lock() 2631 defer db.mu.Unlock() 2632 if db.numOpen != nconn { 2633 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn) 2634 } else if len(db.freeConn) != nconn { 2635 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn) 2636 } 2637 for _, conn := range db.freeConn { 2638 conn.Lock() 2639 conn.ci.(*fakeConn).stickyBad = true 2640 conn.Unlock() 2641 } 2642 return db 2643 } 2644 2645 // Query 2646 db := manyErrBadConnSetup() 2647 defer closeDB(t, db) 2648 rows, err := db.Query("SELECT|people|age,name|") 2649 if err != nil { 2650 t.Fatal(err) 2651 } 2652 if err = rows.Close(); err != nil { 2653 t.Fatal(err) 2654 } 2655 2656 // Exec 2657 db = manyErrBadConnSetup() 2658 defer closeDB(t, db) 2659 _, err = db.Exec("INSERT|people|name=Julia,age=19") 2660 if err != nil { 2661 t.Fatal(err) 2662 } 2663 2664 // Begin 2665 db = manyErrBadConnSetup() 2666 defer closeDB(t, db) 2667 tx, err := db.Begin() 2668 if err != nil { 2669 t.Fatal(err) 2670 } 2671 if err = tx.Rollback(); err != nil { 2672 t.Fatal(err) 2673 } 2674 2675 // Prepare 2676 db = manyErrBadConnSetup() 2677 defer closeDB(t, db) 2678 stmt, err := db.Prepare("SELECT|people|age,name|") 2679 if err != nil { 2680 t.Fatal(err) 2681 } 2682 if err = stmt.Close(); err != nil { 2683 t.Fatal(err) 2684 } 2685 2686 // Stmt.Exec 2687 db = manyErrBadConnSetup(func(db *DB) { 2688 stmt, err = db.Prepare("INSERT|people|name=Julia,age=19") 2689 if err != nil { 2690 t.Fatal(err) 2691 } 2692 }) 2693 defer closeDB(t, db) 2694 _, err = stmt.Exec() 2695 if err != nil { 2696 t.Fatal(err) 2697 } 2698 if err = stmt.Close(); err != nil { 2699 t.Fatal(err) 2700 } 2701 2702 // Stmt.Query 2703 db = manyErrBadConnSetup(func(db *DB) { 2704 stmt, err = db.Prepare("SELECT|people|age,name|") 2705 if err != nil { 2706 t.Fatal(err) 2707 } 2708 }) 2709 defer closeDB(t, db) 2710 rows, err = stmt.Query() 2711 if err != nil { 2712 t.Fatal(err) 2713 } 2714 if err = rows.Close(); err != nil { 2715 t.Fatal(err) 2716 } 2717 if err = stmt.Close(); err != nil { 2718 t.Fatal(err) 2719 } 2720 2721 // Conn 2722 db = manyErrBadConnSetup() 2723 defer closeDB(t, db) 2724 ctx, cancel := context.WithCancel(context.Background()) 2725 defer cancel() 2726 conn, err := db.Conn(ctx) 2727 if err != nil { 2728 t.Fatal(err) 2729 } 2730 conn.dc.ci.(*fakeConn).skipDirtySession = true 2731 err = conn.Close() 2732 if err != nil { 2733 t.Fatal(err) 2734 } 2735 2736 // Ping 2737 db = manyErrBadConnSetup() 2738 defer closeDB(t, db) 2739 err = db.PingContext(ctx) 2740 if err != nil { 2741 t.Fatal(err) 2742 } 2743 } 2744 2745 // Issue 34775: Ensure that a Tx cannot commit after a rollback. 2746 func TestTxCannotCommitAfterRollback(t *testing.T) { 2747 db := newTestDB(t, "tx_status") 2748 defer closeDB(t, db) 2749 2750 // First check query reporting is correct. 2751 var txStatus string 2752 err := db.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2753 if err != nil { 2754 t.Fatal(err) 2755 } 2756 if g, w := txStatus, "autocommit"; g != w { 2757 t.Fatalf("tx_status=%q, wanted %q", g, w) 2758 } 2759 2760 ctx, cancel := context.WithCancel(context.Background()) 2761 defer cancel() 2762 2763 tx, err := db.BeginTx(ctx, nil) 2764 if err != nil { 2765 t.Fatal(err) 2766 } 2767 2768 // Ignore dirty session for this test. 2769 // A failing test should trigger the dirty session flag as well, 2770 // but that isn't exactly what this should test for. 2771 tx.txi.(*fakeTx).c.skipDirtySession = true 2772 2773 defer tx.Rollback() 2774 2775 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2776 if err != nil { 2777 t.Fatal(err) 2778 } 2779 if g, w := txStatus, "transaction"; g != w { 2780 t.Fatalf("tx_status=%q, wanted %q", g, w) 2781 } 2782 2783 // 1. Begin a transaction. 2784 // 2. (A) Start a query, (B) begin Tx rollback through a ctx cancel. 2785 // 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail). 2786 sendQuery := make(chan struct{}) 2787 // The Tx status is returned through the row results, ensure 2788 // that the rows results are not cancelled. 2789 bypassRowsAwaitDone = true 2790 hookTxGrabConn = func() { 2791 cancel() 2792 <-sendQuery 2793 } 2794 rollbackHook = func() { 2795 close(sendQuery) 2796 } 2797 defer func() { 2798 hookTxGrabConn = nil 2799 rollbackHook = nil 2800 bypassRowsAwaitDone = false 2801 }() 2802 2803 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus) 2804 if err != nil { 2805 // A failure here would be expected if skipDirtySession was not set to true above. 2806 t.Fatal(err) 2807 } 2808 if g, w := txStatus, "transaction"; g != w { 2809 t.Fatalf("tx_status=%q, wanted %q", g, w) 2810 } 2811 } 2812 2813 // Issue 40985 transaction statement deadlock while context cancel. 2814 func TestTxStmtDeadlock(t *testing.T) { 2815 db := newTestDB(t, "people") 2816 defer closeDB(t, db) 2817 2818 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) 2819 defer cancel() 2820 tx, err := db.BeginTx(ctx, nil) 2821 if err != nil { 2822 t.Fatal(err) 2823 } 2824 2825 stmt, err := tx.Prepare("SELECT|people|name,age|age=?") 2826 if err != nil { 2827 t.Fatal(err) 2828 } 2829 // Run number of stmt queries to reproduce deadlock from context cancel 2830 for i := 0; i < 1e3; i++ { 2831 // Encounter any close related errors (e.g. ErrTxDone, stmt is closed) 2832 // is expected due to context cancel. 2833 _, err = stmt.Query(1) 2834 if err != nil { 2835 break 2836 } 2837 } 2838 _ = tx.Rollback() 2839 } 2840 2841 // Issue32530 encounters an issue where a connection may 2842 // expire right after it comes out of a used connection pool 2843 // even when a new connection is requested. 2844 func TestConnExpiresFreshOutOfPool(t *testing.T) { 2845 execCases := []struct { 2846 expired bool 2847 badReset bool 2848 }{ 2849 {false, false}, 2850 {true, false}, 2851 {false, true}, 2852 } 2853 2854 t0 := time.Unix(1000000, 0) 2855 offset := time.Duration(0) 2856 offsetMu := sync.RWMutex{} 2857 2858 nowFunc = func() time.Time { 2859 offsetMu.RLock() 2860 defer offsetMu.RUnlock() 2861 return t0.Add(offset) 2862 } 2863 defer func() { nowFunc = time.Now }() 2864 2865 ctx, cancel := context.WithCancel(context.Background()) 2866 defer cancel() 2867 2868 db := newTestDB(t, "magicquery") 2869 defer closeDB(t, db) 2870 2871 db.SetMaxOpenConns(1) 2872 2873 for _, ec := range execCases { 2874 ec := ec 2875 name := fmt.Sprintf("expired=%t,badReset=%t", ec.expired, ec.badReset) 2876 t.Run(name, func(t *testing.T) { 2877 db.clearAllConns(t) 2878 2879 db.SetMaxIdleConns(1) 2880 db.SetConnMaxLifetime(10 * time.Second) 2881 2882 conn, err := db.conn(ctx, alwaysNewConn) 2883 if err != nil { 2884 t.Fatal(err) 2885 } 2886 2887 afterPutConn := make(chan struct{}) 2888 waitingForConn := make(chan struct{}) 2889 2890 go func() { 2891 defer close(afterPutConn) 2892 2893 conn, err := db.conn(ctx, alwaysNewConn) 2894 if err == nil { 2895 db.putConn(conn, err, false) 2896 } else { 2897 t.Errorf("db.conn: %v", err) 2898 } 2899 }() 2900 go func() { 2901 defer close(waitingForConn) 2902 2903 for { 2904 if t.Failed() { 2905 return 2906 } 2907 db.mu.Lock() 2908 ct := len(db.connRequests) 2909 db.mu.Unlock() 2910 if ct > 0 { 2911 return 2912 } 2913 time.Sleep(10 * time.Millisecond) 2914 } 2915 }() 2916 2917 <-waitingForConn 2918 2919 if t.Failed() { 2920 return 2921 } 2922 2923 offsetMu.Lock() 2924 if ec.expired { 2925 offset = 11 * time.Second 2926 } else { 2927 offset = time.Duration(0) 2928 } 2929 offsetMu.Unlock() 2930 2931 conn.ci.(*fakeConn).stickyBad = ec.badReset 2932 2933 db.putConn(conn, err, true) 2934 2935 <-afterPutConn 2936 }) 2937 } 2938 } 2939 2940 // TestIssue20575 ensures the Rows from query does not block 2941 // closing a transaction. Ensure Rows is closed while closing a trasaction. 2942 func TestIssue20575(t *testing.T) { 2943 db := newTestDB(t, "people") 2944 defer closeDB(t, db) 2945 2946 tx, err := db.Begin() 2947 if err != nil { 2948 t.Fatal(err) 2949 } 2950 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 2951 defer cancel() 2952 _, err = tx.QueryContext(ctx, "SELECT|people|age,name|") 2953 if err != nil { 2954 t.Fatal(err) 2955 } 2956 // Do not close Rows from QueryContext. 2957 err = tx.Rollback() 2958 if err != nil { 2959 t.Fatal(err) 2960 } 2961 select { 2962 default: 2963 case <-ctx.Done(): 2964 t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err()) 2965 } 2966 } 2967 2968 // TestIssue20622 tests closing the transaction before rows is closed, requires 2969 // the race detector to fail. 2970 func TestIssue20622(t *testing.T) { 2971 db := newTestDB(t, "people") 2972 defer closeDB(t, db) 2973 2974 ctx, cancel := context.WithCancel(context.Background()) 2975 defer cancel() 2976 2977 tx, err := db.BeginTx(ctx, nil) 2978 if err != nil { 2979 t.Fatal(err) 2980 } 2981 2982 rows, err := tx.Query("SELECT|people|age,name|") 2983 if err != nil { 2984 t.Fatal(err) 2985 } 2986 2987 count := 0 2988 for rows.Next() { 2989 count++ 2990 var age int 2991 var name string 2992 if err := rows.Scan(&age, &name); err != nil { 2993 t.Fatal("scan failed", err) 2994 } 2995 2996 if count == 1 { 2997 cancel() 2998 } 2999 time.Sleep(100 * time.Millisecond) 3000 } 3001 rows.Close() 3002 tx.Commit() 3003 } 3004 3005 // golang.org/issue/5718 3006 func TestErrBadConnReconnect(t *testing.T) { 3007 db := newTestDB(t, "foo") 3008 defer closeDB(t, db) 3009 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 3010 3011 simulateBadConn := func(name string, hook *func() bool, op func() error) { 3012 broken, retried := false, false 3013 numOpen := db.numOpen 3014 3015 // simulate a broken connection on the first try 3016 *hook = func() bool { 3017 if !broken { 3018 broken = true 3019 return true 3020 } 3021 retried = true 3022 return false 3023 } 3024 3025 if err := op(); err != nil { 3026 t.Errorf(name+": %v", err) 3027 return 3028 } 3029 3030 if !broken || !retried { 3031 t.Error(name + ": Failed to simulate broken connection") 3032 } 3033 *hook = nil 3034 3035 if numOpen != db.numOpen { 3036 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 3037 numOpen = db.numOpen 3038 } 3039 } 3040 3041 // db.Exec 3042 dbExec := func() error { 3043 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 3044 return err 3045 } 3046 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec) 3047 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec) 3048 3049 // db.Query 3050 dbQuery := func() error { 3051 rows, err := db.Query("SELECT|t1|age,name|") 3052 if err == nil { 3053 err = rows.Close() 3054 } 3055 return err 3056 } 3057 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery) 3058 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery) 3059 3060 // db.Prepare 3061 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error { 3062 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 3063 if err != nil { 3064 return err 3065 } 3066 stmt.Close() 3067 return nil 3068 }) 3069 3070 // Provide a way to force a re-prepare of a statement on next execution 3071 forcePrepare := func(stmt *Stmt) { 3072 stmt.css = nil 3073 } 3074 3075 // stmt.Exec 3076 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") 3077 if err != nil { 3078 t.Fatalf("prepare: %v", err) 3079 } 3080 defer stmt1.Close() 3081 // make sure we must prepare the stmt first 3082 forcePrepare(stmt1) 3083 3084 stmtExec := func() error { 3085 _, err := stmt1.Exec("Gopher", 3, false) 3086 return err 3087 } 3088 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec) 3089 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec) 3090 3091 // stmt.Query 3092 stmt2, err := db.Prepare("SELECT|t1|age,name|") 3093 if err != nil { 3094 t.Fatalf("prepare: %v", err) 3095 } 3096 defer stmt2.Close() 3097 // make sure we must prepare the stmt first 3098 forcePrepare(stmt2) 3099 3100 stmtQuery := func() error { 3101 rows, err := stmt2.Query() 3102 if err == nil { 3103 err = rows.Close() 3104 } 3105 return err 3106 } 3107 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery) 3108 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery) 3109 } 3110 3111 // golang.org/issue/11264 3112 func TestTxEndBadConn(t *testing.T) { 3113 db := newTestDB(t, "foo") 3114 defer closeDB(t, db) 3115 db.SetMaxIdleConns(0) 3116 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") 3117 db.SetMaxIdleConns(1) 3118 3119 simulateBadConn := func(name string, hook *func() bool, op func() error) { 3120 broken := false 3121 numOpen := db.numOpen 3122 3123 *hook = func() bool { 3124 if !broken { 3125 broken = true 3126 } 3127 return broken 3128 } 3129 3130 if err := op(); err != driver.ErrBadConn { 3131 t.Errorf(name+": %v", err) 3132 return 3133 } 3134 3135 if !broken { 3136 t.Error(name + ": Failed to simulate broken connection") 3137 } 3138 *hook = nil 3139 3140 if numOpen != db.numOpen { 3141 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) 3142 } 3143 } 3144 3145 // db.Exec 3146 dbExec := func(endTx func(tx *Tx) error) func() error { 3147 return func() error { 3148 tx, err := db.Begin() 3149 if err != nil { 3150 return err 3151 } 3152 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) 3153 if err != nil { 3154 return err 3155 } 3156 return endTx(tx) 3157 } 3158 } 3159 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit)) 3160 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback)) 3161 3162 // db.Query 3163 dbQuery := func(endTx func(tx *Tx) error) func() error { 3164 return func() error { 3165 tx, err := db.Begin() 3166 if err != nil { 3167 return err 3168 } 3169 rows, err := tx.Query("SELECT|t1|age,name|") 3170 if err == nil { 3171 err = rows.Close() 3172 } else { 3173 return err 3174 } 3175 return endTx(tx) 3176 } 3177 } 3178 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit)) 3179 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback)) 3180 } 3181 3182 type concurrentTest interface { 3183 init(t testing.TB, db *DB) 3184 finish(t testing.TB) 3185 test(t testing.TB) error 3186 } 3187 3188 type concurrentDBQueryTest struct { 3189 db *DB 3190 } 3191 3192 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) { 3193 c.db = db 3194 } 3195 3196 func (c *concurrentDBQueryTest) finish(t testing.TB) { 3197 c.db = nil 3198 } 3199 3200 func (c *concurrentDBQueryTest) test(t testing.TB) error { 3201 rows, err := c.db.Query("SELECT|people|name|") 3202 if err != nil { 3203 t.Error(err) 3204 return err 3205 } 3206 var name string 3207 for rows.Next() { 3208 rows.Scan(&name) 3209 } 3210 rows.Close() 3211 return nil 3212 } 3213 3214 type concurrentDBExecTest struct { 3215 db *DB 3216 } 3217 3218 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) { 3219 c.db = db 3220 } 3221 3222 func (c *concurrentDBExecTest) finish(t testing.TB) { 3223 c.db = nil 3224 } 3225 3226 func (c *concurrentDBExecTest) test(t testing.TB) error { 3227 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 3228 if err != nil { 3229 t.Error(err) 3230 return err 3231 } 3232 return nil 3233 } 3234 3235 type concurrentStmtQueryTest struct { 3236 db *DB 3237 stmt *Stmt 3238 } 3239 3240 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) { 3241 c.db = db 3242 var err error 3243 c.stmt, err = db.Prepare("SELECT|people|name|") 3244 if err != nil { 3245 t.Fatal(err) 3246 } 3247 } 3248 3249 func (c *concurrentStmtQueryTest) finish(t testing.TB) { 3250 if c.stmt != nil { 3251 c.stmt.Close() 3252 c.stmt = nil 3253 } 3254 c.db = nil 3255 } 3256 3257 func (c *concurrentStmtQueryTest) test(t testing.TB) error { 3258 rows, err := c.stmt.Query() 3259 if err != nil { 3260 t.Errorf("error on query: %v", err) 3261 return err 3262 } 3263 3264 var name string 3265 for rows.Next() { 3266 rows.Scan(&name) 3267 } 3268 rows.Close() 3269 return nil 3270 } 3271 3272 type concurrentStmtExecTest struct { 3273 db *DB 3274 stmt *Stmt 3275 } 3276 3277 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) { 3278 c.db = db 3279 var err error 3280 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 3281 if err != nil { 3282 t.Fatal(err) 3283 } 3284 } 3285 3286 func (c *concurrentStmtExecTest) finish(t testing.TB) { 3287 if c.stmt != nil { 3288 c.stmt.Close() 3289 c.stmt = nil 3290 } 3291 c.db = nil 3292 } 3293 3294 func (c *concurrentStmtExecTest) test(t testing.TB) error { 3295 _, err := c.stmt.Exec(3, chrisBirthday) 3296 if err != nil { 3297 t.Errorf("error on exec: %v", err) 3298 return err 3299 } 3300 return nil 3301 } 3302 3303 type concurrentTxQueryTest struct { 3304 db *DB 3305 tx *Tx 3306 } 3307 3308 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) { 3309 c.db = db 3310 var err error 3311 c.tx, err = c.db.Begin() 3312 if err != nil { 3313 t.Fatal(err) 3314 } 3315 } 3316 3317 func (c *concurrentTxQueryTest) finish(t testing.TB) { 3318 if c.tx != nil { 3319 c.tx.Rollback() 3320 c.tx = nil 3321 } 3322 c.db = nil 3323 } 3324 3325 func (c *concurrentTxQueryTest) test(t testing.TB) error { 3326 rows, err := c.db.Query("SELECT|people|name|") 3327 if err != nil { 3328 t.Error(err) 3329 return err 3330 } 3331 var name string 3332 for rows.Next() { 3333 rows.Scan(&name) 3334 } 3335 rows.Close() 3336 return nil 3337 } 3338 3339 type concurrentTxExecTest struct { 3340 db *DB 3341 tx *Tx 3342 } 3343 3344 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) { 3345 c.db = db 3346 var err error 3347 c.tx, err = c.db.Begin() 3348 if err != nil { 3349 t.Fatal(err) 3350 } 3351 } 3352 3353 func (c *concurrentTxExecTest) finish(t testing.TB) { 3354 if c.tx != nil { 3355 c.tx.Rollback() 3356 c.tx = nil 3357 } 3358 c.db = nil 3359 } 3360 3361 func (c *concurrentTxExecTest) test(t testing.TB) error { 3362 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday) 3363 if err != nil { 3364 t.Error(err) 3365 return err 3366 } 3367 return nil 3368 } 3369 3370 type concurrentTxStmtQueryTest struct { 3371 db *DB 3372 tx *Tx 3373 stmt *Stmt 3374 } 3375 3376 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) { 3377 c.db = db 3378 var err error 3379 c.tx, err = c.db.Begin() 3380 if err != nil { 3381 t.Fatal(err) 3382 } 3383 c.stmt, err = c.tx.Prepare("SELECT|people|name|") 3384 if err != nil { 3385 t.Fatal(err) 3386 } 3387 } 3388 3389 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) { 3390 if c.stmt != nil { 3391 c.stmt.Close() 3392 c.stmt = nil 3393 } 3394 if c.tx != nil { 3395 c.tx.Rollback() 3396 c.tx = nil 3397 } 3398 c.db = nil 3399 } 3400 3401 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error { 3402 rows, err := c.stmt.Query() 3403 if err != nil { 3404 t.Errorf("error on query: %v", err) 3405 return err 3406 } 3407 3408 var name string 3409 for rows.Next() { 3410 rows.Scan(&name) 3411 } 3412 rows.Close() 3413 return nil 3414 } 3415 3416 type concurrentTxStmtExecTest struct { 3417 db *DB 3418 tx *Tx 3419 stmt *Stmt 3420 } 3421 3422 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) { 3423 c.db = db 3424 var err error 3425 c.tx, err = c.db.Begin() 3426 if err != nil { 3427 t.Fatal(err) 3428 } 3429 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?") 3430 if err != nil { 3431 t.Fatal(err) 3432 } 3433 } 3434 3435 func (c *concurrentTxStmtExecTest) finish(t testing.TB) { 3436 if c.stmt != nil { 3437 c.stmt.Close() 3438 c.stmt = nil 3439 } 3440 if c.tx != nil { 3441 c.tx.Rollback() 3442 c.tx = nil 3443 } 3444 c.db = nil 3445 } 3446 3447 func (c *concurrentTxStmtExecTest) test(t testing.TB) error { 3448 _, err := c.stmt.Exec(3, chrisBirthday) 3449 if err != nil { 3450 t.Errorf("error on exec: %v", err) 3451 return err 3452 } 3453 return nil 3454 } 3455 3456 type concurrentRandomTest struct { 3457 tests []concurrentTest 3458 } 3459 3460 func (c *concurrentRandomTest) init(t testing.TB, db *DB) { 3461 c.tests = []concurrentTest{ 3462 new(concurrentDBQueryTest), 3463 new(concurrentDBExecTest), 3464 new(concurrentStmtQueryTest), 3465 new(concurrentStmtExecTest), 3466 new(concurrentTxQueryTest), 3467 new(concurrentTxExecTest), 3468 new(concurrentTxStmtQueryTest), 3469 new(concurrentTxStmtExecTest), 3470 } 3471 for _, ct := range c.tests { 3472 ct.init(t, db) 3473 } 3474 } 3475 3476 func (c *concurrentRandomTest) finish(t testing.TB) { 3477 for _, ct := range c.tests { 3478 ct.finish(t) 3479 } 3480 } 3481 3482 func (c *concurrentRandomTest) test(t testing.TB) error { 3483 ct := c.tests[rand.Intn(len(c.tests))] 3484 return ct.test(t) 3485 } 3486 3487 func doConcurrentTest(t testing.TB, ct concurrentTest) { 3488 maxProcs, numReqs := 1, 500 3489 if testing.Short() { 3490 maxProcs, numReqs = 4, 50 3491 } 3492 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) 3493 3494 db := newTestDB(t, "people") 3495 defer closeDB(t, db) 3496 3497 ct.init(t, db) 3498 defer ct.finish(t) 3499 3500 var wg sync.WaitGroup 3501 wg.Add(numReqs) 3502 3503 reqs := make(chan bool) 3504 defer close(reqs) 3505 3506 for i := 0; i < maxProcs*2; i++ { 3507 go func() { 3508 for range reqs { 3509 err := ct.test(t) 3510 if err != nil { 3511 wg.Done() 3512 continue 3513 } 3514 wg.Done() 3515 } 3516 }() 3517 } 3518 3519 for i := 0; i < numReqs; i++ { 3520 reqs <- true 3521 } 3522 3523 wg.Wait() 3524 } 3525 3526 func TestIssue6081(t *testing.T) { 3527 db := newTestDB(t, "people") 3528 defer closeDB(t, db) 3529 3530 drv := db.Driver().(*fakeDriver) 3531 drv.mu.Lock() 3532 opens0 := drv.openCount 3533 closes0 := drv.closeCount 3534 drv.mu.Unlock() 3535 3536 stmt, err := db.Prepare("SELECT|people|name|") 3537 if err != nil { 3538 t.Fatal(err) 3539 } 3540 setRowsCloseHook(func(rows *Rows, err *error) { 3541 *err = driver.ErrBadConn 3542 }) 3543 defer setRowsCloseHook(nil) 3544 for i := 0; i < 10; i++ { 3545 rows, err := stmt.Query() 3546 if err != nil { 3547 t.Fatal(err) 3548 } 3549 rows.Close() 3550 } 3551 if n := len(stmt.css); n > 1 { 3552 t.Errorf("len(css slice) = %d; want <= 1", n) 3553 } 3554 stmt.Close() 3555 if n := len(stmt.css); n != 0 { 3556 t.Errorf("len(css slice) after Close = %d; want 0", n) 3557 } 3558 3559 drv.mu.Lock() 3560 opens := drv.openCount - opens0 3561 closes := drv.closeCount - closes0 3562 drv.mu.Unlock() 3563 if opens < 9 { 3564 t.Errorf("opens = %d; want >= 9", opens) 3565 } 3566 if closes < 9 { 3567 t.Errorf("closes = %d; want >= 9", closes) 3568 } 3569 } 3570 3571 // TestIssue18429 attempts to stress rolling back the transaction from a 3572 // context cancel while simultaneously calling Tx.Rollback. Rolling back from a 3573 // context happens concurrently so tx.rollback and tx.Commit must guard against 3574 // double entry. 3575 // 3576 // In the test, a context is canceled while the query is in process so 3577 // the internal rollback will run concurrently with the explicitly called 3578 // Tx.Rollback. 3579 // 3580 // The addition of calling rows.Next also tests 3581 // Issue 21117. 3582 func TestIssue18429(t *testing.T) { 3583 db := newTestDB(t, "people") 3584 defer closeDB(t, db) 3585 3586 ctx := context.Background() 3587 sem := make(chan bool, 20) 3588 var wg sync.WaitGroup 3589 3590 const milliWait = 30 3591 3592 for i := 0; i < 100; i++ { 3593 sem <- true 3594 wg.Add(1) 3595 go func() { 3596 defer func() { 3597 <-sem 3598 wg.Done() 3599 }() 3600 qwait := (time.Duration(rand.Intn(milliWait)) * time.Millisecond).String() 3601 3602 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond) 3603 defer cancel() 3604 3605 tx, err := db.BeginTx(ctx, nil) 3606 if err != nil { 3607 return 3608 } 3609 // This is expected to give a cancel error most, but not all the time. 3610 // Test failure will happen with a panic or other race condition being 3611 // reported. 3612 rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|") 3613 if rows != nil { 3614 var name string 3615 // Call Next to test Issue 21117 and check for races. 3616 for rows.Next() { 3617 // Scan the buffer so it is read and checked for races. 3618 rows.Scan(&name) 3619 } 3620 rows.Close() 3621 } 3622 // This call will race with the context cancel rollback to complete 3623 // if the rollback itself isn't guarded. 3624 tx.Rollback() 3625 }() 3626 } 3627 wg.Wait() 3628 } 3629 3630 // TestIssue20160 attempts to test a short context life on a stmt Query. 3631 func TestIssue20160(t *testing.T) { 3632 db := newTestDB(t, "people") 3633 defer closeDB(t, db) 3634 3635 ctx := context.Background() 3636 sem := make(chan bool, 20) 3637 var wg sync.WaitGroup 3638 3639 const milliWait = 30 3640 3641 stmt, err := db.PrepareContext(ctx, "SELECT|people|name|") 3642 if err != nil { 3643 t.Fatal(err) 3644 } 3645 defer stmt.Close() 3646 3647 for i := 0; i < 100; i++ { 3648 sem <- true 3649 wg.Add(1) 3650 go func() { 3651 defer func() { 3652 <-sem 3653 wg.Done() 3654 }() 3655 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond) 3656 defer cancel() 3657 3658 // This is expected to give a cancel error most, but not all the time. 3659 // Test failure will happen with a panic or other race condition being 3660 // reported. 3661 rows, _ := stmt.QueryContext(ctx) 3662 if rows != nil { 3663 rows.Close() 3664 } 3665 }() 3666 } 3667 wg.Wait() 3668 } 3669 3670 // TestIssue18719 closes the context right before use. The sql.driverConn 3671 // will nil out the ci on close in a lock, but if another process uses it right after 3672 // it will panic with on the nil ref. 3673 // 3674 // See https://golang.org/cl/35550 . 3675 func TestIssue18719(t *testing.T) { 3676 db := newTestDB(t, "people") 3677 defer closeDB(t, db) 3678 3679 ctx, cancel := context.WithCancel(context.Background()) 3680 defer cancel() 3681 3682 tx, err := db.BeginTx(ctx, nil) 3683 if err != nil { 3684 t.Fatal(err) 3685 } 3686 3687 hookTxGrabConn = func() { 3688 cancel() 3689 3690 // Wait for the context to cancel and tx to rollback. 3691 for tx.isDone() == false { 3692 time.Sleep(3 * time.Millisecond) 3693 } 3694 } 3695 defer func() { hookTxGrabConn = nil }() 3696 3697 // This call will grab the connection and cancel the context 3698 // after it has done so. Code after must deal with the canceled state. 3699 _, err = tx.QueryContext(ctx, "SELECT|people|name|") 3700 if err != nil { 3701 t.Fatalf("expected error %v but got %v", nil, err) 3702 } 3703 3704 // Rows may be ignored because it will be closed when the context is canceled. 3705 3706 // Do not explicitly rollback. The rollback will happen from the 3707 // canceled context. 3708 3709 cancel() 3710 } 3711 3712 func TestIssue20647(t *testing.T) { 3713 db := newTestDB(t, "people") 3714 defer closeDB(t, db) 3715 3716 ctx, cancel := context.WithCancel(context.Background()) 3717 defer cancel() 3718 3719 conn, err := db.Conn(ctx) 3720 if err != nil { 3721 t.Fatal(err) 3722 } 3723 conn.dc.ci.(*fakeConn).skipDirtySession = true 3724 defer conn.Close() 3725 3726 stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|") 3727 if err != nil { 3728 t.Fatal(err) 3729 } 3730 defer stmt.Close() 3731 3732 rows1, err := stmt.QueryContext(ctx) 3733 if err != nil { 3734 t.Fatal("rows1", err) 3735 } 3736 defer rows1.Close() 3737 3738 rows2, err := stmt.QueryContext(ctx) 3739 if err != nil { 3740 t.Fatal("rows2", err) 3741 } 3742 defer rows2.Close() 3743 3744 if rows1.dc != rows2.dc { 3745 t.Fatal("stmt prepared on Conn does not use same connection") 3746 } 3747 } 3748 3749 func TestConcurrency(t *testing.T) { 3750 list := []struct { 3751 name string 3752 ct concurrentTest 3753 }{ 3754 {"Query", new(concurrentDBQueryTest)}, 3755 {"Exec", new(concurrentDBExecTest)}, 3756 {"StmtQuery", new(concurrentStmtQueryTest)}, 3757 {"StmtExec", new(concurrentStmtExecTest)}, 3758 {"TxQuery", new(concurrentTxQueryTest)}, 3759 {"TxExec", new(concurrentTxExecTest)}, 3760 {"TxStmtQuery", new(concurrentTxStmtQueryTest)}, 3761 {"TxStmtExec", new(concurrentTxStmtExecTest)}, 3762 {"Random", new(concurrentRandomTest)}, 3763 } 3764 for _, item := range list { 3765 t.Run(item.name, func(t *testing.T) { 3766 doConcurrentTest(t, item.ct) 3767 }) 3768 } 3769 } 3770 3771 func TestConnectionLeak(t *testing.T) { 3772 db := newTestDB(t, "people") 3773 defer closeDB(t, db) 3774 // Start by opening defaultMaxIdleConns 3775 rows := make([]*Rows, defaultMaxIdleConns) 3776 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open 3777 // a new connection and we can fill the idle queue with the released 3778 // connections. 3779 db.SetMaxOpenConns(len(rows) + 1) 3780 for ii := range rows { 3781 r, err := db.Query("SELECT|people|name|") 3782 if err != nil { 3783 t.Fatal(err) 3784 } 3785 r.Next() 3786 if err := r.Err(); err != nil { 3787 t.Fatal(err) 3788 } 3789 rows[ii] = r 3790 } 3791 // Now we have defaultMaxIdleConns busy connections. Open 3792 // a new one, but wait until the busy connections are released 3793 // before returning control to DB. 3794 drv := db.Driver().(*fakeDriver) 3795 drv.waitCh = make(chan struct{}, 1) 3796 drv.waitingCh = make(chan struct{}, 1) 3797 var wg sync.WaitGroup 3798 wg.Add(1) 3799 go func() { 3800 r, err := db.Query("SELECT|people|name|") 3801 if err != nil { 3802 t.Error(err) 3803 return 3804 } 3805 r.Close() 3806 wg.Done() 3807 }() 3808 // Wait until the goroutine we've just created has started waiting. 3809 <-drv.waitingCh 3810 // Now close the busy connections. This provides a connection for 3811 // the blocked goroutine and then fills up the idle queue. 3812 for _, v := range rows { 3813 v.Close() 3814 } 3815 // At this point we give the new connection to DB. This connection is 3816 // now useless, since the idle queue is full and there are no pending 3817 // requests. DB should deal with this situation without leaking the 3818 // connection. 3819 drv.waitCh <- struct{}{} 3820 wg.Wait() 3821 } 3822 3823 func TestStatsMaxIdleClosedZero(t *testing.T) { 3824 db := newTestDB(t, "people") 3825 defer closeDB(t, db) 3826 3827 db.SetMaxOpenConns(1) 3828 db.SetMaxIdleConns(1) 3829 db.SetConnMaxLifetime(0) 3830 3831 preMaxIdleClosed := db.Stats().MaxIdleClosed 3832 3833 for i := 0; i < 10; i++ { 3834 rows, err := db.Query("SELECT|people|name|") 3835 if err != nil { 3836 t.Fatal(err) 3837 } 3838 rows.Close() 3839 } 3840 3841 st := db.Stats() 3842 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed 3843 t.Logf("MaxIdleClosed: %d", maxIdleClosed) 3844 if maxIdleClosed != 0 { 3845 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed) 3846 } 3847 } 3848 3849 func TestStatsMaxIdleClosedTen(t *testing.T) { 3850 db := newTestDB(t, "people") 3851 defer closeDB(t, db) 3852 3853 db.SetMaxOpenConns(1) 3854 db.SetMaxIdleConns(0) 3855 db.SetConnMaxLifetime(0) 3856 3857 preMaxIdleClosed := db.Stats().MaxIdleClosed 3858 3859 for i := 0; i < 10; i++ { 3860 rows, err := db.Query("SELECT|people|name|") 3861 if err != nil { 3862 t.Fatal(err) 3863 } 3864 rows.Close() 3865 } 3866 3867 st := db.Stats() 3868 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed 3869 t.Logf("MaxIdleClosed: %d", maxIdleClosed) 3870 if maxIdleClosed != 10 { 3871 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed) 3872 } 3873 } 3874 3875 func TestMaxIdleTime(t *testing.T) { 3876 list := []struct { 3877 wantMaxIdleTime time.Duration 3878 wantIdleClosed int64 3879 timeOffset time.Duration 3880 }{ 3881 {time.Nanosecond, 1, 10 * time.Millisecond}, 3882 {time.Hour, 0, 10 * time.Millisecond}, 3883 } 3884 baseTime := time.Unix(0, 0) 3885 defer func() { 3886 nowFunc = time.Now 3887 }() 3888 for _, item := range list { 3889 nowFunc = func() time.Time { 3890 return baseTime 3891 } 3892 t.Run(fmt.Sprintf("%v", item.wantMaxIdleTime), func(t *testing.T) { 3893 db := newTestDB(t, "people") 3894 defer closeDB(t, db) 3895 3896 db.SetMaxOpenConns(1) 3897 db.SetMaxIdleConns(1) 3898 db.SetConnMaxIdleTime(item.wantMaxIdleTime) 3899 db.SetConnMaxLifetime(0) 3900 3901 preMaxIdleClosed := db.Stats().MaxIdleTimeClosed 3902 3903 if err := db.Ping(); err != nil { 3904 t.Fatal(err) 3905 } 3906 3907 nowFunc = func() time.Time { 3908 return baseTime.Add(item.timeOffset) 3909 } 3910 3911 db.mu.Lock() 3912 closing := db.connectionCleanerRunLocked() 3913 db.mu.Unlock() 3914 for _, c := range closing { 3915 c.Close() 3916 } 3917 if g, w := int64(len(closing)), item.wantIdleClosed; g != w { 3918 t.Errorf("got: %d; want %d closed conns", g, w) 3919 } 3920 3921 st := db.Stats() 3922 maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed 3923 if g, w := maxIdleClosed, item.wantIdleClosed; g != w { 3924 t.Errorf(" got: %d; want %d max idle closed conns", g, w) 3925 } 3926 }) 3927 } 3928 } 3929 3930 type nvcDriver struct { 3931 fakeDriver 3932 skipNamedValueCheck bool 3933 } 3934 3935 func (d *nvcDriver) Open(dsn string) (driver.Conn, error) { 3936 c, err := d.fakeDriver.Open(dsn) 3937 fc := c.(*fakeConn) 3938 fc.db.allowAny = true 3939 return &nvcConn{fc, d.skipNamedValueCheck}, err 3940 } 3941 3942 type nvcConn struct { 3943 *fakeConn 3944 skipNamedValueCheck bool 3945 } 3946 3947 type decimalInt struct { 3948 value int 3949 } 3950 3951 type doNotInclude struct{} 3952 3953 var _ driver.NamedValueChecker = &nvcConn{} 3954 3955 func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error { 3956 if c.skipNamedValueCheck { 3957 return driver.ErrSkip 3958 } 3959 switch v := nv.Value.(type) { 3960 default: 3961 return driver.ErrSkip 3962 case Out: 3963 switch ov := v.Dest.(type) { 3964 default: 3965 return errors.New("unknown NameValueCheck OUTPUT type") 3966 case *string: 3967 *ov = "from-server" 3968 nv.Value = "OUT:*string" 3969 } 3970 return nil 3971 case decimalInt, []int64: 3972 return nil 3973 case doNotInclude: 3974 return driver.ErrRemoveArgument 3975 } 3976 } 3977 3978 func TestNamedValueChecker(t *testing.T) { 3979 Register("NamedValueCheck", &nvcDriver{}) 3980 db, err := Open("NamedValueCheck", "") 3981 if err != nil { 3982 t.Fatal(err) 3983 } 3984 defer db.Close() 3985 3986 ctx, cancel := context.WithCancel(context.Background()) 3987 defer cancel() 3988 3989 _, err = db.ExecContext(ctx, "WIPE") 3990 if err != nil { 3991 t.Fatal("exec wipe", err) 3992 } 3993 3994 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any") 3995 if err != nil { 3996 t.Fatal("exec create", err) 3997 } 3998 3999 o1 := "" 4000 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A,str1=?,out1=?O1,array1=?", Named("A", decimalInt{123}), "hello", Named("O1", Out{Dest: &o1}), []int64{42, 128, 707}, doNotInclude{}) 4001 if err != nil { 4002 t.Fatal("exec insert", err) 4003 } 4004 var ( 4005 str1 string 4006 dec1 decimalInt 4007 arr1 []int64 4008 ) 4009 err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1) 4010 if err != nil { 4011 t.Fatal("select", err) 4012 } 4013 4014 list := []struct{ got, want interface{} }{ 4015 {o1, "from-server"}, 4016 {dec1, decimalInt{123}}, 4017 {str1, "hello"}, 4018 {arr1, []int64{42, 128, 707}}, 4019 } 4020 4021 for index, item := range list { 4022 if !reflect.DeepEqual(item.got, item.want) { 4023 t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index) 4024 } 4025 } 4026 } 4027 4028 func TestNamedValueCheckerSkip(t *testing.T) { 4029 Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true}) 4030 db, err := Open("NamedValueCheckSkip", "") 4031 if err != nil { 4032 t.Fatal(err) 4033 } 4034 defer db.Close() 4035 4036 ctx, cancel := context.WithCancel(context.Background()) 4037 defer cancel() 4038 4039 _, err = db.ExecContext(ctx, "WIPE") 4040 if err != nil { 4041 t.Fatal("exec wipe", err) 4042 } 4043 4044 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any") 4045 if err != nil { 4046 t.Fatal("exec create", err) 4047 } 4048 4049 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimalInt{123})) 4050 if err == nil { 4051 t.Fatalf("expected error with bad argument, got %v", err) 4052 } 4053 } 4054 4055 func TestOpenConnector(t *testing.T) { 4056 Register("testctx", &fakeDriverCtx{}) 4057 db, err := Open("testctx", "people") 4058 if err != nil { 4059 t.Fatal(err) 4060 } 4061 defer db.Close() 4062 4063 if _, is := db.connector.(*fakeConnector); !is { 4064 t.Fatal("not using *fakeConnector") 4065 } 4066 } 4067 4068 type ctxOnlyDriver struct { 4069 fakeDriver 4070 } 4071 4072 func (d *ctxOnlyDriver) Open(dsn string) (driver.Conn, error) { 4073 conn, err := d.fakeDriver.Open(dsn) 4074 if err != nil { 4075 return nil, err 4076 } 4077 return &ctxOnlyConn{fc: conn.(*fakeConn)}, nil 4078 } 4079 4080 var ( 4081 _ driver.Conn = &ctxOnlyConn{} 4082 _ driver.QueryerContext = &ctxOnlyConn{} 4083 _ driver.ExecerContext = &ctxOnlyConn{} 4084 ) 4085 4086 type ctxOnlyConn struct { 4087 fc *fakeConn 4088 4089 queryCtxCalled bool 4090 execCtxCalled bool 4091 } 4092 4093 func (c *ctxOnlyConn) Begin() (driver.Tx, error) { 4094 return c.fc.Begin() 4095 } 4096 4097 func (c *ctxOnlyConn) Close() error { 4098 return c.fc.Close() 4099 } 4100 4101 // Prepare is still part of the Conn interface, so while it isn't used 4102 // must be defined for compatibility. 4103 func (c *ctxOnlyConn) Prepare(q string) (driver.Stmt, error) { 4104 panic("not used") 4105 } 4106 4107 func (c *ctxOnlyConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) { 4108 return c.fc.PrepareContext(ctx, q) 4109 } 4110 4111 func (c *ctxOnlyConn) QueryContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Rows, error) { 4112 c.queryCtxCalled = true 4113 return c.fc.QueryContext(ctx, q, args) 4114 } 4115 4116 func (c *ctxOnlyConn) ExecContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Result, error) { 4117 c.execCtxCalled = true 4118 return c.fc.ExecContext(ctx, q, args) 4119 } 4120 4121 // TestQueryExecContextOnly ensures drivers only need to implement QueryContext 4122 // and ExecContext methods. 4123 func TestQueryExecContextOnly(t *testing.T) { 4124 // Ensure connection does not implement non-context interfaces. 4125 var connType driver.Conn = &ctxOnlyConn{} 4126 if _, ok := connType.(driver.Execer); ok { 4127 t.Fatalf("%T must not implement driver.Execer", connType) 4128 } 4129 if _, ok := connType.(driver.Queryer); ok { 4130 t.Fatalf("%T must not implement driver.Queryer", connType) 4131 } 4132 4133 Register("ContextOnly", &ctxOnlyDriver{}) 4134 db, err := Open("ContextOnly", "") 4135 if err != nil { 4136 t.Fatal(err) 4137 } 4138 defer db.Close() 4139 4140 ctx, cancel := context.WithCancel(context.Background()) 4141 defer cancel() 4142 4143 conn, err := db.Conn(ctx) 4144 if err != nil { 4145 t.Fatal("db.Conn", err) 4146 } 4147 defer conn.Close() 4148 coc := conn.dc.ci.(*ctxOnlyConn) 4149 coc.fc.skipDirtySession = true 4150 4151 _, err = conn.ExecContext(ctx, "WIPE") 4152 if err != nil { 4153 t.Fatal("exec wipe", err) 4154 } 4155 4156 _, err = conn.ExecContext(ctx, "CREATE|keys|v1=string") 4157 if err != nil { 4158 t.Fatal("exec create", err) 4159 } 4160 expectedValue := "value1" 4161 _, err = conn.ExecContext(ctx, "INSERT|keys|v1=?", expectedValue) 4162 if err != nil { 4163 t.Fatal("exec insert", err) 4164 } 4165 rows, err := conn.QueryContext(ctx, "SELECT|keys|v1|") 4166 if err != nil { 4167 t.Fatal("query select", err) 4168 } 4169 v1 := "" 4170 for rows.Next() { 4171 err = rows.Scan(&v1) 4172 if err != nil { 4173 t.Fatal("rows scan", err) 4174 } 4175 } 4176 rows.Close() 4177 4178 if v1 != expectedValue { 4179 t.Fatalf("expected %q, got %q", expectedValue, v1) 4180 } 4181 4182 if !coc.execCtxCalled { 4183 t.Error("ExecContext not called") 4184 } 4185 if !coc.queryCtxCalled { 4186 t.Error("QueryContext not called") 4187 } 4188 } 4189 4190 type alwaysErrScanner struct{} 4191 4192 var errTestScanWrap = errors.New("errTestScanWrap") 4193 4194 func (alwaysErrScanner) Scan(interface{}) error { 4195 return errTestScanWrap 4196 } 4197 4198 // Issue 38099: Ensure that Rows.Scan properly wraps underlying errors. 4199 func TestRowsScanProperlyWrapsErrors(t *testing.T) { 4200 db := newTestDB(t, "people") 4201 defer closeDB(t, db) 4202 4203 rows, err := db.Query("SELECT|people|age|") 4204 if err != nil { 4205 t.Fatalf("Query: %v", err) 4206 } 4207 4208 var res alwaysErrScanner 4209 4210 for rows.Next() { 4211 err = rows.Scan(&res) 4212 if err == nil { 4213 t.Fatal("expecting back an error") 4214 } 4215 if !errors.Is(err, errTestScanWrap) { 4216 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errTestScanWrap) 4217 } 4218 // Ensure that error substring matching still correctly works. 4219 if !strings.Contains(err.Error(), errTestScanWrap.Error()) { 4220 t.Fatalf("Error %v does not contain %v", err, errTestScanWrap) 4221 } 4222 } 4223 } 4224 4225 // badConn implements a bad driver.Conn, for TestBadDriver. 4226 // The Exec method panics. 4227 type badConn struct{} 4228 4229 func (bc badConn) Prepare(query string) (driver.Stmt, error) { 4230 return nil, errors.New("badConn Prepare") 4231 } 4232 4233 func (bc badConn) Close() error { 4234 return nil 4235 } 4236 4237 func (bc badConn) Begin() (driver.Tx, error) { 4238 return nil, errors.New("badConn Begin") 4239 } 4240 4241 func (bc badConn) Exec(query string, args []driver.Value) (driver.Result, error) { 4242 panic("badConn.Exec") 4243 } 4244 4245 // badDriver is a driver.Driver that uses badConn. 4246 type badDriver struct{} 4247 4248 func (bd badDriver) Open(name string) (driver.Conn, error) { 4249 return badConn{}, nil 4250 } 4251 4252 // Issue 15901. 4253 func TestBadDriver(t *testing.T) { 4254 Register("bad", badDriver{}) 4255 db, err := Open("bad", "ignored") 4256 if err != nil { 4257 t.Fatal(err) 4258 } 4259 defer func() { 4260 if r := recover(); r == nil { 4261 t.Error("expected panic") 4262 } else { 4263 if want := "badConn.Exec"; r.(string) != want { 4264 t.Errorf("panic was %v, expected %v", r, want) 4265 } 4266 } 4267 }() 4268 defer db.Close() 4269 db.Exec("ignored") 4270 } 4271 4272 type pingDriver struct { 4273 fails bool 4274 } 4275 4276 type pingConn struct { 4277 badConn 4278 driver *pingDriver 4279 } 4280 4281 var pingError = errors.New("Ping failed") 4282 4283 func (pc pingConn) Ping(ctx context.Context) error { 4284 if pc.driver.fails { 4285 return pingError 4286 } 4287 return nil 4288 } 4289 4290 var _ driver.Pinger = pingConn{} 4291 4292 func (pd *pingDriver) Open(name string) (driver.Conn, error) { 4293 return pingConn{driver: pd}, nil 4294 } 4295 4296 func TestPing(t *testing.T) { 4297 driver := &pingDriver{} 4298 Register("ping", driver) 4299 4300 db, err := Open("ping", "ignored") 4301 if err != nil { 4302 t.Fatal(err) 4303 } 4304 4305 if err := db.Ping(); err != nil { 4306 t.Errorf("err was %#v, expected nil", err) 4307 return 4308 } 4309 4310 driver.fails = true 4311 if err := db.Ping(); err != pingError { 4312 t.Errorf("err was %#v, expected pingError", err) 4313 } 4314 } 4315 4316 // Issue 18101. 4317 func TestTypedString(t *testing.T) { 4318 db := newTestDB(t, "people") 4319 defer closeDB(t, db) 4320 4321 type Str string 4322 var scanned Str 4323 4324 err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned) 4325 if err != nil { 4326 t.Fatal(err) 4327 } 4328 expected := Str("Alice") 4329 if scanned != expected { 4330 t.Errorf("expected %+v, got %+v", expected, scanned) 4331 } 4332 } 4333 4334 func BenchmarkConcurrentDBExec(b *testing.B) { 4335 b.ReportAllocs() 4336 ct := new(concurrentDBExecTest) 4337 for i := 0; i < b.N; i++ { 4338 doConcurrentTest(b, ct) 4339 } 4340 } 4341 4342 func BenchmarkConcurrentStmtQuery(b *testing.B) { 4343 b.ReportAllocs() 4344 ct := new(concurrentStmtQueryTest) 4345 for i := 0; i < b.N; i++ { 4346 doConcurrentTest(b, ct) 4347 } 4348 } 4349 4350 func BenchmarkConcurrentStmtExec(b *testing.B) { 4351 b.ReportAllocs() 4352 ct := new(concurrentStmtExecTest) 4353 for i := 0; i < b.N; i++ { 4354 doConcurrentTest(b, ct) 4355 } 4356 } 4357 4358 func BenchmarkConcurrentTxQuery(b *testing.B) { 4359 b.ReportAllocs() 4360 ct := new(concurrentTxQueryTest) 4361 for i := 0; i < b.N; i++ { 4362 doConcurrentTest(b, ct) 4363 } 4364 } 4365 4366 func BenchmarkConcurrentTxExec(b *testing.B) { 4367 b.ReportAllocs() 4368 ct := new(concurrentTxExecTest) 4369 for i := 0; i < b.N; i++ { 4370 doConcurrentTest(b, ct) 4371 } 4372 } 4373 4374 func BenchmarkConcurrentTxStmtQuery(b *testing.B) { 4375 b.ReportAllocs() 4376 ct := new(concurrentTxStmtQueryTest) 4377 for i := 0; i < b.N; i++ { 4378 doConcurrentTest(b, ct) 4379 } 4380 } 4381 4382 func BenchmarkConcurrentTxStmtExec(b *testing.B) { 4383 b.ReportAllocs() 4384 ct := new(concurrentTxStmtExecTest) 4385 for i := 0; i < b.N; i++ { 4386 doConcurrentTest(b, ct) 4387 } 4388 } 4389 4390 func BenchmarkConcurrentRandom(b *testing.B) { 4391 b.ReportAllocs() 4392 ct := new(concurrentRandomTest) 4393 for i := 0; i < b.N; i++ { 4394 doConcurrentTest(b, ct) 4395 } 4396 } 4397 4398 func BenchmarkManyConcurrentQueries(b *testing.B) { 4399 b.ReportAllocs() 4400 // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required. 4401 const parallelism = 16 4402 4403 db := newTestDB(b, "magicquery") 4404 defer closeDB(b, db) 4405 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism) 4406 4407 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?") 4408 if err != nil { 4409 b.Fatal(err) 4410 } 4411 defer stmt.Close() 4412 4413 b.SetParallelism(parallelism) 4414 b.RunParallel(func(pb *testing.PB) { 4415 for pb.Next() { 4416 rows, err := stmt.Query("sleep", 1) 4417 if err != nil { 4418 b.Error(err) 4419 return 4420 } 4421 rows.Close() 4422 } 4423 }) 4424 }