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