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