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.
27 freedFrom
:= make(map[dbConn
]string)
29 getFreedFrom
:= func(c dbConn
) string {
34 setFreedFrom
:= func(c dbConn
, s
string) {
39 putConnHook
= func(db
*DB
, c
*driverConn
) {
41 for i
, v
:= range db
.freeConn
{
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.")
54 setFreedFrom(dbConn
{db
, c
}, stack())
58 // pollDuration is an arbitrary interval to wait between checks when polling for
59 // a condition to occur.
60 const pollDuration
= 5 * time
.Millisecond
62 const fakeDBName
= "foo"
64 var chrisBirthday
= time
.Unix(123456789, 0)
66 func newTestDB(t testing
.TB
, name
string) *DB
{
67 return newTestDBConnector(t
, &fakeConnector
{name
: fakeDBName
}, name
)
70 func newTestDBConnector(t testing
.TB
, fc
*fakeConnector
, name
string) *DB
{
73 if _
, err
:= db
.Exec("WIPE"); err
!= nil {
74 t
.Fatalf("exec wipe: %v", err
)
77 exec(t
, db
, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
78 exec(t
, db
, "INSERT|people|name=Alice,age=?,photo=APHOTO", 1)
79 exec(t
, db
, "INSERT|people|name=Bob,age=?,photo=BPHOTO", 2)
80 exec(t
, db
, "INSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
82 if name
== "magicquery" {
83 // Magic table name and column, known by fakedb_test.go.
84 exec(t
, db
, "CREATE|magicquery|op=string,millis=int32")
85 exec(t
, db
, "INSERT|magicquery|op=sleep,millis=10")
87 if name
== "tx_status" {
88 // Magic table name and column, known by fakedb_test.go.
89 exec(t
, db
, "CREATE|tx_status|tx_status=string")
90 exec(t
, db
, "INSERT|tx_status|tx_status=invalid")
95 func TestOpenDB(t
*testing
.T
) {
96 db
:= OpenDB(dsnConnector
{dsn
: fakeDBName
, driver
: fdriver
})
97 if db
.Driver() != fdriver
{
98 t
.Fatalf("OpenDB should return the driver of the Connector")
102 func TestDriverPanic(t
*testing
.T
) {
103 // Test that if driver panics, database/sql does not deadlock.
104 db
, err
:= Open("test", fakeDBName
)
106 t
.Fatalf("Open: %v", err
)
108 expectPanic
:= func(name
string, f
func()) {
112 t
.Fatalf("%s did not panic", name
)
118 expectPanic("Exec Exec", func() { db
.Exec("PANIC|Exec|WIPE") })
119 exec(t
, db
, "WIPE") // check not deadlocked
120 expectPanic("Exec NumInput", func() { db
.Exec("PANIC|NumInput|WIPE") })
121 exec(t
, db
, "WIPE") // check not deadlocked
122 expectPanic("Exec Close", func() { db
.Exec("PANIC|Close|WIPE") })
123 exec(t
, db
, "WIPE") // check not deadlocked
124 exec(t
, db
, "PANIC|Query|WIPE") // should run successfully: Exec does not call Query
125 exec(t
, db
, "WIPE") // check not deadlocked
127 exec(t
, db
, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
129 expectPanic("Query Query", func() { db
.Query("PANIC|Query|SELECT|people|age,name|") })
130 expectPanic("Query NumInput", func() { db
.Query("PANIC|NumInput|SELECT|people|age,name|") })
131 expectPanic("Query Close", func() {
132 rows
, err
:= db
.Query("PANIC|Close|SELECT|people|age,name|")
138 db
.Query("PANIC|Exec|SELECT|people|age,name|") // should run successfully: Query does not call Exec
139 exec(t
, db
, "WIPE") // check not deadlocked
142 func exec(t testing
.TB
, db
*DB
, query
string, args
...any
) {
144 _
, err
:= db
.Exec(query
, args
...)
146 t
.Fatalf("Exec of %q: %v", query
, err
)
150 func closeDB(t testing
.TB
, db
*DB
) {
151 if e
:= recover(); e
!= nil {
152 fmt
.Printf("Panic: %v\n", e
)
155 defer setHookpostCloseConn(nil)
156 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
158 t
.Errorf("Error closing fakeConn: %v", err
)
162 for i
, dc
:= range db
.freeConn
{
163 if n
:= len(dc
.openStmt
); n
> 0 {
164 // Just a sanity check. This is legal in
165 // general, but if we make the tests clean up
166 // their statements first, then we can safely
167 // verify this is always zero here, and any
168 // other value is a leak.
169 t
.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i
, len(db
.freeConn
), n
)
176 t
.Fatalf("error closing DB: %v", err
)
180 if !waitCondition(t
, func() bool {
181 numOpen
= db
.numOpenConns()
184 t
.Fatalf("%d connections still open after closing DB", numOpen
)
188 // numPrepares assumes that db has exactly 1 idle conn and returns
189 // its count of calls to Prepare
190 func numPrepares(t
*testing
.T
, db
*DB
) int {
191 if n
:= len(db
.freeConn
); n
!= 1 {
192 t
.Fatalf("free conns = %d; want 1", n
)
194 return db
.freeConn
[0].ci
.(*fakeConn
).numPrepare
197 func (db
*DB
) numDeps() int {
203 // Dependencies are closed via a goroutine, so this polls waiting for
204 // numDeps to fall to want, waiting up to nearly the test's deadline.
205 func (db
*DB
) numDepsPoll(t
*testing
.T
, want
int) int {
207 waitCondition(t
, func() bool {
214 func (db
*DB
) numFreeConns() int {
217 return len(db
.freeConn
)
220 func (db
*DB
) numOpenConns() int {
226 // clearAllConns closes all connections in db.
227 func (db
*DB
) clearAllConns(t
*testing
.T
) {
228 db
.SetMaxIdleConns(0)
230 if g
, w
:= db
.numFreeConns(), 0; g
!= w
{
231 t
.Errorf("free conns = %d; want %d", g
, w
)
234 if n
:= db
.numDepsPoll(t
, 0); n
> 0 {
235 t
.Errorf("number of dependencies = %d; expected 0", n
)
240 func (db
*DB
) dumpDeps(t
*testing
.T
) {
241 for fc
:= range db
.dep
{
242 db
.dumpDep(t
, 0, fc
, map[finalCloser
]bool{})
246 func (db
*DB
) dumpDep(t
*testing
.T
, depth
int, dep finalCloser
, seen
map[finalCloser
]bool) {
248 indent
:= strings
.Repeat(" ", depth
)
251 t
.Logf("%s%T (%p) waiting for -> %T (%p)", indent
, dep
, dep
, k
, k
)
252 if fc
, ok
:= k
.(finalCloser
); ok
{
254 db
.dumpDep(t
, depth
+1, fc
, seen
)
260 func TestQuery(t
*testing
.T
) {
261 db
:= newTestDB(t
, "people")
263 prepares0
:= numPrepares(t
, db
)
264 rows
, err
:= db
.Query("SELECT|people|age,name|")
266 t
.Fatalf("Query: %v", err
)
275 err
= rows
.Scan(&r
.age
, &r
.name
)
277 t
.Fatalf("Scan: %v", err
)
283 t
.Fatalf("Err: %v", err
)
286 {age
: 1, name
: "Alice"},
287 {age
: 2, name
: "Bob"},
288 {age
: 3, name
: "Chris"},
290 if !reflect
.DeepEqual(got
, want
) {
291 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got
, want
)
294 // And verify that the final rows.Next() call, which hit EOF,
295 // also closed the rows connection.
296 if n
:= db
.numFreeConns(); n
!= 1 {
297 t
.Fatalf("free conns after query hitting EOF = %d; want 1", n
)
299 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
300 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
304 // TestQueryContext tests canceling the context while scanning the rows.
305 func TestQueryContext(t
*testing
.T
) {
306 db
:= newTestDB(t
, "people")
308 prepares0
:= numPrepares(t
, db
)
310 ctx
, cancel
:= context
.WithCancel(context
.Background())
313 rows
, err
:= db
.QueryContext(ctx
, "SELECT|people|age,name|")
315 t
.Fatalf("Query: %v", err
)
326 waitForRowsClose(t
, rows
)
329 err
= rows
.Scan(&r
.age
, &r
.name
)
334 t
.Fatalf("Scan: %v", err
)
336 if index
== 2 && err
!= context
.Canceled
{
337 t
.Fatalf("Scan: %v; want context.Canceled", err
)
344 if err
:= ctx
.Err(); err
!= context
.Canceled
{
345 t
.Fatalf("context err = %v; want context.Canceled", err
)
348 t
.Fatalf("context err = nil; want context.Canceled")
351 {age
: 1, name
: "Alice"},
352 {age
: 2, name
: "Bob"},
354 if !reflect
.DeepEqual(got
, want
) {
355 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got
, want
)
358 // And verify that the final rows.Next() call, which hit EOF,
359 // also closed the rows connection.
360 waitForRowsClose(t
, rows
)
361 waitForFree(t
, db
, 1)
362 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
363 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
367 func waitCondition(t testing
.TB
, fn
func() bool) bool {
368 timeout
:= 5 * time
.Second
370 type deadliner
interface {
371 Deadline() (time
.Time
, bool)
373 if td
, ok
:= t
.(deadliner
); ok
{
374 if deadline
, ok
:= td
.Deadline(); ok
{
375 timeout
= time
.Until(deadline
)
376 timeout
= timeout
* 19 / 20 // Give 5% headroom for cleanup and error-reporting.
380 deadline
:= time
.Now().Add(timeout
)
385 if time
.Until(deadline
) < pollDuration
{
388 time
.Sleep(pollDuration
)
392 // waitForFree checks db.numFreeConns until either it equals want or
393 // the maxWait time elapses.
394 func waitForFree(t
*testing
.T
, db
*DB
, want
int) {
396 if !waitCondition(t
, func() bool {
397 numFree
= db
.numFreeConns()
398 return numFree
== want
400 t
.Fatalf("free conns after hitting EOF = %d; want %d", numFree
, want
)
404 func waitForRowsClose(t
*testing
.T
, rows
*Rows
) {
405 if !waitCondition(t
, func() bool {
407 defer rows
.closemu
.RUnlock()
410 t
.Fatal("failed to close rows")
414 // TestQueryContextWait ensures that rows and all internal statements are closed when
415 // a query context is closed during execution.
416 func TestQueryContextWait(t
*testing
.T
) {
417 db
:= newTestDB(t
, "people")
419 prepares0
:= numPrepares(t
, db
)
421 ctx
, cancel
:= context
.WithCancel(context
.Background())
424 // This will trigger the *fakeConn.Prepare method which will take time
425 // performing the query. The ctxDriverPrepare func will check the context
426 // after this and close the rows and return an error.
427 c
, err
:= db
.Conn(ctx
)
432 c
.dc
.ci
.(*fakeConn
).waiter
= func(c context
.Context
) {
436 _
, err
= c
.QueryContext(ctx
, "SELECT|people|age,name|")
438 if err
!= context
.Canceled
{
439 t
.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err
)
442 // Verify closed rows connection after error condition.
443 waitForFree(t
, db
, 1)
444 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
445 t
.Fatalf("executed %d Prepare statements; want 1", prepares
)
449 // TestTxContextWait tests the transaction behavior when the tx context is canceled
450 // during execution of the query.
451 func TestTxContextWait(t
*testing
.T
) {
452 db
:= newTestDB(t
, "people")
455 ctx
, cancel
:= context
.WithCancel(context
.Background())
457 tx
, err
:= db
.BeginTx(ctx
, nil)
461 tx
.keepConnOnRollback
= false
463 tx
.dc
.ci
.(*fakeConn
).waiter
= func(c context
.Context
) {
467 // This will trigger the *fakeConn.Prepare method which will take time
468 // performing the query. The ctxDriverPrepare func will check the context
469 // after this and close the rows and return an error.
470 _
, err
= tx
.QueryContext(ctx
, "SELECT|people|age,name|")
471 if err
!= context
.Canceled
{
472 t
.Fatalf("expected QueryContext to error with context canceled but returned %v", err
)
475 waitForFree(t
, db
, 0)
478 // TestTxContextWaitNoDiscard is the same as TestTxContextWait, but should not discard
479 // the final connection.
480 func TestTxContextWaitNoDiscard(t
*testing
.T
) {
481 db
:= newTestDB(t
, "people")
484 ctx
, cancel
:= context
.WithTimeout(context
.Background(), 15*time
.Millisecond
)
487 tx
, err
:= db
.BeginTx(ctx
, nil)
489 // Guard against the context being canceled before BeginTx completes.
490 if err
== context
.DeadlineExceeded
{
491 t
.Skip("tx context canceled prior to first use")
496 // This will trigger the *fakeConn.Prepare method which will take time
497 // performing the query. The ctxDriverPrepare func will check the context
498 // after this and close the rows and return an error.
499 _
, err
= tx
.QueryContext(ctx
, "WAIT|1s|SELECT|people|age,name|")
500 if err
!= context
.DeadlineExceeded
{
501 t
.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err
)
504 waitForFree(t
, db
, 1)
507 // TestUnsupportedOptions checks that the database fails when a driver that
508 // doesn't implement ConnBeginTx is used with non-default options and an
509 // un-cancellable context.
510 func TestUnsupportedOptions(t
*testing
.T
) {
511 db
:= newTestDB(t
, "people")
513 _
, err
:= db
.BeginTx(context
.Background(), &TxOptions
{
514 Isolation
: LevelSerializable
, ReadOnly
: true,
517 t
.Fatal("expected error when using unsupported options, got nil")
521 func TestMultiResultSetQuery(t
*testing
.T
) {
522 db
:= newTestDB(t
, "people")
524 prepares0
:= numPrepares(t
, db
)
525 rows
, err
:= db
.Query("SELECT|people|age,name|;SELECT|people|name|")
527 t
.Fatalf("Query: %v", err
)
539 err
= rows
.Scan(&r
.age
, &r
.name
)
541 t
.Fatalf("Scan: %v", err
)
543 got1
= append(got1
, r
)
547 t
.Fatalf("Err: %v", err
)
550 {age
: 1, name
: "Alice"},
551 {age
: 2, name
: "Bob"},
552 {age
: 3, name
: "Chris"},
554 if !reflect
.DeepEqual(got1
, want1
) {
555 t
.Errorf("mismatch.\n got1: %#v\nwant: %#v", got1
, want1
)
558 if !rows
.NextResultSet() {
559 t
.Errorf("expected another result set")
565 err
= rows
.Scan(&r
.name
)
567 t
.Fatalf("Scan: %v", err
)
569 got2
= append(got2
, r
)
573 t
.Fatalf("Err: %v", err
)
580 if !reflect
.DeepEqual(got2
, want2
) {
581 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got2
, want2
)
583 if rows
.NextResultSet() {
584 t
.Errorf("expected no more result sets")
587 // And verify that the final rows.Next() call, which hit EOF,
588 // also closed the rows connection.
589 waitForFree(t
, db
, 1)
590 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
591 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
595 func TestQueryNamedArg(t
*testing
.T
) {
596 db
:= newTestDB(t
, "people")
598 prepares0
:= numPrepares(t
, db
)
599 rows
, err
:= db
.Query(
600 // Ensure the name and age parameters only match on placeholder name, not position.
601 "SELECT|people|age,name|name=?name,age=?age",
603 Named("name", "Bob"),
606 t
.Fatalf("Query: %v", err
)
615 err
= rows
.Scan(&r
.age
, &r
.name
)
617 t
.Fatalf("Scan: %v", err
)
623 t
.Fatalf("Err: %v", err
)
626 {age
: 2, name
: "Bob"},
628 if !reflect
.DeepEqual(got
, want
) {
629 t
.Errorf("mismatch.\n got: %#v\nwant: %#v", got
, want
)
632 // And verify that the final rows.Next() call, which hit EOF,
633 // also closed the rows connection.
634 if n
:= db
.numFreeConns(); n
!= 1 {
635 t
.Fatalf("free conns after query hitting EOF = %d; want 1", n
)
637 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
638 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
642 func TestPoolExhaustOnCancel(t
*testing
.T
) {
648 var saturate
, saturateDone sync
.WaitGroup
650 saturateDone
.Add(max
)
652 donePing
:= make(chan bool)
655 // waiter will be called for all queries, including
656 // initial setup queries. The state is only assigned when
657 // no queries are made.
659 // Only allow the first batch of queries to finish once the
660 // second batch of Ping queries have finished.
661 waiter
:= func(ctx context
.Context
) {
664 // Nothing. Initial database setup.
674 db
:= newTestDBConnector(t
, &fakeConnector
{waiter
: waiter
}, "people")
677 db
.SetMaxOpenConns(max
)
679 // First saturate the connection pool.
680 // Then start new requests for a connection that is canceled after it is requested.
683 for i
:= 0; i
< max
; i
++ {
685 rows
, err
:= db
.Query("SELECT|people|name,photo|")
687 t
.Errorf("Query: %v", err
)
701 // Now cancel the request while it is waiting.
702 ctx
, cancel
:= context
.WithTimeout(context
.Background(), 2*time
.Second
)
705 for i
:= 0; i
< max
; i
++ {
706 ctxReq
, cancelReq
:= context
.WithCancel(ctx
)
708 time
.Sleep(100 * time
.Millisecond
)
711 err
:= db
.PingContext(ctxReq
)
712 if err
!= context
.Canceled
{
713 t
.Fatalf("PingContext (Exhaust): %v", err
)
719 // Now try to open a normal connection.
720 err
:= db
.PingContext(ctx
)
722 t
.Fatalf("PingContext (Normal): %v", err
)
726 func TestRowsColumns(t
*testing
.T
) {
727 db
:= newTestDB(t
, "people")
729 rows
, err
:= db
.Query("SELECT|people|age,name|")
731 t
.Fatalf("Query: %v", err
)
733 cols
, err
:= rows
.Columns()
735 t
.Fatalf("Columns: %v", err
)
737 want
:= []string{"age", "name"}
738 if !reflect
.DeepEqual(cols
, want
) {
739 t
.Errorf("got %#v; want %#v", cols
, want
)
741 if err
:= rows
.Close(); err
!= nil {
742 t
.Errorf("error closing rows: %s", err
)
746 func TestRowsColumnTypes(t
*testing
.T
) {
747 db
:= newTestDB(t
, "people")
749 rows
, err
:= db
.Query("SELECT|people|age,name|")
751 t
.Fatalf("Query: %v", err
)
753 tt
, err
:= rows
.ColumnTypes()
755 t
.Fatalf("ColumnTypes: %v", err
)
758 types
:= make([]reflect
.Type
, len(tt
))
759 for i
, tp
:= range tt
{
762 t
.Errorf("scantype is null for column %q", tp
.Name())
767 values
:= make([]any
, len(tt
))
768 for i
:= range values
{
769 values
[i
] = reflect
.New(types
[i
]).Interface()
773 err
= rows
.Scan(values
...)
775 t
.Fatalf("failed to scan values in %v", err
)
778 if age
:= *values
[0].(*int32); age
!= 2 {
779 t
.Errorf("Expected 2, got %v", age
)
781 if name
:= *values
[1].(*string); name
!= "Bob" {
782 t
.Errorf("Expected Bob, got %v", name
)
788 t
.Errorf("expected 3 rows, got %d", ct
)
791 if err
:= rows
.Close(); err
!= nil {
792 t
.Errorf("error closing rows: %s", err
)
796 func TestQueryRow(t
*testing
.T
) {
797 db
:= newTestDB(t
, "people")
801 var birthday time
.Time
803 err
:= db
.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age
)
804 if err
== nil ||
!strings
.Contains(err
.Error(), "expected 2 destination arguments") {
805 t
.Errorf("expected error from wrong number of arguments; actually got: %v", err
)
808 err
= db
.QueryRow("SELECT|people|bdate|age=?", 3).Scan(&birthday
)
809 if err
!= nil ||
!birthday
.Equal(chrisBirthday
) {
810 t
.Errorf("chris birthday = %v, err = %v; want %v", birthday
, err
, chrisBirthday
)
813 err
= db
.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age
, &name
)
815 t
.Fatalf("age QueryRow+Scan: %v", err
)
818 t
.Errorf("expected name Bob, got %q", name
)
821 t
.Errorf("expected age 2, got %d", age
)
824 err
= db
.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age
, &name
)
826 t
.Fatalf("name QueryRow+Scan: %v", err
)
829 t
.Errorf("expected name Alice, got %q", name
)
832 t
.Errorf("expected age 1, got %d", age
)
836 err
= db
.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo
)
838 t
.Fatalf("photo QueryRow+Scan: %v", err
)
840 want
:= []byte("APHOTO")
841 if !reflect
.DeepEqual(photo
, want
) {
842 t
.Errorf("photo = %q; want %q", photo
, want
)
846 func TestRowErr(t
*testing
.T
) {
847 db
:= newTestDB(t
, "people")
849 err
:= db
.QueryRowContext(context
.Background(), "SELECT|people|bdate|age=?", 3).Err()
851 t
.Errorf("Unexpected err = %v; want %v", err
, nil)
854 ctx
, cancel
:= context
.WithCancel(context
.Background())
857 err
= db
.QueryRowContext(ctx
, "SELECT|people|bdate|age=?", 3).Err()
858 exp
:= "context canceled"
859 if err
== nil ||
!strings
.Contains(err
.Error(), exp
) {
860 t
.Errorf("Expected err = %v; got %v", exp
, err
)
864 func TestTxRollbackCommitErr(t
*testing
.T
) {
865 db
:= newTestDB(t
, "people")
868 tx
, err
:= db
.Begin()
874 t
.Errorf("expected nil error from Rollback; got %v", err
)
877 if err
!= ErrTxDone
{
878 t
.Errorf("expected %q from Commit; got %q", ErrTxDone
, err
)
887 t
.Errorf("expected nil error from Commit; got %v", err
)
890 if err
!= ErrTxDone
{
891 t
.Errorf("expected %q from Rollback; got %q", ErrTxDone
, err
)
895 func TestStatementErrorAfterClose(t
*testing
.T
) {
896 db
:= newTestDB(t
, "people")
898 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
900 t
.Fatalf("Prepare: %v", err
)
904 t
.Fatalf("Close: %v", err
)
907 err
= stmt
.QueryRow("foo").Scan(&name
)
909 t
.Errorf("expected error from QueryRow.Scan after Stmt.Close")
913 func TestStatementQueryRow(t
*testing
.T
) {
914 db
:= newTestDB(t
, "people")
916 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
918 t
.Fatalf("Prepare: %v", err
)
922 for n
, tt
:= range []struct {
930 if err
:= stmt
.QueryRow(tt
.name
).Scan(&age
); err
!= nil {
931 t
.Errorf("%d: on %q, QueryRow/Scan: %v", n
, tt
.name
, err
)
932 } else if age
!= tt
.want
{
933 t
.Errorf("%d: age=%d, want %d", n
, age
, tt
.want
)
938 type stubDriverStmt
struct {
942 func (s stubDriverStmt
) Close() error
{
946 func (s stubDriverStmt
) NumInput() int {
950 func (s stubDriverStmt
) Exec(args
[]driver
.Value
) (driver
.Result
, error
) {
954 func (s stubDriverStmt
) Query(args
[]driver
.Value
) (driver
.Rows
, error
) {
958 // golang.org/issue/12798
959 func TestStatementClose(t
*testing
.T
) {
960 want
:= errors
.New("STMT ERROR")
966 {&Stmt
{stickyErr
: want
}, "stickyErr not propagated"},
967 {&Stmt
{cg
: &Tx
{}, cgds
: &driverStmt
{Locker
: &sync
.Mutex
{}, si
: stubDriverStmt
{want
}}}, "driverStmt.Close() error not propagated"},
969 for _
, test
:= range tests
{
970 if err
:= test
.stmt
.Close(); err
!= want
{
971 t
.Errorf("%s. Got stmt.Close() = %v, want = %v", test
.msg
, err
, want
)
976 // golang.org/issue/3734
977 func TestStatementQueryRowConcurrent(t
*testing
.T
) {
978 db
:= newTestDB(t
, "people")
980 stmt
, err
:= db
.Prepare("SELECT|people|age|name=?")
982 t
.Fatalf("Prepare: %v", err
)
987 ch
:= make(chan error
, n
)
988 for i
:= 0; i
< n
; i
++ {
991 err
:= stmt
.QueryRow("Alice").Scan(&age
)
992 if err
== nil && age
!= 1 {
993 err
= fmt
.Errorf("unexpected age %d", age
)
998 for i
:= 0; i
< n
; i
++ {
999 if err
:= <-ch
; err
!= nil {
1005 // just a test of fakedb itself
1006 func TestBogusPreboundParameters(t
*testing
.T
) {
1007 db
:= newTestDB(t
, "foo")
1008 defer closeDB(t
, db
)
1009 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1010 _
, err
:= db
.Prepare("INSERT|t1|name=?,age=bogusconversion")
1012 t
.Fatalf("expected error")
1014 if err
.Error() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
1015 t
.Errorf("unexpected error: %v", err
)
1019 func TestExec(t
*testing
.T
) {
1020 db
:= newTestDB(t
, "foo")
1021 defer closeDB(t
, db
)
1022 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1023 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1025 t
.Errorf("Stmt, err = %v, %v", stmt
, err
)
1029 type execTest
struct {
1033 execTests
:= []execTest
{
1035 {[]any
{"Brad", 31}, ""},
1036 {[]any
{"Brad", int64(31)}, ""},
1037 {[]any
{"Bob", "32"}, ""},
1040 // Invalid conversions:
1041 {[]any
{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"},
1042 {[]any
{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`},
1044 // Wrong number of args:
1045 {[]any
{}, "sql: expected 2 arguments, got 0"},
1046 {[]any
{1, 2, 3}, "sql: expected 2 arguments, got 3"},
1048 for n
, et
:= range execTests
{
1049 _
, err
:= stmt
.Exec(et
.args
...)
1052 errStr
= err
.Error()
1054 if errStr
!= et
.wantErr
{
1055 t
.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
1056 n
, et
.args
, errStr
, et
.wantErr
)
1061 func TestTxPrepare(t
*testing
.T
) {
1062 db
:= newTestDB(t
, "")
1063 defer closeDB(t
, db
)
1064 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1065 tx
, err
:= db
.Begin()
1067 t
.Fatalf("Begin = %v", err
)
1069 stmt
, err
:= tx
.Prepare("INSERT|t1|name=?,age=?")
1071 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1074 _
, err
= stmt
.Exec("Bobby", 7)
1076 t
.Fatalf("Exec = %v", err
)
1080 t
.Fatalf("Commit = %v", err
)
1082 // Commit() should have closed the statement
1084 t
.Fatal("Stmt not closed after Commit")
1088 func TestTxStmt(t
*testing
.T
) {
1089 db
:= newTestDB(t
, "")
1090 defer closeDB(t
, db
)
1091 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1092 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1094 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1097 tx
, err
:= db
.Begin()
1099 t
.Fatalf("Begin = %v", err
)
1101 txs
:= tx
.Stmt(stmt
)
1103 _
, err
= txs
.Exec("Bobby", 7)
1105 t
.Fatalf("Exec = %v", err
)
1109 t
.Fatalf("Commit = %v", err
)
1111 // Commit() should have closed the statement
1113 t
.Fatal("Stmt not closed after Commit")
1117 func TestTxStmtPreparedOnce(t
*testing
.T
) {
1118 db
:= newTestDB(t
, "")
1119 defer closeDB(t
, db
)
1120 exec(t
, db
, "CREATE|t1|name=string,age=int32")
1122 prepares0
:= numPrepares(t
, db
)
1124 // db.Prepare increments numPrepares.
1125 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1127 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1131 tx
, err
:= db
.Begin()
1133 t
.Fatalf("Begin = %v", err
)
1136 txs1
:= tx
.Stmt(stmt
)
1137 txs2
:= tx
.Stmt(stmt
)
1139 _
, err
= txs1
.Exec("Go", 7)
1141 t
.Fatalf("Exec = %v", err
)
1145 _
, err
= txs2
.Exec("Gopher", 8)
1147 t
.Fatalf("Exec = %v", err
)
1153 t
.Fatalf("Commit = %v", err
)
1156 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
1157 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
1161 func TestTxStmtClosedRePrepares(t
*testing
.T
) {
1162 db
:= newTestDB(t
, "")
1163 defer closeDB(t
, db
)
1164 exec(t
, db
, "CREATE|t1|name=string,age=int32")
1166 prepares0
:= numPrepares(t
, db
)
1168 // db.Prepare increments numPrepares.
1169 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1171 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1173 tx
, err
:= db
.Begin()
1175 t
.Fatalf("Begin = %v", err
)
1179 t
.Fatalf("stmt.Close() = %v", err
)
1181 // tx.Stmt increments numPrepares because stmt is closed.
1182 txs
:= tx
.Stmt(stmt
)
1183 if txs
.stickyErr
!= nil {
1184 t
.Fatal(txs
.stickyErr
)
1186 if txs
.parentStmt
!= nil {
1187 t
.Fatal("expected nil parentStmt")
1189 _
, err
= txs
.Exec(`Eric`, 82)
1191 t
.Fatalf("txs.Exec = %v", err
)
1196 t
.Fatalf("txs.Close = %v", err
)
1201 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 2 {
1202 t
.Errorf("executed %d Prepare statements; want 2", prepares
)
1206 func TestParentStmtOutlivesTxStmt(t
*testing
.T
) {
1207 db
:= newTestDB(t
, "")
1208 defer closeDB(t
, db
)
1209 exec(t
, db
, "CREATE|t1|name=string,age=int32")
1211 // Make sure everything happens on the same connection.
1212 db
.SetMaxOpenConns(1)
1214 prepares0
:= numPrepares(t
, db
)
1216 // db.Prepare increments numPrepares.
1217 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1219 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1222 tx
, err
:= db
.Begin()
1224 t
.Fatalf("Begin = %v", err
)
1226 txs
:= tx
.Stmt(stmt
)
1227 if len(stmt
.css
) != 1 {
1228 t
.Fatalf("len(stmt.css) = %v; want 1", len(stmt
.css
))
1232 t
.Fatalf("txs.Close() = %v", err
)
1236 t
.Fatalf("tx.Rollback() = %v", err
)
1238 // txs must not be valid.
1239 _
, err
= txs
.Exec("Suzan", 30)
1241 t
.Fatalf("txs.Exec(), expected err")
1243 // Stmt must still be valid.
1244 _
, err
= stmt
.Exec("Janina", 25)
1246 t
.Fatalf("stmt.Exec() = %v", err
)
1249 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 1 {
1250 t
.Errorf("executed %d Prepare statements; want 1", prepares
)
1254 // Test that tx.Stmt called with a statement already
1255 // associated with tx as argument re-prepares the same
1257 func TestTxStmtFromTxStmtRePrepares(t
*testing
.T
) {
1258 db
:= newTestDB(t
, "")
1259 defer closeDB(t
, db
)
1260 exec(t
, db
, "CREATE|t1|name=string,age=int32")
1261 prepares0
:= numPrepares(t
, db
)
1262 // db.Prepare increments numPrepares.
1263 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1265 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1269 tx
, err
:= db
.Begin()
1271 t
.Fatalf("Begin = %v", err
)
1273 txs1
:= tx
.Stmt(stmt
)
1275 // tx.Stmt(txs1) increments numPrepares because txs1 already
1276 // belongs to a transaction (albeit the same transaction).
1277 txs2
:= tx
.Stmt(txs1
)
1278 if txs2
.stickyErr
!= nil {
1279 t
.Fatal(txs2
.stickyErr
)
1281 if txs2
.parentStmt
!= nil {
1282 t
.Fatal("expected nil parentStmt")
1284 _
, err
= txs2
.Exec(`Eric`, 82)
1291 t
.Fatalf("txs1.Close = %v", err
)
1295 t
.Fatalf("txs1.Close = %v", err
)
1299 t
.Fatalf("tx.Rollback = %v", err
)
1302 if prepares
:= numPrepares(t
, db
) - prepares0
; prepares
!= 2 {
1303 t
.Errorf("executed %d Prepare statements; want 2", prepares
)
1307 // Issue: https://golang.org/issue/2784
1308 // This test didn't fail before because we got lucky with the fakedb driver.
1309 // It was failing, and now not, in github.com/bradfitz/go-sql-test
1310 func TestTxQuery(t
*testing
.T
) {
1311 db
:= newTestDB(t
, "")
1312 defer closeDB(t
, db
)
1313 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1314 exec(t
, db
, "INSERT|t1|name=Alice")
1316 tx
, err
:= db
.Begin()
1322 r
, err
:= tx
.Query("SELECT|t1|name|")
1332 t
.Fatal("expected one row")
1342 func TestTxQueryInvalid(t
*testing
.T
) {
1343 db
:= newTestDB(t
, "")
1344 defer closeDB(t
, db
)
1346 tx
, err
:= db
.Begin()
1352 _
, err
= tx
.Query("SELECT|t1|name|")
1354 t
.Fatal("Error expected")
1358 // Tests fix for issue 4433, that retries in Begin happen when
1359 // conn.Begin() returns ErrBadConn
1360 func TestTxErrBadConn(t
*testing
.T
) {
1361 db
, err
:= Open("test", fakeDBName
+";badConn")
1363 t
.Fatalf("Open: %v", err
)
1365 if _
, err
:= db
.Exec("WIPE"); err
!= nil {
1366 t
.Fatalf("exec wipe: %v", err
)
1368 defer closeDB(t
, db
)
1369 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
1370 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?")
1372 t
.Fatalf("Stmt, err = %v, %v", stmt
, err
)
1375 tx
, err
:= db
.Begin()
1377 t
.Fatalf("Begin = %v", err
)
1379 txs
:= tx
.Stmt(stmt
)
1381 _
, err
= txs
.Exec("Bobby", 7)
1383 t
.Fatalf("Exec = %v", err
)
1387 t
.Fatalf("Commit = %v", err
)
1391 func TestConnQuery(t
*testing
.T
) {
1392 db
:= newTestDB(t
, "people")
1393 defer closeDB(t
, db
)
1395 ctx
, cancel
:= context
.WithCancel(context
.Background())
1397 conn
, err
:= db
.Conn(ctx
)
1401 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
1405 err
= conn
.QueryRowContext(ctx
, "SELECT|people|name|age=?", 3).Scan(&name
)
1409 if name
!= "Chris" {
1410 t
.Fatalf("unexpected result, got %q want Chris", name
)
1413 err
= conn
.PingContext(ctx
)
1419 func TestConnRaw(t
*testing
.T
) {
1420 db
:= newTestDB(t
, "people")
1421 defer closeDB(t
, db
)
1423 ctx
, cancel
:= context
.WithCancel(context
.Background())
1425 conn
, err
:= db
.Conn(ctx
)
1429 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
1433 err
= conn
.Raw(func(dc any
) error
{
1435 if _
, ok
:= dc
.(*fakeConn
); !ok
{
1436 return fmt
.Errorf("got %T want *fakeConn", dc
)
1444 t
.Fatal("Raw func not called")
1451 t
.Fatal("expected panic")
1454 closed := conn
.dc
== nil
1455 conn
.closemu
.Unlock()
1457 t
.Fatal("expected connection to be closed after panic")
1460 err
= conn
.Raw(func(dc any
) error
{
1461 panic("Conn.Raw panic should return an error")
1463 t
.Fatal("expected panic from Raw func")
1467 func TestCursorFake(t
*testing
.T
) {
1468 db
:= newTestDB(t
, "people")
1469 defer closeDB(t
, db
)
1471 ctx
, cancel
:= context
.WithTimeout(context
.Background(), time
.Second
*30)
1474 exec(t
, db
, "CREATE|peoplecursor|list=table")
1475 exec(t
, db
, "INSERT|peoplecursor|list=people!name!age")
1477 rows
, err
:= db
.QueryContext(ctx
, `SELECT|peoplecursor|list|`)
1486 var cursor
= &Rows
{}
1487 err
= rows
.Scan(cursor
)
1491 defer cursor
.Close()
1493 const expectedRows
= 3
1494 var currentRow
int64
1500 err
= cursor
.Scan(&s
, &n
)
1504 if n
!= currentRow
{
1505 t
.Errorf("expected number(Age)=%d, got %d", currentRow
, n
)
1508 if currentRow
!= expectedRows
{
1509 t
.Errorf("expected %d rows, got %d rows", expectedRows
, currentRow
)
1513 func TestInvalidNilValues(t
*testing
.T
) {
1520 expectedError
string
1525 expectedError
: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type <nil> into type *time.Time`,
1530 expectedError
: `sql: Scan error on column index 0, name "bdate": converting NULL to int is unsupported`,
1534 for _
, tt
:= range tests
{
1535 t
.Run(tt
.name
, func(t
*testing
.T
) {
1536 db
:= newTestDB(t
, "people")
1537 defer closeDB(t
, db
)
1539 ctx
, cancel
:= context
.WithCancel(context
.Background())
1541 conn
, err
:= db
.Conn(ctx
)
1545 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
1548 err
= conn
.QueryRowContext(ctx
, "SELECT|people|bdate|age=?", 1).Scan(tt
.input
)
1550 t
.Fatal("expected error when querying nil column, but succeeded")
1552 if err
.Error() != tt
.expectedError
{
1553 t
.Fatalf("Expected error: %s\nReceived: %s", tt
.expectedError
, err
.Error())
1556 err
= conn
.PingContext(ctx
)
1564 func TestConnTx(t
*testing
.T
) {
1565 db
:= newTestDB(t
, "people")
1566 defer closeDB(t
, db
)
1568 ctx
, cancel
:= context
.WithCancel(context
.Background())
1570 conn
, err
:= db
.Conn(ctx
)
1574 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
1577 tx
, err
:= conn
.BeginTx(ctx
, nil)
1581 insertName
, insertAge
:= "Nancy", 33
1582 _
, err
= tx
.ExecContext(ctx
, "INSERT|people|name=?,age=?,photo=APHOTO", insertName
, insertAge
)
1591 var selectName
string
1592 err
= conn
.QueryRowContext(ctx
, "SELECT|people|name|age=?", insertAge
).Scan(&selectName
)
1596 if selectName
!= insertName
{
1597 t
.Fatalf("got %q want %q", selectName
, insertName
)
1601 // TestConnIsValid verifies that a database connection that should be discarded,
1602 // is actually discarded and does not re-enter the connection pool.
1603 // If the IsValid method from *fakeConn is removed, this test will fail.
1604 func TestConnIsValid(t
*testing
.T
) {
1605 db
:= newTestDB(t
, "people")
1606 defer closeDB(t
, db
)
1608 db
.SetMaxOpenConns(1)
1610 ctx
:= context
.Background()
1612 c
, err
:= db
.Conn(ctx
)
1617 err
= c
.Raw(func(raw any
) error
{
1618 dc
:= raw
.(*fakeConn
)
1627 if len(db
.freeConn
) > 0 && db
.freeConn
[0].ci
.(*fakeConn
).stickyBad
{
1628 t
.Fatal("bad connection returned to pool; expected bad connection to be discarded")
1632 // Tests fix for issue 2542, that we release a lock when querying on
1633 // a closed connection.
1634 func TestIssue2542Deadlock(t
*testing
.T
) {
1635 db
:= newTestDB(t
, "people")
1637 for i
:= 0; i
< 2; i
++ {
1638 _
, err
:= db
.Query("SELECT|people|age,name|")
1640 t
.Fatalf("expected error")
1645 // From golang.org/issue/3865
1646 func TestCloseStmtBeforeRows(t
*testing
.T
) {
1647 db
:= newTestDB(t
, "people")
1648 defer closeDB(t
, db
)
1650 s
, err
:= db
.Prepare("SELECT|people|name|")
1669 // Tests fix for issue 2788, that we bind nil to a []byte if the
1670 // value in the column is sql null
1671 func TestNullByteSlice(t
*testing
.T
) {
1672 db
:= newTestDB(t
, "")
1673 defer closeDB(t
, db
)
1674 exec(t
, db
, "CREATE|t|id=int32,name=nullstring")
1675 exec(t
, db
, "INSERT|t|id=10,name=?", nil)
1679 err
:= db
.QueryRow("SELECT|t|name|id=?", 10).Scan(&name
)
1684 t
.Fatalf("name []byte should be nil for null column value, got: %#v", name
)
1687 exec(t
, db
, "INSERT|t|id=11,name=?", "bob")
1688 err
= db
.QueryRow("SELECT|t|name|id=?", 11).Scan(&name
)
1692 if string(name
) != "bob" {
1693 t
.Fatalf("name []byte should be bob, got: %q", string(name
))
1697 func TestPointerParamsAndScans(t
*testing
.T
) {
1698 db
:= newTestDB(t
, "")
1699 defer closeDB(t
, db
)
1700 exec(t
, db
, "CREATE|t|id=int32,name=nullstring")
1706 exec(t
, db
, "INSERT|t|id=10,name=?", name
)
1708 exec(t
, db
, "INSERT|t|id=20,name=?", name
)
1710 err
:= db
.QueryRow("SELECT|t|name|id=?", 10).Scan(&name
)
1712 t
.Fatalf("querying id 10: %v", err
)
1715 t
.Errorf("id 10's name = nil; want bob")
1716 } else if *name
!= "bob" {
1717 t
.Errorf("id 10's name = %q; want bob", *name
)
1720 err
= db
.QueryRow("SELECT|t|name|id=?", 20).Scan(&name
)
1722 t
.Fatalf("querying id 20: %v", err
)
1725 t
.Errorf("id 20 = %q; want nil", *name
)
1729 func TestQueryRowClosingStmt(t
*testing
.T
) {
1730 db
:= newTestDB(t
, "people")
1731 defer closeDB(t
, db
)
1734 err
:= db
.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age
, &name
)
1738 if len(db
.freeConn
) != 1 {
1739 t
.Fatalf("expected 1 free conn")
1741 fakeConn
:= db
.freeConn
[0].ci
.(*fakeConn
)
1742 if made
, closed := fakeConn
.stmtsMade
, fakeConn
.stmtsClosed
; made
!= closed {
1743 t
.Errorf("statement close mismatch: made %d, closed %d", made
, closed)
1747 var atomicRowsCloseHook atomic
.Value
// of func(*Rows, *error)
1750 rowsCloseHook
= func() func(*Rows
, *error
) {
1751 fn
, _
:= atomicRowsCloseHook
.Load().(func(*Rows
, *error
))
1756 func setRowsCloseHook(fn
func(*Rows
, *error
)) {
1758 // Can't change an atomic.Value back to nil, so set it to this
1759 // no-op func instead.
1760 fn
= func(*Rows
, *error
) {}
1762 atomicRowsCloseHook
.Store(fn
)
1766 func TestIssue6651(t
*testing
.T
) {
1767 db
:= newTestDB(t
, "people")
1768 defer closeDB(t
, db
)
1772 want
:= "error in rows.Next"
1773 rowsCursorNextHook
= func(dest
[]driver
.Value
) error
{
1774 return fmt
.Errorf(want
)
1776 defer func() { rowsCursorNextHook
= nil }()
1778 err
:= db
.QueryRow("SELECT|people|name|").Scan(&v
)
1779 if err
== nil || err
.Error() != want
{
1780 t
.Errorf("error = %q; want %q", err
, want
)
1782 rowsCursorNextHook
= nil
1784 want
= "error in rows.Close"
1785 setRowsCloseHook(func(rows
*Rows
, err
*error
) {
1786 *err
= fmt
.Errorf(want
)
1788 defer setRowsCloseHook(nil)
1789 err
= db
.QueryRow("SELECT|people|name|").Scan(&v
)
1790 if err
== nil || err
.Error() != want
{
1791 t
.Errorf("error = %q; want %q", err
, want
)
1795 type nullTestRow
struct {
1801 type nullTestSpec
struct {
1807 func TestNullStringParam(t
*testing
.T
) {
1808 spec
:= nullTestSpec
{"nullstring", "string", [6]nullTestRow
{
1809 {NullString
{"aqua", true}, "", NullString
{"aqua", true}},
1810 {NullString
{"brown", false}, "", NullString
{"", false}},
1811 {"chartreuse", "", NullString
{"chartreuse", true}},
1812 {NullString
{"darkred", true}, "", NullString
{"darkred", true}},
1813 {NullString
{"eel", false}, "", NullString
{"", false}},
1814 {"foo", NullString
{"black", false}, nil},
1816 nullTestRun(t
, spec
)
1819 func TestNullInt64Param(t
*testing
.T
) {
1820 spec
:= nullTestSpec
{"nullint64", "int64", [6]nullTestRow
{
1821 {NullInt64
{31, true}, 1, NullInt64
{31, true}},
1822 {NullInt64
{-22, false}, 1, NullInt64
{0, false}},
1823 {22, 1, NullInt64
{22, true}},
1824 {NullInt64
{33, true}, 1, NullInt64
{33, true}},
1825 {NullInt64
{222, false}, 1, NullInt64
{0, false}},
1826 {0, NullInt64
{31, false}, nil},
1828 nullTestRun(t
, spec
)
1831 func TestNullInt32Param(t
*testing
.T
) {
1832 spec
:= nullTestSpec
{"nullint32", "int32", [6]nullTestRow
{
1833 {NullInt32
{31, true}, 1, NullInt32
{31, true}},
1834 {NullInt32
{-22, false}, 1, NullInt32
{0, false}},
1835 {22, 1, NullInt32
{22, true}},
1836 {NullInt32
{33, true}, 1, NullInt32
{33, true}},
1837 {NullInt32
{222, false}, 1, NullInt32
{0, false}},
1838 {0, NullInt32
{31, false}, nil},
1840 nullTestRun(t
, spec
)
1843 func TestNullInt16Param(t
*testing
.T
) {
1844 spec
:= nullTestSpec
{"nullint16", "int16", [6]nullTestRow
{
1845 {NullInt16
{31, true}, 1, NullInt16
{31, true}},
1846 {NullInt16
{-22, false}, 1, NullInt16
{0, false}},
1847 {22, 1, NullInt16
{22, true}},
1848 {NullInt16
{33, true}, 1, NullInt16
{33, true}},
1849 {NullInt16
{222, false}, 1, NullInt16
{0, false}},
1850 {0, NullInt16
{31, false}, nil},
1852 nullTestRun(t
, spec
)
1855 func TestNullByteParam(t
*testing
.T
) {
1856 spec
:= nullTestSpec
{"nullbyte", "byte", [6]nullTestRow
{
1857 {NullByte
{31, true}, 1, NullByte
{31, true}},
1858 {NullByte
{0, false}, 1, NullByte
{0, false}},
1859 {22, 1, NullByte
{22, true}},
1860 {NullByte
{33, true}, 1, NullByte
{33, true}},
1861 {NullByte
{222, false}, 1, NullByte
{0, false}},
1862 {0, NullByte
{31, false}, nil},
1864 nullTestRun(t
, spec
)
1867 func TestNullFloat64Param(t
*testing
.T
) {
1868 spec
:= nullTestSpec
{"nullfloat64", "float64", [6]nullTestRow
{
1869 {NullFloat64
{31.2, true}, 1, NullFloat64
{31.2, true}},
1870 {NullFloat64
{13.1, false}, 1, NullFloat64
{0, false}},
1871 {-22.9, 1, NullFloat64
{-22.9, true}},
1872 {NullFloat64
{33.81, true}, 1, NullFloat64
{33.81, true}},
1873 {NullFloat64
{222, false}, 1, NullFloat64
{0, false}},
1874 {10, NullFloat64
{31.2, false}, nil},
1876 nullTestRun(t
, spec
)
1879 func TestNullBoolParam(t
*testing
.T
) {
1880 spec
:= nullTestSpec
{"nullbool", "bool", [6]nullTestRow
{
1881 {NullBool
{false, true}, true, NullBool
{false, true}},
1882 {NullBool
{true, false}, false, NullBool
{false, false}},
1883 {true, true, NullBool
{true, true}},
1884 {NullBool
{true, true}, false, NullBool
{true, true}},
1885 {NullBool
{true, false}, true, NullBool
{false, false}},
1886 {true, NullBool
{true, false}, nil},
1888 nullTestRun(t
, spec
)
1891 func TestNullTimeParam(t
*testing
.T
) {
1893 t1
:= time
.Date(2000, 1, 1, 8, 9, 10, 11, time
.UTC
)
1894 t2
:= time
.Date(2010, 1, 1, 8, 9, 10, 11, time
.UTC
)
1895 spec
:= nullTestSpec
{"nulldatetime", "datetime", [6]nullTestRow
{
1896 {NullTime
{t1
, true}, t2
, NullTime
{t1
, true}},
1897 {NullTime
{t1
, false}, t2
, NullTime
{t0
, false}},
1898 {t1
, t2
, NullTime
{t1
, true}},
1899 {NullTime
{t1
, true}, t2
, NullTime
{t1
, true}},
1900 {NullTime
{t1
, false}, t2
, NullTime
{t0
, false}},
1901 {t2
, NullTime
{t1
, false}, nil},
1903 nullTestRun(t
, spec
)
1906 func nullTestRun(t
*testing
.T
, spec nullTestSpec
) {
1907 db
:= newTestDB(t
, "")
1908 defer closeDB(t
, db
)
1909 exec(t
, db
, fmt
.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec
.nullType
, spec
.notNullType
))
1911 // Inserts with db.Exec:
1912 exec(t
, db
, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec
.rows
[0].nullParam
, spec
.rows
[0].notNullParam
)
1913 exec(t
, db
, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec
.rows
[1].nullParam
, spec
.rows
[1].notNullParam
)
1915 // Inserts with a prepared statement:
1916 stmt
, err
:= db
.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
1918 t
.Fatalf("prepare: %v", err
)
1921 if _
, err
:= stmt
.Exec(3, "chris", spec
.rows
[2].nullParam
, spec
.rows
[2].notNullParam
); err
!= nil {
1922 t
.Errorf("exec insert chris: %v", err
)
1924 if _
, err
:= stmt
.Exec(4, "dave", spec
.rows
[3].nullParam
, spec
.rows
[3].notNullParam
); err
!= nil {
1925 t
.Errorf("exec insert dave: %v", err
)
1927 if _
, err
:= stmt
.Exec(5, "eleanor", spec
.rows
[4].nullParam
, spec
.rows
[4].notNullParam
); err
!= nil {
1928 t
.Errorf("exec insert eleanor: %v", err
)
1931 // Can't put null val into non-null col
1932 if _
, err
:= stmt
.Exec(6, "bob", spec
.rows
[5].nullParam
, spec
.rows
[5].notNullParam
); err
== nil {
1933 t
.Errorf("expected error inserting nil val with prepared statement Exec")
1936 _
, err
= db
.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
1938 // TODO: this test fails, but it's just because
1939 // fakeConn implements the optional Execer interface,
1940 // so arguably this is the correct behavior. But
1941 // maybe I should flesh out the fakeConn.Exec
1942 // implementation so this properly fails.
1943 // t.Errorf("expected error inserting nil name with Exec")
1946 paramtype
:= reflect
.TypeOf(spec
.rows
[0].nullParam
)
1947 bindVal
:= reflect
.New(paramtype
).Interface()
1949 for i
:= 0; i
< 5; i
++ {
1951 if err
:= db
.QueryRow("SELECT|t|nullf|id=?", id
).Scan(bindVal
); err
!= nil {
1952 t
.Errorf("id=%d Scan: %v", id
, err
)
1954 bindValDeref
:= reflect
.ValueOf(bindVal
).Elem().Interface()
1955 if !reflect
.DeepEqual(bindValDeref
, spec
.rows
[i
].scanNullVal
) {
1956 t
.Errorf("id=%d got %#v, want %#v", id
, bindValDeref
, spec
.rows
[i
].scanNullVal
)
1961 // golang.org/issue/4859
1962 func TestQueryRowNilScanDest(t
*testing
.T
) {
1963 db
:= newTestDB(t
, "people")
1964 defer closeDB(t
, db
)
1965 var name
*string // nil pointer
1966 err
:= db
.QueryRow("SELECT|people|name|").Scan(name
)
1967 want
:= `sql: Scan error on column index 0, name "name": destination pointer is nil`
1968 if err
== nil || err
.Error() != want
{
1969 t
.Errorf("error = %q; want %q", err
.Error(), want
)
1973 func TestIssue4902(t
*testing
.T
) {
1974 db
:= newTestDB(t
, "people")
1975 defer closeDB(t
, db
)
1977 driver
:= db
.Driver().(*fakeDriver
)
1978 opens0
:= driver
.openCount
1982 for i
:= 0; i
< 10; i
++ {
1983 stmt
, err
= db
.Prepare("SELECT|people|name|")
1993 opens
:= driver
.openCount
- opens0
1995 t
.Errorf("opens = %d; want <= 1", opens
)
1996 t
.Logf("db = %#v", db
)
1997 t
.Logf("driver = %#v", driver
)
1998 t
.Logf("stmt = %#v", stmt
)
2003 // This used to deadlock.
2004 func TestSimultaneousQueries(t
*testing
.T
) {
2005 db
:= newTestDB(t
, "people")
2006 defer closeDB(t
, db
)
2008 tx
, err
:= db
.Begin()
2014 r1
, err
:= tx
.Query("SELECT|people|name|")
2020 r2
, err
:= tx
.Query("SELECT|people|name|")
2027 func TestMaxIdleConns(t
*testing
.T
) {
2028 db
:= newTestDB(t
, "people")
2029 defer closeDB(t
, db
)
2031 tx
, err
:= db
.Begin()
2036 if got
:= len(db
.freeConn
); got
!= 1 {
2037 t
.Errorf("freeConns = %d; want 1", got
)
2040 db
.SetMaxIdleConns(0)
2042 if got
:= len(db
.freeConn
); got
!= 0 {
2043 t
.Errorf("freeConns after set to zero = %d; want 0", got
)
2046 tx
, err
= db
.Begin()
2051 if got
:= len(db
.freeConn
); got
!= 0 {
2052 t
.Errorf("freeConns = %d; want 0", got
)
2056 func TestMaxOpenConns(t
*testing
.T
) {
2057 if testing
.Short() {
2058 t
.Skip("skipping in short mode")
2060 defer setHookpostCloseConn(nil)
2061 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
2063 t
.Errorf("Error closing fakeConn: %v", err
)
2067 db
:= newTestDB(t
, "magicquery")
2068 defer closeDB(t
, db
)
2070 driver
:= db
.Driver().(*fakeDriver
)
2072 // Force the number of open connections to 0 so we can get an accurate
2073 // count for the test
2077 opens0
:= driver
.openCount
2078 closes0
:= driver
.closeCount
2081 db
.SetMaxIdleConns(10)
2082 db
.SetMaxOpenConns(10)
2084 stmt
, err
:= db
.Prepare("SELECT|magicquery|op|op=?,millis=?")
2089 // Start 50 parallel slow queries.
2095 var wg sync
.WaitGroup
2096 for batch
:= 0; batch
< nbatch
; batch
++ {
2097 for i
:= 0; i
< nquery
; i
++ {
2102 if err
:= stmt
.QueryRow("sleep", sleepMillis
).Scan(&op
); err
!= nil && err
!= ErrNoRows
{
2107 // Wait for the batch of queries above to finish before starting the next round.
2111 if g
, w
:= db
.numFreeConns(), 10; g
!= w
{
2112 t
.Errorf("free conns = %d; want %d", g
, w
)
2115 if n
:= db
.numDepsPoll(t
, 20); n
> 20 {
2116 t
.Errorf("number of dependencies = %d; expected <= 20", n
)
2121 opens
:= driver
.openCount
- opens0
2122 closes
:= driver
.closeCount
- closes0
2126 t
.Logf("open calls = %d", opens
)
2127 t
.Logf("close calls = %d", closes
)
2128 t
.Errorf("db connections opened = %d; want <= 10", opens
)
2132 if err
:= stmt
.Close(); err
!= nil {
2136 if g
, w
:= db
.numFreeConns(), 10; g
!= w
{
2137 t
.Errorf("free conns = %d; want %d", g
, w
)
2140 if n
:= db
.numDepsPoll(t
, 10); n
> 10 {
2141 t
.Errorf("number of dependencies = %d; expected <= 10", n
)
2145 db
.SetMaxOpenConns(5)
2147 if g
, w
:= db
.numFreeConns(), 5; g
!= w
{
2148 t
.Errorf("free conns = %d; want %d", g
, w
)
2151 if n
:= db
.numDepsPoll(t
, 5); n
> 5 {
2152 t
.Errorf("number of dependencies = %d; expected 0", n
)
2156 db
.SetMaxOpenConns(0)
2158 if g
, w
:= db
.numFreeConns(), 5; g
!= w
{
2159 t
.Errorf("free conns = %d; want %d", g
, w
)
2162 if n
:= db
.numDepsPoll(t
, 5); n
> 5 {
2163 t
.Errorf("number of dependencies = %d; expected 0", n
)
2170 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime
2171 // and affects the subsequent release of connections.
2172 func TestMaxOpenConnsOnBusy(t
*testing
.T
) {
2173 defer setHookpostCloseConn(nil)
2174 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
2176 t
.Errorf("Error closing fakeConn: %v", err
)
2180 db
:= newTestDB(t
, "magicquery")
2181 defer closeDB(t
, db
)
2183 db
.SetMaxOpenConns(3)
2185 ctx
:= context
.Background()
2187 conn0
, err
:= db
.conn(ctx
, cachedOrNewConn
)
2189 t
.Fatalf("db open conn fail: %v", err
)
2192 conn1
, err
:= db
.conn(ctx
, cachedOrNewConn
)
2194 t
.Fatalf("db open conn fail: %v", err
)
2197 conn2
, err
:= db
.conn(ctx
, cachedOrNewConn
)
2199 t
.Fatalf("db open conn fail: %v", err
)
2202 if g
, w
:= db
.numOpen
, 3; g
!= w
{
2203 t
.Errorf("free conns = %d; want %d", g
, w
)
2206 db
.SetMaxOpenConns(2)
2207 if g
, w
:= db
.numOpen
, 3; g
!= w
{
2208 t
.Errorf("free conns = %d; want %d", g
, w
)
2211 conn0
.releaseConn(nil)
2212 conn1
.releaseConn(nil)
2213 if g
, w
:= db
.numOpen
, 2; g
!= w
{
2214 t
.Errorf("free conns = %d; want %d", g
, w
)
2217 conn2
.releaseConn(nil)
2218 if g
, w
:= db
.numOpen
, 2; g
!= w
{
2219 t
.Errorf("free conns = %d; want %d", g
, w
)
2223 // Issue 10886: tests that all connection attempts return when more than
2224 // DB.maxOpen connections are in flight and the first DB.maxOpen fail.
2225 func TestPendingConnsAfterErr(t
*testing
.T
) {
2228 tryOpen
= maxOpen
*2 + 2
2231 // No queries will be run.
2232 db
, err
:= Open("test", fakeDBName
)
2234 t
.Fatalf("Open: %v", err
)
2236 defer closeDB(t
, db
)
2238 for k
, v
:= range db
.lastPut
{
2239 t
.Logf("%p: %v", k
, v
)
2243 db
.SetMaxOpenConns(maxOpen
)
2244 db
.SetMaxIdleConns(0)
2246 errOffline
:= errors
.New("db offline")
2248 defer func() { setHookOpenErr(nil) }()
2250 errs
:= make(chan error
, tryOpen
)
2252 var opening sync
.WaitGroup
2253 opening
.Add(tryOpen
)
2255 setHookOpenErr(func() error
{
2256 // Wait for all connections to enqueue.
2261 for i
:= 0; i
< tryOpen
; i
++ {
2263 opening
.Done() // signal one connection is in flight
2264 _
, err
:= db
.Exec("will never run")
2269 opening
.Wait() // wait for all workers to begin running
2271 const timeout
= 5 * time
.Second
2272 to
:= time
.NewTimer(timeout
)
2275 // check that all connections fail without deadlock
2276 for i
:= 0; i
< tryOpen
; i
++ {
2279 if got
, want
:= err
, errOffline
; got
!= want
{
2280 t
.Errorf("unexpected err: got %v, want %v", got
, want
)
2283 t
.Fatalf("orphaned connection request(s), still waiting after %v", timeout
)
2287 // Wait a reasonable time for the database to close all connections.
2288 tick
:= time
.NewTicker(3 * time
.Millisecond
)
2294 if db
.numOpen
== 0 {
2300 // Closing the database will check for numOpen and fail the test.
2306 func TestSingleOpenConn(t
*testing
.T
) {
2307 db
:= newTestDB(t
, "people")
2308 defer closeDB(t
, db
)
2310 db
.SetMaxOpenConns(1)
2312 rows
, err
:= db
.Query("SELECT|people|name|")
2316 if err
= rows
.Close(); err
!= nil {
2319 // shouldn't deadlock
2320 rows
, err
= db
.Query("SELECT|people|name|")
2324 if err
= rows
.Close(); err
!= nil {
2329 func TestStats(t
*testing
.T
) {
2330 db
:= newTestDB(t
, "people")
2332 if got
:= stats
.OpenConnections
; got
!= 1 {
2333 t
.Errorf("stats.OpenConnections = %d; want 1", got
)
2336 tx
, err
:= db
.Begin()
2344 if got
:= stats
.OpenConnections
; got
!= 0 {
2345 t
.Errorf("stats.OpenConnections = %d; want 0", got
)
2349 func TestConnMaxLifetime(t
*testing
.T
) {
2350 t0
:= time
.Unix(1000000, 0)
2351 offset
:= time
.Duration(0)
2353 nowFunc
= func() time
.Time
{ return t0
.Add(offset
) }
2354 defer func() { nowFunc
= time
.Now
}()
2356 db
:= newTestDB(t
, "magicquery")
2357 defer closeDB(t
, db
)
2359 driver
:= db
.Driver().(*fakeDriver
)
2361 // Force the number of open connections to 0 so we can get an accurate
2362 // count for the test
2366 opens0
:= driver
.openCount
2367 closes0
:= driver
.closeCount
2370 db
.SetMaxIdleConns(10)
2371 db
.SetMaxOpenConns(10)
2373 tx
, err
:= db
.Begin()
2378 offset
= time
.Second
2379 tx2
, err
:= db
.Begin()
2388 opens
:= driver
.openCount
- opens0
2389 closes
:= driver
.closeCount
- closes0
2393 t
.Errorf("opens = %d; want 2", opens
)
2396 t
.Errorf("closes = %d; want 0", closes
)
2398 if g
, w
:= db
.numFreeConns(), 2; g
!= w
{
2399 t
.Errorf("free conns = %d; want %d", g
, w
)
2402 // Expire first conn
2403 offset
= 11 * time
.Second
2404 db
.SetConnMaxLifetime(10 * time
.Second
)
2409 tx
, err
= db
.Begin()
2413 tx2
, err
= db
.Begin()
2420 // Give connectionCleaner chance to run.
2421 waitCondition(t
, func() bool {
2423 opens
= driver
.openCount
- opens0
2424 closes
= driver
.closeCount
- closes0
2431 t
.Errorf("opens = %d; want 3", opens
)
2434 t
.Errorf("closes = %d; want 1", closes
)
2437 if s
:= db
.Stats(); s
.MaxLifetimeClosed
!= 1 {
2438 t
.Errorf("MaxLifetimeClosed = %d; want 1 %#v", s
.MaxLifetimeClosed
, s
)
2442 // golang.org/issue/5323
2443 func TestStmtCloseDeps(t
*testing
.T
) {
2444 if testing
.Short() {
2445 t
.Skip("skipping in short mode")
2447 defer setHookpostCloseConn(nil)
2448 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
2450 t
.Errorf("Error closing fakeConn: %v", err
)
2454 db
:= newTestDB(t
, "magicquery")
2455 defer closeDB(t
, db
)
2457 driver
:= db
.Driver().(*fakeDriver
)
2460 opens0
:= driver
.openCount
2461 closes0
:= driver
.closeCount
2463 openDelta0
:= opens0
- closes0
2465 stmt
, err
:= db
.Prepare("SELECT|magicquery|op|op=?,millis=?")
2470 // Start 50 parallel slow queries.
2476 var wg sync
.WaitGroup
2477 for batch
:= 0; batch
< nbatch
; batch
++ {
2478 for i
:= 0; i
< nquery
; i
++ {
2483 if err
:= stmt
.QueryRow("sleep", sleepMillis
).Scan(&op
); err
!= nil && err
!= ErrNoRows
{
2488 // Wait for the batch of queries above to finish before starting the next round.
2492 if g
, w
:= db
.numFreeConns(), 2; g
!= w
{
2493 t
.Errorf("free conns = %d; want %d", g
, w
)
2496 if n
:= db
.numDepsPoll(t
, 4); n
> 4 {
2497 t
.Errorf("number of dependencies = %d; expected <= 4", n
)
2502 opens
:= driver
.openCount
- opens0
2503 closes
:= driver
.closeCount
- closes0
2504 openDelta
:= (driver
.openCount
- driver
.closeCount
) - openDelta0
2508 t
.Logf("open calls = %d", opens
)
2509 t
.Logf("close calls = %d", closes
)
2510 t
.Logf("open delta = %d", openDelta
)
2511 t
.Errorf("db connections opened = %d; want <= 2", openDelta
)
2515 if !waitCondition(t
, func() bool {
2516 return len(stmt
.css
) <= nquery
2518 t
.Errorf("len(stmt.css) = %d; want <= %d", len(stmt
.css
), nquery
)
2521 if err
:= stmt
.Close(); err
!= nil {
2525 if g
, w
:= db
.numFreeConns(), 2; g
!= w
{
2526 t
.Errorf("free conns = %d; want %d", g
, w
)
2529 if n
:= db
.numDepsPoll(t
, 2); n
> 2 {
2530 t
.Errorf("number of dependencies = %d; expected <= 2", n
)
2537 // golang.org/issue/5046
2538 func TestCloseConnBeforeStmts(t
*testing
.T
) {
2539 db
:= newTestDB(t
, "people")
2540 defer closeDB(t
, db
)
2542 defer setHookpostCloseConn(nil)
2543 setHookpostCloseConn(func(_
*fakeConn
, err error
) {
2545 t
.Errorf("Error closing fakeConn: %v; from %s", err
, stack())
2547 t
.Errorf("DB = %#v", db
)
2551 stmt
, err
:= db
.Prepare("SELECT|people|name|")
2556 if len(db
.freeConn
) != 1 {
2557 t
.Fatalf("expected 1 freeConn; got %d", len(db
.freeConn
))
2559 dc
:= db
.freeConn
[0]
2561 t
.Errorf("conn shouldn't be closed")
2564 if n
:= len(dc
.openStmt
); n
!= 1 {
2565 t
.Errorf("driverConn num openStmt = %d; want 1", n
)
2569 t
.Errorf("db Close = %v", err
)
2572 t
.Errorf("after db.Close, driverConn should be closed")
2574 if n
:= len(dc
.openStmt
); n
!= 0 {
2575 t
.Errorf("driverConn num openStmt = %d; want 0", n
)
2580 t
.Errorf("Stmt close = %v", err
)
2584 t
.Errorf("conn should be closed")
2587 t
.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
2591 // golang.org/issue/5283: don't release the Rows' connection in Close
2592 // before calling Stmt.Close.
2593 func TestRowsCloseOrder(t
*testing
.T
) {
2594 db
:= newTestDB(t
, "people")
2595 defer closeDB(t
, db
)
2597 db
.SetMaxIdleConns(0)
2598 setStrictFakeConnClose(t
)
2599 defer setStrictFakeConnClose(nil)
2601 rows
, err
:= db
.Query("SELECT|people|age,name|")
2611 func TestRowsImplicitClose(t
*testing
.T
) {
2612 db
:= newTestDB(t
, "people")
2613 defer closeDB(t
, db
)
2615 rows
, err
:= db
.Query("SELECT|people|age,name|")
2620 want
, fail
:= 2, errors
.New("fail")
2621 r
:= rows
.rowsi
.(*rowsCursor
)
2622 r
.errPos
, r
.err
= want
, fail
2629 t
.Errorf("got %d rows, want %d", got
, want
)
2631 if err
:= rows
.Err(); err
!= fail
{
2632 t
.Errorf("got error %v, want %v", err
, fail
)
2635 t
.Errorf("r.closed is false, want true")
2639 func TestStmtCloseOrder(t
*testing
.T
) {
2640 db
:= newTestDB(t
, "people")
2641 defer closeDB(t
, db
)
2643 db
.SetMaxIdleConns(0)
2644 setStrictFakeConnClose(t
)
2645 defer setStrictFakeConnClose(nil)
2647 _
, err
:= db
.Query("SELECT|non_existent|name|")
2649 t
.Fatal("Querying non-existent table should fail")
2653 // Test cases where there's more than maxBadConnRetries bad connections in the
2654 // pool (issue 8834)
2655 func TestManyErrBadConn(t
*testing
.T
) {
2656 manyErrBadConnSetup
:= func(first
...func(db
*DB
)) *DB
{
2657 db
:= newTestDB(t
, "people")
2659 for _
, f
:= range first
{
2663 nconn
:= maxBadConnRetries
+ 1
2664 db
.SetMaxIdleConns(nconn
)
2665 db
.SetMaxOpenConns(nconn
)
2666 // open enough connections
2668 for i
:= 0; i
< nconn
; i
++ {
2669 rows
, err
:= db
.Query("SELECT|people|age,name|")
2678 defer db
.mu
.Unlock()
2679 if db
.numOpen
!= nconn
{
2680 t
.Fatalf("unexpected numOpen %d (was expecting %d)", db
.numOpen
, nconn
)
2681 } else if len(db
.freeConn
) != nconn
{
2682 t
.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db
.freeConn
), nconn
)
2684 for _
, conn
:= range db
.freeConn
{
2686 conn
.ci
.(*fakeConn
).stickyBad
= true
2693 db
:= manyErrBadConnSetup()
2694 defer closeDB(t
, db
)
2695 rows
, err
:= db
.Query("SELECT|people|age,name|")
2699 if err
= rows
.Close(); err
!= nil {
2704 db
= manyErrBadConnSetup()
2705 defer closeDB(t
, db
)
2706 _
, err
= db
.Exec("INSERT|people|name=Julia,age=19")
2712 db
= manyErrBadConnSetup()
2713 defer closeDB(t
, db
)
2714 tx
, err
:= db
.Begin()
2718 if err
= tx
.Rollback(); err
!= nil {
2723 db
= manyErrBadConnSetup()
2724 defer closeDB(t
, db
)
2725 stmt
, err
:= db
.Prepare("SELECT|people|age,name|")
2729 if err
= stmt
.Close(); err
!= nil {
2734 db
= manyErrBadConnSetup(func(db
*DB
) {
2735 stmt
, err
= db
.Prepare("INSERT|people|name=Julia,age=19")
2740 defer closeDB(t
, db
)
2741 _
, err
= stmt
.Exec()
2745 if err
= stmt
.Close(); err
!= nil {
2750 db
= manyErrBadConnSetup(func(db
*DB
) {
2751 stmt
, err
= db
.Prepare("SELECT|people|age,name|")
2756 defer closeDB(t
, db
)
2757 rows
, err
= stmt
.Query()
2761 if err
= rows
.Close(); err
!= nil {
2764 if err
= stmt
.Close(); err
!= nil {
2769 db
= manyErrBadConnSetup()
2770 defer closeDB(t
, db
)
2771 ctx
, cancel
:= context
.WithCancel(context
.Background())
2773 conn
, err
:= db
.Conn(ctx
)
2777 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
2784 db
= manyErrBadConnSetup()
2785 defer closeDB(t
, db
)
2786 err
= db
.PingContext(ctx
)
2792 // Issue 34775: Ensure that a Tx cannot commit after a rollback.
2793 func TestTxCannotCommitAfterRollback(t
*testing
.T
) {
2794 db
:= newTestDB(t
, "tx_status")
2795 defer closeDB(t
, db
)
2797 // First check query reporting is correct.
2799 err
:= db
.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus
)
2803 if g
, w
:= txStatus
, "autocommit"; g
!= w
{
2804 t
.Fatalf("tx_status=%q, wanted %q", g
, w
)
2807 ctx
, cancel
:= context
.WithCancel(context
.Background())
2810 tx
, err
:= db
.BeginTx(ctx
, nil)
2815 // Ignore dirty session for this test.
2816 // A failing test should trigger the dirty session flag as well,
2817 // but that isn't exactly what this should test for.
2818 tx
.txi
.(*fakeTx
).c
.skipDirtySession
= true
2822 err
= tx
.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus
)
2826 if g
, w
:= txStatus
, "transaction"; g
!= w
{
2827 t
.Fatalf("tx_status=%q, wanted %q", g
, w
)
2830 // 1. Begin a transaction.
2831 // 2. (A) Start a query, (B) begin Tx rollback through a ctx cancel.
2832 // 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail).
2833 sendQuery
:= make(chan struct{})
2834 // The Tx status is returned through the row results, ensure
2835 // that the rows results are not canceled.
2836 bypassRowsAwaitDone
= true
2837 hookTxGrabConn
= func() {
2841 rollbackHook
= func() {
2845 hookTxGrabConn
= nil
2847 bypassRowsAwaitDone
= false
2850 err
= tx
.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus
)
2852 // A failure here would be expected if skipDirtySession was not set to true above.
2855 if g
, w
:= txStatus
, "transaction"; g
!= w
{
2856 t
.Fatalf("tx_status=%q, wanted %q", g
, w
)
2860 // Issue 40985 transaction statement deadlock while context cancel.
2861 func TestTxStmtDeadlock(t
*testing
.T
) {
2862 db
:= newTestDB(t
, "people")
2863 defer closeDB(t
, db
)
2865 ctx
, cancel
:= context
.WithCancel(context
.Background())
2867 tx
, err
:= db
.BeginTx(ctx
, nil)
2872 stmt
, err
:= tx
.Prepare("SELECT|people|name,age|age=?")
2877 // Run number of stmt queries to reproduce deadlock from context cancel
2878 for i
:= 0; i
< 1e3
; i
++ {
2879 // Encounter any close related errors (e.g. ErrTxDone, stmt is closed)
2880 // is expected due to context cancel.
2881 _
, err
= stmt
.Query(1)
2889 // Issue32530 encounters an issue where a connection may
2890 // expire right after it comes out of a used connection pool
2891 // even when a new connection is requested.
2892 func TestConnExpiresFreshOutOfPool(t
*testing
.T
) {
2893 execCases
:= []struct {
2902 t0
:= time
.Unix(1000000, 0)
2903 offset
:= time
.Duration(0)
2904 offsetMu
:= sync
.RWMutex
{}
2906 nowFunc
= func() time
.Time
{
2908 defer offsetMu
.RUnlock()
2909 return t0
.Add(offset
)
2911 defer func() { nowFunc
= time
.Now
}()
2913 ctx
, cancel
:= context
.WithCancel(context
.Background())
2916 db
:= newTestDB(t
, "magicquery")
2917 defer closeDB(t
, db
)
2919 db
.SetMaxOpenConns(1)
2921 for _
, ec
:= range execCases
{
2923 name
:= fmt
.Sprintf("expired=%t,badReset=%t", ec
.expired
, ec
.badReset
)
2924 t
.Run(name
, func(t
*testing
.T
) {
2927 db
.SetMaxIdleConns(1)
2928 db
.SetConnMaxLifetime(10 * time
.Second
)
2930 conn
, err
:= db
.conn(ctx
, alwaysNewConn
)
2935 afterPutConn
:= make(chan struct{})
2936 waitingForConn
:= make(chan struct{})
2939 defer close(afterPutConn
)
2941 conn
, err
:= db
.conn(ctx
, alwaysNewConn
)
2943 db
.putConn(conn
, err
, false)
2945 t
.Errorf("db.conn: %v", err
)
2949 defer close(waitingForConn
)
2956 ct
:= len(db
.connRequests
)
2961 time
.Sleep(pollDuration
)
2973 offset
= 11 * time
.Second
2975 offset
= time
.Duration(0)
2979 conn
.ci
.(*fakeConn
).stickyBad
= ec
.badReset
2981 db
.putConn(conn
, err
, true)
2988 // TestIssue20575 ensures the Rows from query does not block
2989 // closing a transaction. Ensure Rows is closed while closing a trasaction.
2990 func TestIssue20575(t
*testing
.T
) {
2991 db
:= newTestDB(t
, "people")
2992 defer closeDB(t
, db
)
2994 tx
, err
:= db
.Begin()
2998 ctx
, cancel
:= context
.WithTimeout(context
.Background(), 3*time
.Second
)
3000 _
, err
= tx
.QueryContext(ctx
, "SELECT|people|age,name|")
3004 // Do not close Rows from QueryContext.
3012 t
.Fatal("timeout: failed to rollback query without closing rows:", ctx
.Err())
3016 // TestIssue20622 tests closing the transaction before rows is closed, requires
3017 // the race detector to fail.
3018 func TestIssue20622(t
*testing
.T
) {
3019 db
:= newTestDB(t
, "people")
3020 defer closeDB(t
, db
)
3022 ctx
, cancel
:= context
.WithCancel(context
.Background())
3025 tx
, err
:= db
.BeginTx(ctx
, nil)
3030 rows
, err
:= tx
.Query("SELECT|people|age,name|")
3040 if err
:= rows
.Scan(&age
, &name
); err
!= nil {
3041 t
.Fatal("scan failed", err
)
3047 time
.Sleep(100 * time
.Millisecond
)
3053 // golang.org/issue/5718
3054 func TestErrBadConnReconnect(t
*testing
.T
) {
3055 db
:= newTestDB(t
, "foo")
3056 defer closeDB(t
, db
)
3057 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
3059 simulateBadConn
:= func(name
string, hook
*func() bool, op
func() error
) {
3060 broken
, retried
:= false, false
3061 numOpen
:= db
.numOpen
3063 // simulate a broken connection on the first try
3064 *hook
= func() bool {
3073 if err
:= op(); err
!= nil {
3074 t
.Errorf(name
+": %v", err
)
3078 if !broken ||
!retried
{
3079 t
.Error(name
+ ": Failed to simulate broken connection")
3083 if numOpen
!= db
.numOpen
{
3084 t
.Errorf(name
+": leaked %d connection(s)!", db
.numOpen
-numOpen
)
3085 numOpen
= db
.numOpen
3090 dbExec
:= func() error
{
3091 _
, err
:= db
.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3094 simulateBadConn("db.Exec prepare", &hookPrepareBadConn
, dbExec
)
3095 simulateBadConn("db.Exec exec", &hookExecBadConn
, dbExec
)
3098 dbQuery
:= func() error
{
3099 rows
, err
:= db
.Query("SELECT|t1|age,name|")
3105 simulateBadConn("db.Query prepare", &hookPrepareBadConn
, dbQuery
)
3106 simulateBadConn("db.Query query", &hookQueryBadConn
, dbQuery
)
3109 simulateBadConn("db.Prepare", &hookPrepareBadConn
, func() error
{
3110 stmt
, err
:= db
.Prepare("INSERT|t1|name=?,age=?,dead=?")
3118 // Provide a way to force a re-prepare of a statement on next execution
3119 forcePrepare
:= func(stmt
*Stmt
) {
3124 stmt1
, err
:= db
.Prepare("INSERT|t1|name=?,age=?,dead=?")
3126 t
.Fatalf("prepare: %v", err
)
3129 // make sure we must prepare the stmt first
3132 stmtExec
:= func() error
{
3133 _
, err
:= stmt1
.Exec("Gopher", 3, false)
3136 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn
, stmtExec
)
3137 simulateBadConn("stmt.Exec exec", &hookExecBadConn
, stmtExec
)
3140 stmt2
, err
:= db
.Prepare("SELECT|t1|age,name|")
3142 t
.Fatalf("prepare: %v", err
)
3145 // make sure we must prepare the stmt first
3148 stmtQuery
:= func() error
{
3149 rows
, err
:= stmt2
.Query()
3155 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn
, stmtQuery
)
3156 simulateBadConn("stmt.Query exec", &hookQueryBadConn
, stmtQuery
)
3159 // golang.org/issue/11264
3160 func TestTxEndBadConn(t
*testing
.T
) {
3161 db
:= newTestDB(t
, "foo")
3162 defer closeDB(t
, db
)
3163 db
.SetMaxIdleConns(0)
3164 exec(t
, db
, "CREATE|t1|name=string,age=int32,dead=bool")
3165 db
.SetMaxIdleConns(1)
3167 simulateBadConn
:= func(name
string, hook
*func() bool, op
func() error
) {
3169 numOpen
:= db
.numOpen
3171 *hook
= func() bool {
3178 if err
:= op(); !errors
.Is(err
, driver
.ErrBadConn
) {
3179 t
.Errorf(name
+": %v", err
)
3184 t
.Error(name
+ ": Failed to simulate broken connection")
3188 if numOpen
!= db
.numOpen
{
3189 t
.Errorf(name
+": leaked %d connection(s)!", db
.numOpen
-numOpen
)
3194 dbExec
:= func(endTx
func(tx
*Tx
) error
) func() error
{
3195 return func() error
{
3196 tx
, err
:= db
.Begin()
3200 _
, err
= tx
.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3207 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn
, dbExec((*Tx
).Commit
))
3208 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn
, dbExec((*Tx
).Rollback
))
3211 dbQuery
:= func(endTx
func(tx
*Tx
) error
) func() error
{
3212 return func() error
{
3213 tx
, err
:= db
.Begin()
3217 rows
, err
:= tx
.Query("SELECT|t1|age,name|")
3226 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn
, dbQuery((*Tx
).Commit
))
3227 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn
, dbQuery((*Tx
).Rollback
))
3230 type concurrentTest
interface {
3231 init(t testing
.TB
, db
*DB
)
3232 finish(t testing
.TB
)
3233 test(t testing
.TB
) error
3236 type concurrentDBQueryTest
struct {
3240 func (c
*concurrentDBQueryTest
) init(t testing
.TB
, db
*DB
) {
3244 func (c
*concurrentDBQueryTest
) finish(t testing
.TB
) {
3248 func (c
*concurrentDBQueryTest
) test(t testing
.TB
) error
{
3249 rows
, err
:= c
.db
.Query("SELECT|people|name|")
3262 type concurrentDBExecTest
struct {
3266 func (c
*concurrentDBExecTest
) init(t testing
.TB
, db
*DB
) {
3270 func (c
*concurrentDBExecTest
) finish(t testing
.TB
) {
3274 func (c
*concurrentDBExecTest
) test(t testing
.TB
) error
{
3275 _
, err
:= c
.db
.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
3283 type concurrentStmtQueryTest
struct {
3288 func (c
*concurrentStmtQueryTest
) init(t testing
.TB
, db
*DB
) {
3291 c
.stmt
, err
= db
.Prepare("SELECT|people|name|")
3297 func (c
*concurrentStmtQueryTest
) finish(t testing
.TB
) {
3305 func (c
*concurrentStmtQueryTest
) test(t testing
.TB
) error
{
3306 rows
, err
:= c
.stmt
.Query()
3308 t
.Errorf("error on query: %v", err
)
3320 type concurrentStmtExecTest
struct {
3325 func (c
*concurrentStmtExecTest
) init(t testing
.TB
, db
*DB
) {
3328 c
.stmt
, err
= db
.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3334 func (c
*concurrentStmtExecTest
) finish(t testing
.TB
) {
3342 func (c
*concurrentStmtExecTest
) test(t testing
.TB
) error
{
3343 _
, err
:= c
.stmt
.Exec(3, chrisBirthday
)
3345 t
.Errorf("error on exec: %v", err
)
3351 type concurrentTxQueryTest
struct {
3356 func (c
*concurrentTxQueryTest
) init(t testing
.TB
, db
*DB
) {
3359 c
.tx
, err
= c
.db
.Begin()
3365 func (c
*concurrentTxQueryTest
) finish(t testing
.TB
) {
3373 func (c
*concurrentTxQueryTest
) test(t testing
.TB
) error
{
3374 rows
, err
:= c
.db
.Query("SELECT|people|name|")
3387 type concurrentTxExecTest
struct {
3392 func (c
*concurrentTxExecTest
) init(t testing
.TB
, db
*DB
) {
3395 c
.tx
, err
= c
.db
.Begin()
3401 func (c
*concurrentTxExecTest
) finish(t testing
.TB
) {
3409 func (c
*concurrentTxExecTest
) test(t testing
.TB
) error
{
3410 _
, err
:= c
.tx
.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday
)
3418 type concurrentTxStmtQueryTest
struct {
3424 func (c
*concurrentTxStmtQueryTest
) init(t testing
.TB
, db
*DB
) {
3427 c
.tx
, err
= c
.db
.Begin()
3431 c
.stmt
, err
= c
.tx
.Prepare("SELECT|people|name|")
3437 func (c
*concurrentTxStmtQueryTest
) finish(t testing
.TB
) {
3449 func (c
*concurrentTxStmtQueryTest
) test(t testing
.TB
) error
{
3450 rows
, err
:= c
.stmt
.Query()
3452 t
.Errorf("error on query: %v", err
)
3464 type concurrentTxStmtExecTest
struct {
3470 func (c
*concurrentTxStmtExecTest
) init(t testing
.TB
, db
*DB
) {
3473 c
.tx
, err
= c
.db
.Begin()
3477 c
.stmt
, err
= c
.tx
.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3483 func (c
*concurrentTxStmtExecTest
) finish(t testing
.TB
) {
3495 func (c
*concurrentTxStmtExecTest
) test(t testing
.TB
) error
{
3496 _
, err
:= c
.stmt
.Exec(3, chrisBirthday
)
3498 t
.Errorf("error on exec: %v", err
)
3504 type concurrentRandomTest
struct {
3505 tests
[]concurrentTest
3508 func (c
*concurrentRandomTest
) init(t testing
.TB
, db
*DB
) {
3509 c
.tests
= []concurrentTest
{
3510 new(concurrentDBQueryTest
),
3511 new(concurrentDBExecTest
),
3512 new(concurrentStmtQueryTest
),
3513 new(concurrentStmtExecTest
),
3514 new(concurrentTxQueryTest
),
3515 new(concurrentTxExecTest
),
3516 new(concurrentTxStmtQueryTest
),
3517 new(concurrentTxStmtExecTest
),
3519 for _
, ct
:= range c
.tests
{
3524 func (c
*concurrentRandomTest
) finish(t testing
.TB
) {
3525 for _
, ct
:= range c
.tests
{
3530 func (c
*concurrentRandomTest
) test(t testing
.TB
) error
{
3531 ct
:= c
.tests
[rand
.Intn(len(c
.tests
))]
3535 func doConcurrentTest(t testing
.TB
, ct concurrentTest
) {
3536 maxProcs
, numReqs
:= 1, 500
3537 if testing
.Short() {
3538 maxProcs
, numReqs
= 4, 50
3540 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(maxProcs
))
3542 db
:= newTestDB(t
, "people")
3543 defer closeDB(t
, db
)
3548 var wg sync
.WaitGroup
3551 reqs
:= make(chan bool)
3554 for i
:= 0; i
< maxProcs
*2; i
++ {
3567 for i
:= 0; i
< numReqs
; i
++ {
3574 func TestIssue6081(t
*testing
.T
) {
3575 db
:= newTestDB(t
, "people")
3576 defer closeDB(t
, db
)
3578 drv
:= db
.Driver().(*fakeDriver
)
3580 opens0
:= drv
.openCount
3581 closes0
:= drv
.closeCount
3584 stmt
, err
:= db
.Prepare("SELECT|people|name|")
3588 setRowsCloseHook(func(rows
*Rows
, err
*error
) {
3589 *err
= driver
.ErrBadConn
3591 defer setRowsCloseHook(nil)
3592 for i
:= 0; i
< 10; i
++ {
3593 rows
, err
:= stmt
.Query()
3599 if n
:= len(stmt
.css
); n
> 1 {
3600 t
.Errorf("len(css slice) = %d; want <= 1", n
)
3603 if n
:= len(stmt
.css
); n
!= 0 {
3604 t
.Errorf("len(css slice) after Close = %d; want 0", n
)
3608 opens
:= drv
.openCount
- opens0
3609 closes
:= drv
.closeCount
- closes0
3612 t
.Errorf("opens = %d; want >= 9", opens
)
3615 t
.Errorf("closes = %d; want >= 9", closes
)
3619 // TestIssue18429 attempts to stress rolling back the transaction from a
3620 // context cancel while simultaneously calling Tx.Rollback. Rolling back from a
3621 // context happens concurrently so tx.rollback and tx.Commit must guard against
3624 // In the test, a context is canceled while the query is in process so
3625 // the internal rollback will run concurrently with the explicitly called
3628 // The addition of calling rows.Next also tests
3630 func TestIssue18429(t
*testing
.T
) {
3631 db
:= newTestDB(t
, "people")
3632 defer closeDB(t
, db
)
3634 ctx
:= context
.Background()
3635 sem
:= make(chan bool, 20)
3636 var wg sync
.WaitGroup
3638 const milliWait
= 30
3640 for i
:= 0; i
< 100; i
++ {
3648 qwait
:= (time
.Duration(rand
.Intn(milliWait
)) * time
.Millisecond
).String()
3650 ctx
, cancel
:= context
.WithTimeout(ctx
, time
.Duration(rand
.Intn(milliWait
))*time
.Millisecond
)
3653 tx
, err
:= db
.BeginTx(ctx
, nil)
3657 // This is expected to give a cancel error most, but not all the time.
3658 // Test failure will happen with a panic or other race condition being
3660 rows
, _
:= tx
.QueryContext(ctx
, "WAIT|"+qwait
+"|SELECT|people|name|")
3663 // Call Next to test Issue 21117 and check for races.
3665 // Scan the buffer so it is read and checked for races.
3670 // This call will race with the context cancel rollback to complete
3671 // if the rollback itself isn't guarded.
3678 // TestIssue20160 attempts to test a short context life on a stmt Query.
3679 func TestIssue20160(t
*testing
.T
) {
3680 db
:= newTestDB(t
, "people")
3681 defer closeDB(t
, db
)
3683 ctx
:= context
.Background()
3684 sem
:= make(chan bool, 20)
3685 var wg sync
.WaitGroup
3687 const milliWait
= 30
3689 stmt
, err
:= db
.PrepareContext(ctx
, "SELECT|people|name|")
3695 for i
:= 0; i
< 100; i
++ {
3703 ctx
, cancel
:= context
.WithTimeout(ctx
, time
.Duration(rand
.Intn(milliWait
))*time
.Millisecond
)
3706 // This is expected to give a cancel error most, but not all the time.
3707 // Test failure will happen with a panic or other race condition being
3709 rows
, _
:= stmt
.QueryContext(ctx
)
3718 // TestIssue18719 closes the context right before use. The sql.driverConn
3719 // will nil out the ci on close in a lock, but if another process uses it right after
3720 // it will panic with on the nil ref.
3722 // See https://golang.org/cl/35550 .
3723 func TestIssue18719(t
*testing
.T
) {
3724 db
:= newTestDB(t
, "people")
3725 defer closeDB(t
, db
)
3727 ctx
, cancel
:= context
.WithCancel(context
.Background())
3730 tx
, err
:= db
.BeginTx(ctx
, nil)
3735 hookTxGrabConn
= func() {
3738 // Wait for the context to cancel and tx to rollback.
3739 for tx
.isDone() == false {
3740 time
.Sleep(pollDuration
)
3743 defer func() { hookTxGrabConn
= nil }()
3745 // This call will grab the connection and cancel the context
3746 // after it has done so. Code after must deal with the canceled state.
3747 _
, err
= tx
.QueryContext(ctx
, "SELECT|people|name|")
3749 t
.Fatalf("expected error %v but got %v", nil, err
)
3752 // Rows may be ignored because it will be closed when the context is canceled.
3754 // Do not explicitly rollback. The rollback will happen from the
3755 // canceled context.
3760 func TestIssue20647(t
*testing
.T
) {
3761 db
:= newTestDB(t
, "people")
3762 defer closeDB(t
, db
)
3764 ctx
, cancel
:= context
.WithCancel(context
.Background())
3767 conn
, err
:= db
.Conn(ctx
)
3771 conn
.dc
.ci
.(*fakeConn
).skipDirtySession
= true
3774 stmt
, err
:= conn
.PrepareContext(ctx
, "SELECT|people|name|")
3780 rows1
, err
:= stmt
.QueryContext(ctx
)
3782 t
.Fatal("rows1", err
)
3786 rows2
, err
:= stmt
.QueryContext(ctx
)
3788 t
.Fatal("rows2", err
)
3792 if rows1
.dc
!= rows2
.dc
{
3793 t
.Fatal("stmt prepared on Conn does not use same connection")
3797 func TestConcurrency(t
*testing
.T
) {
3802 {"Query", new(concurrentDBQueryTest
)},
3803 {"Exec", new(concurrentDBExecTest
)},
3804 {"StmtQuery", new(concurrentStmtQueryTest
)},
3805 {"StmtExec", new(concurrentStmtExecTest
)},
3806 {"TxQuery", new(concurrentTxQueryTest
)},
3807 {"TxExec", new(concurrentTxExecTest
)},
3808 {"TxStmtQuery", new(concurrentTxStmtQueryTest
)},
3809 {"TxStmtExec", new(concurrentTxStmtExecTest
)},
3810 {"Random", new(concurrentRandomTest
)},
3812 for _
, item
:= range list
{
3813 t
.Run(item
.name
, func(t
*testing
.T
) {
3814 doConcurrentTest(t
, item
.ct
)
3819 func TestConnectionLeak(t
*testing
.T
) {
3820 db
:= newTestDB(t
, "people")
3821 defer closeDB(t
, db
)
3822 // Start by opening defaultMaxIdleConns
3823 rows
:= make([]*Rows
, defaultMaxIdleConns
)
3824 // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open
3825 // a new connection and we can fill the idle queue with the released
3827 db
.SetMaxOpenConns(len(rows
) + 1)
3828 for ii
:= range rows
{
3829 r
, err
:= db
.Query("SELECT|people|name|")
3834 if err
:= r
.Err(); err
!= nil {
3839 // Now we have defaultMaxIdleConns busy connections. Open
3840 // a new one, but wait until the busy connections are released
3841 // before returning control to DB.
3842 drv
:= db
.Driver().(*fakeDriver
)
3843 drv
.waitCh
= make(chan struct{}, 1)
3844 drv
.waitingCh
= make(chan struct{}, 1)
3845 var wg sync
.WaitGroup
3848 r
, err
:= db
.Query("SELECT|people|name|")
3856 // Wait until the goroutine we've just created has started waiting.
3858 // Now close the busy connections. This provides a connection for
3859 // the blocked goroutine and then fills up the idle queue.
3860 for _
, v
:= range rows
{
3863 // At this point we give the new connection to DB. This connection is
3864 // now useless, since the idle queue is full and there are no pending
3865 // requests. DB should deal with this situation without leaking the
3867 drv
.waitCh
<- struct{}{}
3871 func TestStatsMaxIdleClosedZero(t
*testing
.T
) {
3872 db
:= newTestDB(t
, "people")
3873 defer closeDB(t
, db
)
3875 db
.SetMaxOpenConns(1)
3876 db
.SetMaxIdleConns(1)
3877 db
.SetConnMaxLifetime(0)
3879 preMaxIdleClosed
:= db
.Stats().MaxIdleClosed
3881 for i
:= 0; i
< 10; i
++ {
3882 rows
, err
:= db
.Query("SELECT|people|name|")
3890 maxIdleClosed
:= st
.MaxIdleClosed
- preMaxIdleClosed
3891 t
.Logf("MaxIdleClosed: %d", maxIdleClosed
)
3892 if maxIdleClosed
!= 0 {
3893 t
.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed
)
3897 func TestStatsMaxIdleClosedTen(t
*testing
.T
) {
3898 db
:= newTestDB(t
, "people")
3899 defer closeDB(t
, db
)
3901 db
.SetMaxOpenConns(1)
3902 db
.SetMaxIdleConns(0)
3903 db
.SetConnMaxLifetime(0)
3905 preMaxIdleClosed
:= db
.Stats().MaxIdleClosed
3907 for i
:= 0; i
< 10; i
++ {
3908 rows
, err
:= db
.Query("SELECT|people|name|")
3916 maxIdleClosed
:= st
.MaxIdleClosed
- preMaxIdleClosed
3917 t
.Logf("MaxIdleClosed: %d", maxIdleClosed
)
3918 if maxIdleClosed
!= 10 {
3919 t
.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed
)
3923 // testUseConns uses count concurrent connections with 1 nanosecond apart.
3924 // Returns the returnedAt time of the final connection.
3925 func testUseConns(t
*testing
.T
, count
int, tm time
.Time
, db
*DB
) time
.Time
{
3926 conns
:= make([]*Conn
, count
)
3927 ctx
:= context
.Background()
3928 for i
:= range conns
{
3929 tm
= tm
.Add(time
.Nanosecond
)
3930 nowFunc
= func() time
.Time
{
3933 c
, err
:= db
.Conn(ctx
)
3940 for i
:= len(conns
) - 1; i
>= 0; i
-- {
3941 tm
= tm
.Add(time
.Nanosecond
)
3942 nowFunc
= func() time
.Time
{
3945 if err
:= conns
[i
].Close(); err
!= nil {
3953 func TestMaxIdleTime(t
*testing
.T
) {
3957 wantMaxIdleTime time
.Duration
3958 wantMaxLifetime time
.Duration
3959 wantNextCheck time
.Duration
3960 wantIdleClosed
int64
3961 wantMaxIdleClosed
int64
3962 timeOffset time
.Duration
3963 secondTimeOffset time
.Duration
3968 time
.Millisecond
- time
.Nanosecond
,
3969 int64(usedConns
- reusedConns
),
3970 int64(usedConns
- reusedConns
),
3971 10 * time
.Millisecond
,
3975 // Want to close some connections via max idle time and one by max lifetime.
3977 // nowFunc() - MaxLifetime should be 1 * time.Nanosecond in connectionCleanerRunLocked.
3978 // This guarantees that first opened connection is to be closed.
3979 // Thus it is timeOffset + secondTimeOffset + 3 (+2 for Close while reusing conns and +1 for Conn).
3980 10*time
.Millisecond
+ 100*time
.Nanosecond
+ 3*time
.Nanosecond
,
3982 // Closed all not reused connections and extra one by max lifetime.
3983 int64(usedConns
- reusedConns
+ 1),
3984 int64(usedConns
- reusedConns
),
3985 10 * time
.Millisecond
,
3986 // Add second offset because otherwise connections are expired via max lifetime in Close.
3987 100 * time
.Nanosecond
,
3995 10 * time
.Millisecond
,
3998 baseTime
:= time
.Unix(0, 0)
4002 for _
, item
:= range list
{
4003 nowFunc
= func() time
.Time
{
4006 t
.Run(fmt
.Sprintf("%v", item
.wantMaxIdleTime
), func(t
*testing
.T
) {
4007 db
:= newTestDB(t
, "people")
4008 defer closeDB(t
, db
)
4010 db
.SetMaxOpenConns(usedConns
)
4011 db
.SetMaxIdleConns(usedConns
)
4012 db
.SetConnMaxIdleTime(item
.wantMaxIdleTime
)
4013 db
.SetConnMaxLifetime(item
.wantMaxLifetime
)
4015 preMaxIdleClosed
:= db
.Stats().MaxIdleTimeClosed
4018 testUseConns(t
, usedConns
, baseTime
, db
)
4020 tm
:= baseTime
.Add(item
.timeOffset
)
4022 // Reuse connections which should never be considered idle
4023 // and exercises the sorting for issue 39471.
4024 tm
= testUseConns(t
, reusedConns
, tm
, db
)
4026 tm
= tm
.Add(item
.secondTimeOffset
)
4027 nowFunc
= func() time
.Time
{
4032 nc
, closing
:= db
.connectionCleanerRunLocked(time
.Second
)
4033 if nc
!= item
.wantNextCheck
{
4034 t
.Errorf("got %v; want %v next check duration", nc
, item
.wantNextCheck
)
4037 // Validate freeConn order.
4039 for _
, c
:= range db
.freeConn
{
4040 if last
.After(c
.returnedAt
) {
4041 t
.Error("freeConn is not ordered by returnedAt")
4048 for _
, c
:= range closing
{
4051 if g
, w
:= int64(len(closing
)), item
.wantIdleClosed
; g
!= w
{
4052 t
.Errorf("got: %d; want %d closed conns", g
, w
)
4056 maxIdleClosed
:= st
.MaxIdleTimeClosed
- preMaxIdleClosed
4057 if g
, w
:= maxIdleClosed
, item
.wantMaxIdleClosed
; g
!= w
{
4058 t
.Errorf("got: %d; want %d max idle closed conns", g
, w
)
4064 type nvcDriver
struct {
4066 skipNamedValueCheck
bool
4069 func (d
*nvcDriver
) Open(dsn
string) (driver
.Conn
, error
) {
4070 c
, err
:= d
.fakeDriver
.Open(dsn
)
4072 fc
.db
.allowAny
= true
4073 return &nvcConn
{fc
, d
.skipNamedValueCheck
}, err
4076 type nvcConn
struct {
4078 skipNamedValueCheck
bool
4081 type decimalInt
struct {
4085 type doNotInclude
struct{}
4087 var _ driver
.NamedValueChecker
= &nvcConn
{}
4089 func (c
*nvcConn
) CheckNamedValue(nv
*driver
.NamedValue
) error
{
4090 if c
.skipNamedValueCheck
{
4091 return driver
.ErrSkip
4093 switch v
:= nv
.Value
.(type) {
4095 return driver
.ErrSkip
4097 switch ov
:= v
.Dest
.(type) {
4099 return errors
.New("unknown NameValueCheck OUTPUT type")
4102 nv
.Value
= "OUT:*string"
4105 case decimalInt
, []int64:
4108 return driver
.ErrRemoveArgument
4112 func TestNamedValueChecker(t
*testing
.T
) {
4113 Register("NamedValueCheck", &nvcDriver
{})
4114 db
, err
:= Open("NamedValueCheck", "")
4120 ctx
, cancel
:= context
.WithCancel(context
.Background())
4123 _
, err
= db
.ExecContext(ctx
, "WIPE")
4125 t
.Fatal("exec wipe", err
)
4128 _
, err
= db
.ExecContext(ctx
, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any")
4130 t
.Fatal("exec create", err
)
4134 _
, 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
{})
4136 t
.Fatal("exec insert", err
)
4143 err
= db
.QueryRowContext(ctx
, "SELECT|keys|dec1,str1,array1|").Scan(&dec1
, &str1
, &arr1
)
4145 t
.Fatal("select", err
)
4148 list
:= []struct{ got
, want any
}{
4149 {o1
, "from-server"},
4150 {dec1
, decimalInt
{123}},
4152 {arr1
, []int64{42, 128, 707}},
4155 for index
, item
:= range list
{
4156 if !reflect
.DeepEqual(item
.got
, item
.want
) {
4157 t
.Errorf("got %#v wanted %#v for index %d", item
.got
, item
.want
, index
)
4162 func TestNamedValueCheckerSkip(t
*testing
.T
) {
4163 Register("NamedValueCheckSkip", &nvcDriver
{skipNamedValueCheck
: true})
4164 db
, err
:= Open("NamedValueCheckSkip", "")
4170 ctx
, cancel
:= context
.WithCancel(context
.Background())
4173 _
, err
= db
.ExecContext(ctx
, "WIPE")
4175 t
.Fatal("exec wipe", err
)
4178 _
, err
= db
.ExecContext(ctx
, "CREATE|keys|dec1=any")
4180 t
.Fatal("exec create", err
)
4183 _
, err
= db
.ExecContext(ctx
, "INSERT|keys|dec1=?A", Named("A", decimalInt
{123}))
4185 t
.Fatalf("expected error with bad argument, got %v", err
)
4189 func TestOpenConnector(t
*testing
.T
) {
4190 Register("testctx", &fakeDriverCtx
{})
4191 db
, err
:= Open("testctx", "people")
4197 c
, ok
:= db
.connector
.(*fakeConnector
)
4199 t
.Fatal("not using *fakeConnector")
4202 if err
:= db
.Close(); err
!= nil {
4207 t
.Fatal("connector is not closed")
4211 type ctxOnlyDriver
struct {
4215 func (d
*ctxOnlyDriver
) Open(dsn
string) (driver
.Conn
, error
) {
4216 conn
, err
:= d
.fakeDriver
.Open(dsn
)
4220 return &ctxOnlyConn
{fc
: conn
.(*fakeConn
)}, nil
4224 _ driver
.Conn
= &ctxOnlyConn
{}
4225 _ driver
.QueryerContext
= &ctxOnlyConn
{}
4226 _ driver
.ExecerContext
= &ctxOnlyConn
{}
4229 type ctxOnlyConn
struct {
4236 func (c
*ctxOnlyConn
) Begin() (driver
.Tx
, error
) {
4240 func (c
*ctxOnlyConn
) Close() error
{
4244 // Prepare is still part of the Conn interface, so while it isn't used
4245 // must be defined for compatibility.
4246 func (c
*ctxOnlyConn
) Prepare(q
string) (driver
.Stmt
, error
) {
4250 func (c
*ctxOnlyConn
) PrepareContext(ctx context
.Context
, q
string) (driver
.Stmt
, error
) {
4251 return c
.fc
.PrepareContext(ctx
, q
)
4254 func (c
*ctxOnlyConn
) QueryContext(ctx context
.Context
, q
string, args
[]driver
.NamedValue
) (driver
.Rows
, error
) {
4255 c
.queryCtxCalled
= true
4256 return c
.fc
.QueryContext(ctx
, q
, args
)
4259 func (c
*ctxOnlyConn
) ExecContext(ctx context
.Context
, q
string, args
[]driver
.NamedValue
) (driver
.Result
, error
) {
4260 c
.execCtxCalled
= true
4261 return c
.fc
.ExecContext(ctx
, q
, args
)
4264 // TestQueryExecContextOnly ensures drivers only need to implement QueryContext
4265 // and ExecContext methods.
4266 func TestQueryExecContextOnly(t
*testing
.T
) {
4267 // Ensure connection does not implement non-context interfaces.
4268 var connType driver
.Conn
= &ctxOnlyConn
{}
4269 if _
, ok
:= connType
.(driver
.Execer
); ok
{
4270 t
.Fatalf("%T must not implement driver.Execer", connType
)
4272 if _
, ok
:= connType
.(driver
.Queryer
); ok
{
4273 t
.Fatalf("%T must not implement driver.Queryer", connType
)
4276 Register("ContextOnly", &ctxOnlyDriver
{})
4277 db
, err
:= Open("ContextOnly", "")
4283 ctx
, cancel
:= context
.WithCancel(context
.Background())
4286 conn
, err
:= db
.Conn(ctx
)
4288 t
.Fatal("db.Conn", err
)
4291 coc
:= conn
.dc
.ci
.(*ctxOnlyConn
)
4292 coc
.fc
.skipDirtySession
= true
4294 _
, err
= conn
.ExecContext(ctx
, "WIPE")
4296 t
.Fatal("exec wipe", err
)
4299 _
, err
= conn
.ExecContext(ctx
, "CREATE|keys|v1=string")
4301 t
.Fatal("exec create", err
)
4303 expectedValue
:= "value1"
4304 _
, err
= conn
.ExecContext(ctx
, "INSERT|keys|v1=?", expectedValue
)
4306 t
.Fatal("exec insert", err
)
4308 rows
, err
:= conn
.QueryContext(ctx
, "SELECT|keys|v1|")
4310 t
.Fatal("query select", err
)
4314 err
= rows
.Scan(&v1
)
4316 t
.Fatal("rows scan", err
)
4321 if v1
!= expectedValue
{
4322 t
.Fatalf("expected %q, got %q", expectedValue
, v1
)
4325 if !coc
.execCtxCalled
{
4326 t
.Error("ExecContext not called")
4328 if !coc
.queryCtxCalled
{
4329 t
.Error("QueryContext not called")
4333 type alwaysErrScanner
struct{}
4335 var errTestScanWrap
= errors
.New("errTestScanWrap")
4337 func (alwaysErrScanner
) Scan(any
) error
{
4338 return errTestScanWrap
4341 // Issue 38099: Ensure that Rows.Scan properly wraps underlying errors.
4342 func TestRowsScanProperlyWrapsErrors(t
*testing
.T
) {
4343 db
:= newTestDB(t
, "people")
4344 defer closeDB(t
, db
)
4346 rows
, err
:= db
.Query("SELECT|people|age|")
4348 t
.Fatalf("Query: %v", err
)
4351 var res alwaysErrScanner
4354 err
= rows
.Scan(&res
)
4356 t
.Fatal("expecting back an error")
4358 if !errors
.Is(err
, errTestScanWrap
) {
4359 t
.Fatalf("errors.Is mismatch\n%v\nWant: %v", err
, errTestScanWrap
)
4361 // Ensure that error substring matching still correctly works.
4362 if !strings
.Contains(err
.Error(), errTestScanWrap
.Error()) {
4363 t
.Fatalf("Error %v does not contain %v", err
, errTestScanWrap
)
4368 // badConn implements a bad driver.Conn, for TestBadDriver.
4369 // The Exec method panics.
4370 type badConn
struct{}
4372 func (bc badConn
) Prepare(query
string) (driver
.Stmt
, error
) {
4373 return nil, errors
.New("badConn Prepare")
4376 func (bc badConn
) Close() error
{
4380 func (bc badConn
) Begin() (driver
.Tx
, error
) {
4381 return nil, errors
.New("badConn Begin")
4384 func (bc badConn
) Exec(query
string, args
[]driver
.Value
) (driver
.Result
, error
) {
4385 panic("badConn.Exec")
4388 // badDriver is a driver.Driver that uses badConn.
4389 type badDriver
struct{}
4391 func (bd badDriver
) Open(name
string) (driver
.Conn
, error
) {
4392 return badConn
{}, nil
4396 func TestBadDriver(t
*testing
.T
) {
4397 Register("bad", badDriver
{})
4398 db
, err
:= Open("bad", "ignored")
4403 if r
:= recover(); r
== nil {
4404 t
.Error("expected panic")
4406 if want
:= "badConn.Exec"; r
.(string) != want
{
4407 t
.Errorf("panic was %v, expected %v", r
, want
)
4415 type pingDriver
struct {
4419 type pingConn
struct {
4424 var pingError
= errors
.New("Ping failed")
4426 func (pc pingConn
) Ping(ctx context
.Context
) error
{
4427 if pc
.driver
.fails
{
4433 var _ driver
.Pinger
= pingConn
{}
4435 func (pd
*pingDriver
) Open(name
string) (driver
.Conn
, error
) {
4436 return pingConn
{driver
: pd
}, nil
4439 func TestPing(t
*testing
.T
) {
4440 driver
:= &pingDriver
{}
4441 Register("ping", driver
)
4443 db
, err
:= Open("ping", "ignored")
4448 if err
:= db
.Ping(); err
!= nil {
4449 t
.Errorf("err was %#v, expected nil", err
)
4454 if err
:= db
.Ping(); err
!= pingError
{
4455 t
.Errorf("err was %#v, expected pingError", err
)
4460 func TestTypedString(t
*testing
.T
) {
4461 db
:= newTestDB(t
, "people")
4462 defer closeDB(t
, db
)
4467 err
:= db
.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned
)
4471 expected
:= Str("Alice")
4472 if scanned
!= expected
{
4473 t
.Errorf("expected %+v, got %+v", expected
, scanned
)
4477 func BenchmarkConcurrentDBExec(b
*testing
.B
) {
4479 ct
:= new(concurrentDBExecTest
)
4480 for i
:= 0; i
< b
.N
; i
++ {
4481 doConcurrentTest(b
, ct
)
4485 func BenchmarkConcurrentStmtQuery(b
*testing
.B
) {
4487 ct
:= new(concurrentStmtQueryTest
)
4488 for i
:= 0; i
< b
.N
; i
++ {
4489 doConcurrentTest(b
, ct
)
4493 func BenchmarkConcurrentStmtExec(b
*testing
.B
) {
4495 ct
:= new(concurrentStmtExecTest
)
4496 for i
:= 0; i
< b
.N
; i
++ {
4497 doConcurrentTest(b
, ct
)
4501 func BenchmarkConcurrentTxQuery(b
*testing
.B
) {
4503 ct
:= new(concurrentTxQueryTest
)
4504 for i
:= 0; i
< b
.N
; i
++ {
4505 doConcurrentTest(b
, ct
)
4509 func BenchmarkConcurrentTxExec(b
*testing
.B
) {
4511 ct
:= new(concurrentTxExecTest
)
4512 for i
:= 0; i
< b
.N
; i
++ {
4513 doConcurrentTest(b
, ct
)
4517 func BenchmarkConcurrentTxStmtQuery(b
*testing
.B
) {
4519 ct
:= new(concurrentTxStmtQueryTest
)
4520 for i
:= 0; i
< b
.N
; i
++ {
4521 doConcurrentTest(b
, ct
)
4525 func BenchmarkConcurrentTxStmtExec(b
*testing
.B
) {
4527 ct
:= new(concurrentTxStmtExecTest
)
4528 for i
:= 0; i
< b
.N
; i
++ {
4529 doConcurrentTest(b
, ct
)
4533 func BenchmarkConcurrentRandom(b
*testing
.B
) {
4535 ct
:= new(concurrentRandomTest
)
4536 for i
:= 0; i
< b
.N
; i
++ {
4537 doConcurrentTest(b
, ct
)
4541 func BenchmarkManyConcurrentQueries(b
*testing
.B
) {
4543 // To see lock contention in Go 1.4, 16~ cores and 128~ goroutines are required.
4544 const parallelism
= 16
4546 db
:= newTestDB(b
, "magicquery")
4547 defer closeDB(b
, db
)
4548 db
.SetMaxIdleConns(runtime
.GOMAXPROCS(0) * parallelism
)
4550 stmt
, err
:= db
.Prepare("SELECT|magicquery|op|op=?,millis=?")
4556 b
.SetParallelism(parallelism
)
4557 b
.RunParallel(func(pb
*testing
.PB
) {
4559 rows
, err
:= stmt
.Query("sleep", 1)