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