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