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