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, cancel := context.WithCancel(context.Background())
1379 defer cancel()
1380 conn, err := db.Conn(ctx)
1381 if err != nil {
1382 t.Fatal(err)
1383 }
1384 conn.dc.ci.(*fakeConn).skipDirtySession = true
1385 defer conn.Close()
1386
1387 var name string
1388 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", 3).Scan(&name)
1389 if err != nil {
1390 t.Fatal(err)
1391 }
1392 if name != "Chris" {
1393 t.Fatalf("unexpected result, got %q want Chris", name)
1394 }
1395
1396 err = conn.PingContext(ctx)
1397 if err != nil {
1398 t.Fatal(err)
1399 }
1400 }
1401
1402 func TestConnRaw(t *testing.T) {
1403 db := newTestDB(t, "people")
1404 defer closeDB(t, db)
1405
1406 ctx, cancel := context.WithCancel(context.Background())
1407 defer cancel()
1408 conn, err := db.Conn(ctx)
1409 if err != nil {
1410 t.Fatal(err)
1411 }
1412 conn.dc.ci.(*fakeConn).skipDirtySession = true
1413 defer conn.Close()
1414
1415 sawFunc := false
1416 err = conn.Raw(func(dc any) error {
1417 sawFunc = true
1418 if _, ok := dc.(*fakeConn); !ok {
1419 return fmt.Errorf("got %T want *fakeConn", dc)
1420 }
1421 return nil
1422 })
1423 if err != nil {
1424 t.Fatal(err)
1425 }
1426 if !sawFunc {
1427 t.Fatal("Raw func not called")
1428 }
1429
1430 func() {
1431 defer func() {
1432 x := recover()
1433 if x == nil {
1434 t.Fatal("expected panic")
1435 }
1436 conn.closemu.Lock()
1437 closed := conn.dc == nil
1438 conn.closemu.Unlock()
1439 if !closed {
1440 t.Fatal("expected connection to be closed after panic")
1441 }
1442 }()
1443 err = conn.Raw(func(dc any) error {
1444 panic("Conn.Raw panic should return an error")
1445 })
1446 t.Fatal("expected panic from Raw func")
1447 }()
1448 }
1449
1450 func TestCursorFake(t *testing.T) {
1451 db := newTestDB(t, "people")
1452 defer closeDB(t, db)
1453
1454 ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
1455 defer cancel()
1456
1457 exec(t, db, "CREATE|peoplecursor|list=table")
1458 exec(t, db, "INSERT|peoplecursor|list=people!name!age")
1459
1460 rows, err := db.QueryContext(ctx, `SELECT|peoplecursor|list|`)
1461 if err != nil {
1462 t.Fatal(err)
1463 }
1464 defer rows.Close()
1465
1466 if !rows.Next() {
1467 t.Fatal("no rows")
1468 }
1469 var cursor = &Rows{}
1470 err = rows.Scan(cursor)
1471 if err != nil {
1472 t.Fatal(err)
1473 }
1474 defer cursor.Close()
1475
1476 const expectedRows = 3
1477 var currentRow int64
1478
1479 var n int64
1480 var s string
1481 for cursor.Next() {
1482 currentRow++
1483 err = cursor.Scan(&s, &n)
1484 if err != nil {
1485 t.Fatal(err)
1486 }
1487 if n != currentRow {
1488 t.Errorf("expected number(Age)=%d, got %d", currentRow, n)
1489 }
1490 }
1491 if currentRow != expectedRows {
1492 t.Errorf("expected %d rows, got %d rows", expectedRows, currentRow)
1493 }
1494 }
1495
1496 func TestInvalidNilValues(t *testing.T) {
1497 var date1 time.Time
1498 var date2 int
1499
1500 tests := []struct {
1501 name string
1502 input any
1503 expectedError string
1504 }{
1505 {
1506 name: "time.Time",
1507 input: &date1,
1508 expectedError: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type <nil> into type *time.Time`,
1509 },
1510 {
1511 name: "int",
1512 input: &date2,
1513 expectedError: `sql: Scan error on column index 0, name "bdate": converting NULL to int is unsupported`,
1514 },
1515 }
1516
1517 for _, tt := range tests {
1518 t.Run(tt.name, func(t *testing.T) {
1519 db := newTestDB(t, "people")
1520 defer closeDB(t, db)
1521
1522 ctx, cancel := context.WithCancel(context.Background())
1523 defer cancel()
1524 conn, err := db.Conn(ctx)
1525 if err != nil {
1526 t.Fatal(err)
1527 }
1528 conn.dc.ci.(*fakeConn).skipDirtySession = true
1529 defer conn.Close()
1530
1531 err = conn.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 1).Scan(tt.input)
1532 if err == nil {
1533 t.Fatal("expected error when querying nil column, but succeeded")
1534 }
1535 if err.Error() != tt.expectedError {
1536 t.Fatalf("Expected error: %s\nReceived: %s", tt.expectedError, err.Error())
1537 }
1538
1539 err = conn.PingContext(ctx)
1540 if err != nil {
1541 t.Fatal(err)
1542 }
1543 })
1544 }
1545 }
1546
1547 func TestConnTx(t *testing.T) {
1548 db := newTestDB(t, "people")
1549 defer closeDB(t, db)
1550
1551 ctx, cancel := context.WithCancel(context.Background())
1552 defer cancel()
1553 conn, err := db.Conn(ctx)
1554 if err != nil {
1555 t.Fatal(err)
1556 }
1557 conn.dc.ci.(*fakeConn).skipDirtySession = true
1558 defer conn.Close()
1559
1560 tx, err := conn.BeginTx(ctx, nil)
1561 if err != nil {
1562 t.Fatal(err)
1563 }
1564 insertName, insertAge := "Nancy", 33
1565 _, err = tx.ExecContext(ctx, "INSERT|people|name=?,age=?,photo=APHOTO", insertName, insertAge)
1566 if err != nil {
1567 t.Fatal(err)
1568 }
1569 err = tx.Commit()
1570 if err != nil {
1571 t.Fatal(err)
1572 }
1573
1574 var selectName string
1575 err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", insertAge).Scan(&selectName)
1576 if err != nil {
1577 t.Fatal(err)
1578 }
1579 if selectName != insertName {
1580 t.Fatalf("got %q want %q", selectName, insertName)
1581 }
1582 }
1583
1584
1585
1586
1587 func TestConnIsValid(t *testing.T) {
1588 db := newTestDB(t, "people")
1589 defer closeDB(t, db)
1590
1591 db.SetMaxOpenConns(1)
1592
1593 ctx := context.Background()
1594
1595 c, err := db.Conn(ctx)
1596 if err != nil {
1597 t.Fatal(err)
1598 }
1599
1600 err = c.Raw(func(raw any) error {
1601 dc := raw.(*fakeConn)
1602 dc.stickyBad = true
1603 return nil
1604 })
1605 if err != nil {
1606 t.Fatal(err)
1607 }
1608 c.Close()
1609
1610 if len(db.freeConn) > 0 && db.freeConn[0].ci.(*fakeConn).stickyBad {
1611 t.Fatal("bad connection returned to pool; expected bad connection to be discarded")
1612 }
1613 }
1614
1615
1616
1617 func TestIssue2542Deadlock(t *testing.T) {
1618 db := newTestDB(t, "people")
1619 closeDB(t, db)
1620 for i := 0; i < 2; i++ {
1621 _, err := db.Query("SELECT|people|age,name|")
1622 if err == nil {
1623 t.Fatalf("expected error")
1624 }
1625 }
1626 }
1627
1628
1629 func TestCloseStmtBeforeRows(t *testing.T) {
1630 db := newTestDB(t, "people")
1631 defer closeDB(t, db)
1632
1633 s, err := db.Prepare("SELECT|people|name|")
1634 if err != nil {
1635 t.Fatal(err)
1636 }
1637
1638 r, err := s.Query()
1639 if err != nil {
1640 s.Close()
1641 t.Fatal(err)
1642 }
1643
1644 err = s.Close()
1645 if err != nil {
1646 t.Fatal(err)
1647 }
1648
1649 r.Close()
1650 }
1651
1652
1653
1654 func TestNullByteSlice(t *testing.T) {
1655 db := newTestDB(t, "")
1656 defer closeDB(t, db)
1657 exec(t, db, "CREATE|t|id=int32,name=nullstring")
1658 exec(t, db, "INSERT|t|id=10,name=?", nil)
1659
1660 var name []byte
1661
1662 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
1663 if err != nil {
1664 t.Fatal(err)
1665 }
1666 if name != nil {
1667 t.Fatalf("name []byte should be nil for null column value, got: %#v", name)
1668 }
1669
1670 exec(t, db, "INSERT|t|id=11,name=?", "bob")
1671 err = db.QueryRow("SELECT|t|name|id=?", 11).Scan(&name)
1672 if err != nil {
1673 t.Fatal(err)
1674 }
1675 if string(name) != "bob" {
1676 t.Fatalf("name []byte should be bob, got: %q", string(name))
1677 }
1678 }
1679
1680 func TestPointerParamsAndScans(t *testing.T) {
1681 db := newTestDB(t, "")
1682 defer closeDB(t, db)
1683 exec(t, db, "CREATE|t|id=int32,name=nullstring")
1684
1685 bob := "bob"
1686 var name *string
1687
1688 name = &bob
1689 exec(t, db, "INSERT|t|id=10,name=?", name)
1690 name = nil
1691 exec(t, db, "INSERT|t|id=20,name=?", name)
1692
1693 err := db.QueryRow("SELECT|t|name|id=?", 10).Scan(&name)
1694 if err != nil {
1695 t.Fatalf("querying id 10: %v", err)
1696 }
1697 if name == nil {
1698 t.Errorf("id 10's name = nil; want bob")
1699 } else if *name != "bob" {
1700 t.Errorf("id 10's name = %q; want bob", *name)
1701 }
1702
1703 err = db.QueryRow("SELECT|t|name|id=?", 20).Scan(&name)
1704 if err != nil {
1705 t.Fatalf("querying id 20: %v", err)
1706 }
1707 if name != nil {
1708 t.Errorf("id 20 = %q; want nil", *name)
1709 }
1710 }
1711
1712 func TestQueryRowClosingStmt(t *testing.T) {
1713 db := newTestDB(t, "people")
1714 defer closeDB(t, db)
1715 var name string
1716 var age int
1717 err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age, &name)
1718 if err != nil {
1719 t.Fatal(err)
1720 }
1721 if len(db.freeConn) != 1 {
1722 t.Fatalf("expected 1 free conn")
1723 }
1724 fakeConn := db.freeConn[0].ci.(*fakeConn)
1725 if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
1726 t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
1727 }
1728 }
1729
1730 var atomicRowsCloseHook atomic.Value
1731
1732 func init() {
1733 rowsCloseHook = func() func(*Rows, *error) {
1734 fn, _ := atomicRowsCloseHook.Load().(func(*Rows, *error))
1735 return fn
1736 }
1737 }
1738
1739 func setRowsCloseHook(fn func(*Rows, *error)) {
1740 if fn == nil {
1741
1742
1743 fn = func(*Rows, *error) {}
1744 }
1745 atomicRowsCloseHook.Store(fn)
1746 }
1747
1748
1749 func TestIssue6651(t *testing.T) {
1750 db := newTestDB(t, "people")
1751 defer closeDB(t, db)
1752
1753 var v string
1754
1755 want := "error in rows.Next"
1756 rowsCursorNextHook = func(dest []driver.Value) error {
1757 return errors.New(want)
1758 }
1759 defer func() { rowsCursorNextHook = nil }()
1760
1761 err := db.QueryRow("SELECT|people|name|").Scan(&v)
1762 if err == nil || err.Error() != want {
1763 t.Errorf("error = %q; want %q", err, want)
1764 }
1765 rowsCursorNextHook = nil
1766
1767 want = "error in rows.Close"
1768 setRowsCloseHook(func(rows *Rows, err *error) {
1769 *err = errors.New(want)
1770 })
1771 defer setRowsCloseHook(nil)
1772 err = db.QueryRow("SELECT|people|name|").Scan(&v)
1773 if err == nil || err.Error() != want {
1774 t.Errorf("error = %q; want %q", err, want)
1775 }
1776 }
1777
1778 type nullTestRow struct {
1779 nullParam any
1780 notNullParam any
1781 scanNullVal any
1782 }
1783
1784 type nullTestSpec struct {
1785 nullType string
1786 notNullType string
1787 rows [6]nullTestRow
1788 }
1789
1790 func TestNullStringParam(t *testing.T) {
1791 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
1792 {NullString{"aqua", true}, "", NullString{"aqua", true}},
1793 {NullString{"brown", false}, "", NullString{"", false}},
1794 {"chartreuse", "", NullString{"chartreuse", true}},
1795 {NullString{"darkred", true}, "", NullString{"darkred", true}},
1796 {NullString{"eel", false}, "", NullString{"", false}},
1797 {"foo", NullString{"black", false}, nil},
1798 }}
1799 nullTestRun(t, spec)
1800 }
1801
1802 func TestGenericNullStringParam(t *testing.T) {
1803 spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
1804 {Null[string]{"aqua", true}, "", Null[string]{"aqua", true}},
1805 {Null[string]{"brown", false}, "", Null[string]{"", false}},
1806 {"chartreuse", "", Null[string]{"chartreuse", true}},
1807 {Null[string]{"darkred", true}, "", Null[string]{"darkred", true}},
1808 {Null[string]{"eel", false}, "", Null[string]{"", false}},
1809 {"foo", Null[string]{"black", false}, nil},
1810 }}
1811 nullTestRun(t, spec)
1812 }
1813
1814 func TestNullInt64Param(t *testing.T) {
1815 spec := nullTestSpec{"nullint64", "int64", [6]nullTestRow{
1816 {NullInt64{31, true}, 1, NullInt64{31, true}},
1817 {NullInt64{-22, false}, 1, NullInt64{0, false}},
1818 {22, 1, NullInt64{22, true}},
1819 {NullInt64{33, true}, 1, NullInt64{33, true}},
1820 {NullInt64{222, false}, 1, NullInt64{0, false}},
1821 {0, NullInt64{31, false}, nil},
1822 }}
1823 nullTestRun(t, spec)
1824 }
1825
1826 func TestNullInt32Param(t *testing.T) {
1827 spec := nullTestSpec{"nullint32", "int32", [6]nullTestRow{
1828 {NullInt32{31, true}, 1, NullInt32{31, true}},
1829 {NullInt32{-22, false}, 1, NullInt32{0, false}},
1830 {22, 1, NullInt32{22, true}},
1831 {NullInt32{33, true}, 1, NullInt32{33, true}},
1832 {NullInt32{222, false}, 1, NullInt32{0, false}},
1833 {0, NullInt32{31, false}, nil},
1834 }}
1835 nullTestRun(t, spec)
1836 }
1837
1838 func TestNullInt16Param(t *testing.T) {
1839 spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{
1840 {NullInt16{31, true}, 1, NullInt16{31, true}},
1841 {NullInt16{-22, false}, 1, NullInt16{0, false}},
1842 {22, 1, NullInt16{22, true}},
1843 {NullInt16{33, true}, 1, NullInt16{33, true}},
1844 {NullInt16{222, false}, 1, NullInt16{0, false}},
1845 {0, NullInt16{31, false}, nil},
1846 }}
1847 nullTestRun(t, spec)
1848 }
1849
1850 func TestNullByteParam(t *testing.T) {
1851 spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{
1852 {NullByte{31, true}, 1, NullByte{31, true}},
1853 {NullByte{0, false}, 1, NullByte{0, false}},
1854 {22, 1, NullByte{22, true}},
1855 {NullByte{33, true}, 1, NullByte{33, true}},
1856 {NullByte{222, false}, 1, NullByte{0, false}},
1857 {0, NullByte{31, false}, nil},
1858 }}
1859 nullTestRun(t, spec)
1860 }
1861
1862 func TestNullFloat64Param(t *testing.T) {
1863 spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
1864 {NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
1865 {NullFloat64{13.1, false}, 1, NullFloat64{0, false}},
1866 {-22.9, 1, NullFloat64{-22.9, true}},
1867 {NullFloat64{33.81, true}, 1, NullFloat64{33.81, true}},
1868 {NullFloat64{222, false}, 1, NullFloat64{0, false}},
1869 {10, NullFloat64{31.2, false}, nil},
1870 }}
1871 nullTestRun(t, spec)
1872 }
1873
1874 func TestNullBoolParam(t *testing.T) {
1875 spec := nullTestSpec{"nullbool", "bool", [6]nullTestRow{
1876 {NullBool{false, true}, true, NullBool{false, true}},
1877 {NullBool{true, false}, false, NullBool{false, false}},
1878 {true, true, NullBool{true, true}},
1879 {NullBool{true, true}, false, NullBool{true, true}},
1880 {NullBool{true, false}, true, NullBool{false, false}},
1881 {true, NullBool{true, false}, nil},
1882 }}
1883 nullTestRun(t, spec)
1884 }
1885
1886 func TestNullTimeParam(t *testing.T) {
1887 t0 := time.Time{}
1888 t1 := time.Date(2000, 1, 1, 8, 9, 10, 11, time.UTC)
1889 t2 := time.Date(2010, 1, 1, 8, 9, 10, 11, time.UTC)
1890 spec := nullTestSpec{"nulldatetime", "datetime", [6]nullTestRow{
1891 {NullTime{t1, true}, t2, NullTime{t1, true}},
1892 {NullTime{t1, false}, t2, NullTime{t0, false}},
1893 {t1, t2, NullTime{t1, true}},
1894 {NullTime{t1, true}, t2, NullTime{t1, true}},
1895 {NullTime{t1, false}, t2, NullTime{t0, false}},
1896 {t2, NullTime{t1, false}, nil},
1897 }}
1898 nullTestRun(t, spec)
1899 }
1900
1901 func nullTestRun(t *testing.T, spec nullTestSpec) {
1902 db := newTestDB(t, "")
1903 defer closeDB(t, db)
1904 exec(t, db, fmt.Sprintf("CREATE|t|id=int32,name=string,nullf=%s,notnullf=%s", spec.nullType, spec.notNullType))
1905
1906
1907 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 1, "alice", spec.rows[0].nullParam, spec.rows[0].notNullParam)
1908 exec(t, db, "INSERT|t|id=?,name=?,nullf=?,notnullf=?", 2, "bob", spec.rows[1].nullParam, spec.rows[1].notNullParam)
1909
1910
1911 stmt, err := db.Prepare("INSERT|t|id=?,name=?,nullf=?,notnullf=?")
1912 if err != nil {
1913 t.Fatalf("prepare: %v", err)
1914 }
1915 defer stmt.Close()
1916 if _, err := stmt.Exec(3, "chris", spec.rows[2].nullParam, spec.rows[2].notNullParam); err != nil {
1917 t.Errorf("exec insert chris: %v", err)
1918 }
1919 if _, err := stmt.Exec(4, "dave", spec.rows[3].nullParam, spec.rows[3].notNullParam); err != nil {
1920 t.Errorf("exec insert dave: %v", err)
1921 }
1922 if _, err := stmt.Exec(5, "eleanor", spec.rows[4].nullParam, spec.rows[4].notNullParam); err != nil {
1923 t.Errorf("exec insert eleanor: %v", err)
1924 }
1925
1926
1927 row5 := spec.rows[5]
1928 if _, err := stmt.Exec(6, "bob", row5.nullParam, row5.notNullParam); err == nil {
1929 t.Errorf("expected error inserting nil val with prepared statement Exec: NULL=%#v, NOT-NULL=%#v", row5.nullParam, row5.notNullParam)
1930 }
1931
1932 _, err = db.Exec("INSERT|t|id=?,name=?,nullf=?", 999, nil, nil)
1933 if err == nil {
1934
1935
1936
1937
1938
1939
1940 }
1941
1942 paramtype := reflect.TypeOf(spec.rows[0].nullParam)
1943 bindVal := reflect.New(paramtype).Interface()
1944
1945 for i := 0; i < 5; i++ {
1946 id := i + 1
1947 if err := db.QueryRow("SELECT|t|nullf|id=?", id).Scan(bindVal); err != nil {
1948 t.Errorf("id=%d Scan: %v", id, err)
1949 }
1950 bindValDeref := reflect.ValueOf(bindVal).Elem().Interface()
1951 if !reflect.DeepEqual(bindValDeref, spec.rows[i].scanNullVal) {
1952 t.Errorf("id=%d got %#v, want %#v", id, bindValDeref, spec.rows[i].scanNullVal)
1953 }
1954 }
1955 }
1956
1957
1958 func TestQueryRowNilScanDest(t *testing.T) {
1959 db := newTestDB(t, "people")
1960 defer closeDB(t, db)
1961 var name *string
1962 err := db.QueryRow("SELECT|people|name|").Scan(name)
1963 want := `sql: Scan error on column index 0, name "name": destination pointer is nil`
1964 if err == nil || err.Error() != want {
1965 t.Errorf("error = %q; want %q", err.Error(), want)
1966 }
1967 }
1968
1969 func TestIssue4902(t *testing.T) {
1970 db := newTestDB(t, "people")
1971 defer closeDB(t, db)
1972
1973 driver := db.Driver().(*fakeDriver)
1974 opens0 := driver.openCount
1975
1976 var stmt *Stmt
1977 var err error
1978 for i := 0; i < 10; i++ {
1979 stmt, err = db.Prepare("SELECT|people|name|")
1980 if err != nil {
1981 t.Fatal(err)
1982 }
1983 err = stmt.Close()
1984 if err != nil {
1985 t.Fatal(err)
1986 }
1987 }
1988
1989 opens := driver.openCount - opens0
1990 if opens > 1 {
1991 t.Errorf("opens = %d; want <= 1", opens)
1992 t.Logf("db = %#v", db)
1993 t.Logf("driver = %#v", driver)
1994 t.Logf("stmt = %#v", stmt)
1995 }
1996 }
1997
1998
1999
2000 func TestSimultaneousQueries(t *testing.T) {
2001 db := newTestDB(t, "people")
2002 defer closeDB(t, db)
2003
2004 tx, err := db.Begin()
2005 if err != nil {
2006 t.Fatal(err)
2007 }
2008 defer tx.Rollback()
2009
2010 r1, err := tx.Query("SELECT|people|name|")
2011 if err != nil {
2012 t.Fatal(err)
2013 }
2014 defer r1.Close()
2015
2016 r2, err := tx.Query("SELECT|people|name|")
2017 if err != nil {
2018 t.Fatal(err)
2019 }
2020 defer r2.Close()
2021 }
2022
2023 func TestMaxIdleConns(t *testing.T) {
2024 db := newTestDB(t, "people")
2025 defer closeDB(t, db)
2026
2027 tx, err := db.Begin()
2028 if err != nil {
2029 t.Fatal(err)
2030 }
2031 tx.Commit()
2032 if got := len(db.freeConn); got != 1 {
2033 t.Errorf("freeConns = %d; want 1", got)
2034 }
2035
2036 db.SetMaxIdleConns(0)
2037
2038 if got := len(db.freeConn); got != 0 {
2039 t.Errorf("freeConns after set to zero = %d; want 0", got)
2040 }
2041
2042 tx, err = db.Begin()
2043 if err != nil {
2044 t.Fatal(err)
2045 }
2046 tx.Commit()
2047 if got := len(db.freeConn); got != 0 {
2048 t.Errorf("freeConns = %d; want 0", got)
2049 }
2050 }
2051
2052 func TestMaxOpenConns(t *testing.T) {
2053 if testing.Short() {
2054 t.Skip("skipping in short mode")
2055 }
2056 defer setHookpostCloseConn(nil)
2057 setHookpostCloseConn(func(_ *fakeConn, err error) {
2058 if err != nil {
2059 t.Errorf("Error closing fakeConn: %v", err)
2060 }
2061 })
2062
2063 db := newTestDB(t, "magicquery")
2064 defer closeDB(t, db)
2065
2066 driver := db.Driver().(*fakeDriver)
2067
2068
2069
2070 db.clearAllConns(t)
2071
2072 driver.mu.Lock()
2073 opens0 := driver.openCount
2074 closes0 := driver.closeCount
2075 driver.mu.Unlock()
2076
2077 db.SetMaxIdleConns(10)
2078 db.SetMaxOpenConns(10)
2079
2080 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
2081 if err != nil {
2082 t.Fatal(err)
2083 }
2084
2085
2086 const (
2087 nquery = 50
2088 sleepMillis = 25
2089 nbatch = 2
2090 )
2091 var wg sync.WaitGroup
2092 for batch := 0; batch < nbatch; batch++ {
2093 for i := 0; i < nquery; i++ {
2094 wg.Add(1)
2095 go func() {
2096 defer wg.Done()
2097 var op string
2098 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
2099 t.Error(err)
2100 }
2101 }()
2102 }
2103
2104 wg.Wait()
2105 }
2106
2107 if g, w := db.numFreeConns(), 10; g != w {
2108 t.Errorf("free conns = %d; want %d", g, w)
2109 }
2110
2111 if n := db.numDepsPoll(t, 20); n > 20 {
2112 t.Errorf("number of dependencies = %d; expected <= 20", n)
2113 db.dumpDeps(t)
2114 }
2115
2116 driver.mu.Lock()
2117 opens := driver.openCount - opens0
2118 closes := driver.closeCount - closes0
2119 driver.mu.Unlock()
2120
2121 if opens > 10 {
2122 t.Logf("open calls = %d", opens)
2123 t.Logf("close calls = %d", closes)
2124 t.Errorf("db connections opened = %d; want <= 10", opens)
2125 db.dumpDeps(t)
2126 }
2127
2128 if err := stmt.Close(); err != nil {
2129 t.Fatal(err)
2130 }
2131
2132 if g, w := db.numFreeConns(), 10; g != w {
2133 t.Errorf("free conns = %d; want %d", g, w)
2134 }
2135
2136 if n := db.numDepsPoll(t, 10); n > 10 {
2137 t.Errorf("number of dependencies = %d; expected <= 10", n)
2138 db.dumpDeps(t)
2139 }
2140
2141 db.SetMaxOpenConns(5)
2142
2143 if g, w := db.numFreeConns(), 5; g != w {
2144 t.Errorf("free conns = %d; want %d", g, w)
2145 }
2146
2147 if n := db.numDepsPoll(t, 5); n > 5 {
2148 t.Errorf("number of dependencies = %d; expected 0", n)
2149 db.dumpDeps(t)
2150 }
2151
2152 db.SetMaxOpenConns(0)
2153
2154 if g, w := db.numFreeConns(), 5; g != w {
2155 t.Errorf("free conns = %d; want %d", g, w)
2156 }
2157
2158 if n := db.numDepsPoll(t, 5); n > 5 {
2159 t.Errorf("number of dependencies = %d; expected 0", n)
2160 db.dumpDeps(t)
2161 }
2162
2163 db.clearAllConns(t)
2164 }
2165
2166
2167
2168 func TestMaxOpenConnsOnBusy(t *testing.T) {
2169 defer setHookpostCloseConn(nil)
2170 setHookpostCloseConn(func(_ *fakeConn, err error) {
2171 if err != nil {
2172 t.Errorf("Error closing fakeConn: %v", err)
2173 }
2174 })
2175
2176 db := newTestDB(t, "magicquery")
2177 defer closeDB(t, db)
2178
2179 db.SetMaxOpenConns(3)
2180
2181 ctx := context.Background()
2182
2183 conn0, err := db.conn(ctx, cachedOrNewConn)
2184 if err != nil {
2185 t.Fatalf("db open conn fail: %v", err)
2186 }
2187
2188 conn1, err := db.conn(ctx, cachedOrNewConn)
2189 if err != nil {
2190 t.Fatalf("db open conn fail: %v", err)
2191 }
2192
2193 conn2, err := db.conn(ctx, cachedOrNewConn)
2194 if err != nil {
2195 t.Fatalf("db open conn fail: %v", err)
2196 }
2197
2198 if g, w := db.numOpen, 3; g != w {
2199 t.Errorf("free conns = %d; want %d", g, w)
2200 }
2201
2202 db.SetMaxOpenConns(2)
2203 if g, w := db.numOpen, 3; g != w {
2204 t.Errorf("free conns = %d; want %d", g, w)
2205 }
2206
2207 conn0.releaseConn(nil)
2208 conn1.releaseConn(nil)
2209 if g, w := db.numOpen, 2; g != w {
2210 t.Errorf("free conns = %d; want %d", g, w)
2211 }
2212
2213 conn2.releaseConn(nil)
2214 if g, w := db.numOpen, 2; g != w {
2215 t.Errorf("free conns = %d; want %d", g, w)
2216 }
2217 }
2218
2219
2220
2221 func TestPendingConnsAfterErr(t *testing.T) {
2222 const (
2223 maxOpen = 2
2224 tryOpen = maxOpen*2 + 2
2225 )
2226
2227
2228 db, err := Open("test", fakeDBName)
2229 if err != nil {
2230 t.Fatalf("Open: %v", err)
2231 }
2232 defer closeDB(t, db)
2233 defer func() {
2234 for k, v := range db.lastPut {
2235 t.Logf("%p: %v", k, v)
2236 }
2237 }()
2238
2239 db.SetMaxOpenConns(maxOpen)
2240 db.SetMaxIdleConns(0)
2241
2242 errOffline := errors.New("db offline")
2243
2244 defer func() { setHookOpenErr(nil) }()
2245
2246 errs := make(chan error, tryOpen)
2247
2248 var opening sync.WaitGroup
2249 opening.Add(tryOpen)
2250
2251 setHookOpenErr(func() error {
2252
2253 opening.Wait()
2254 return errOffline
2255 })
2256
2257 for i := 0; i < tryOpen; i++ {
2258 go func() {
2259 opening.Done()
2260 _, err := db.Exec("will never run")
2261 errs <- err
2262 }()
2263 }
2264
2265 opening.Wait()
2266
2267 const timeout = 5 * time.Second
2268 to := time.NewTimer(timeout)
2269 defer to.Stop()
2270
2271
2272 for i := 0; i < tryOpen; i++ {
2273 select {
2274 case err := <-errs:
2275 if got, want := err, errOffline; got != want {
2276 t.Errorf("unexpected err: got %v, want %v", got, want)
2277 }
2278 case <-to.C:
2279 t.Fatalf("orphaned connection request(s), still waiting after %v", timeout)
2280 }
2281 }
2282
2283
2284 tick := time.NewTicker(3 * time.Millisecond)
2285 defer tick.Stop()
2286 for {
2287 select {
2288 case <-tick.C:
2289 db.mu.Lock()
2290 if db.numOpen == 0 {
2291 db.mu.Unlock()
2292 return
2293 }
2294 db.mu.Unlock()
2295 case <-to.C:
2296
2297 return
2298 }
2299 }
2300 }
2301
2302 func TestSingleOpenConn(t *testing.T) {
2303 db := newTestDB(t, "people")
2304 defer closeDB(t, db)
2305
2306 db.SetMaxOpenConns(1)
2307
2308 rows, err := db.Query("SELECT|people|name|")
2309 if err != nil {
2310 t.Fatal(err)
2311 }
2312 if err = rows.Close(); err != nil {
2313 t.Fatal(err)
2314 }
2315
2316 rows, err = db.Query("SELECT|people|name|")
2317 if err != nil {
2318 t.Fatal(err)
2319 }
2320 if err = rows.Close(); err != nil {
2321 t.Fatal(err)
2322 }
2323 }
2324
2325 func TestStats(t *testing.T) {
2326 db := newTestDB(t, "people")
2327 stats := db.Stats()
2328 if got := stats.OpenConnections; got != 1 {
2329 t.Errorf("stats.OpenConnections = %d; want 1", got)
2330 }
2331
2332 tx, err := db.Begin()
2333 if err != nil {
2334 t.Fatal(err)
2335 }
2336 tx.Commit()
2337
2338 closeDB(t, db)
2339 stats = db.Stats()
2340 if got := stats.OpenConnections; got != 0 {
2341 t.Errorf("stats.OpenConnections = %d; want 0", got)
2342 }
2343 }
2344
2345 func TestConnMaxLifetime(t *testing.T) {
2346 t0 := time.Unix(1000000, 0)
2347 offset := time.Duration(0)
2348
2349 nowFunc = func() time.Time { return t0.Add(offset) }
2350 defer func() { nowFunc = time.Now }()
2351
2352 db := newTestDB(t, "magicquery")
2353 defer closeDB(t, db)
2354
2355 driver := db.Driver().(*fakeDriver)
2356
2357
2358
2359 db.clearAllConns(t)
2360
2361 driver.mu.Lock()
2362 opens0 := driver.openCount
2363 closes0 := driver.closeCount
2364 driver.mu.Unlock()
2365
2366 db.SetMaxIdleConns(10)
2367 db.SetMaxOpenConns(10)
2368
2369 tx, err := db.Begin()
2370 if err != nil {
2371 t.Fatal(err)
2372 }
2373
2374 offset = time.Second
2375 tx2, err := db.Begin()
2376 if err != nil {
2377 t.Fatal(err)
2378 }
2379
2380 tx.Commit()
2381 tx2.Commit()
2382
2383 driver.mu.Lock()
2384 opens := driver.openCount - opens0
2385 closes := driver.closeCount - closes0
2386 driver.mu.Unlock()
2387
2388 if opens != 2 {
2389 t.Errorf("opens = %d; want 2", opens)
2390 }
2391 if closes != 0 {
2392 t.Errorf("closes = %d; want 0", closes)
2393 }
2394 if g, w := db.numFreeConns(), 2; g != w {
2395 t.Errorf("free conns = %d; want %d", g, w)
2396 }
2397
2398
2399 offset = 11 * time.Second
2400 db.SetConnMaxLifetime(10 * time.Second)
2401
2402 tx, err = db.Begin()
2403 if err != nil {
2404 t.Fatal(err)
2405 }
2406 tx2, err = db.Begin()
2407 if err != nil {
2408 t.Fatal(err)
2409 }
2410 tx.Commit()
2411 tx2.Commit()
2412
2413
2414 waitCondition(t, func() bool {
2415 driver.mu.Lock()
2416 opens = driver.openCount - opens0
2417 closes = driver.closeCount - closes0
2418 driver.mu.Unlock()
2419
2420 return closes == 1
2421 })
2422
2423 if opens != 3 {
2424 t.Errorf("opens = %d; want 3", opens)
2425 }
2426 if closes != 1 {
2427 t.Errorf("closes = %d; want 1", closes)
2428 }
2429
2430 if s := db.Stats(); s.MaxLifetimeClosed != 1 {
2431 t.Errorf("MaxLifetimeClosed = %d; want 1 %#v", s.MaxLifetimeClosed, s)
2432 }
2433 }
2434
2435
2436 func TestStmtCloseDeps(t *testing.T) {
2437 if testing.Short() {
2438 t.Skip("skipping in short mode")
2439 }
2440 defer setHookpostCloseConn(nil)
2441 setHookpostCloseConn(func(_ *fakeConn, err error) {
2442 if err != nil {
2443 t.Errorf("Error closing fakeConn: %v", err)
2444 }
2445 })
2446
2447 db := newTestDB(t, "magicquery")
2448 defer closeDB(t, db)
2449
2450 driver := db.Driver().(*fakeDriver)
2451
2452 driver.mu.Lock()
2453 opens0 := driver.openCount
2454 closes0 := driver.closeCount
2455 driver.mu.Unlock()
2456 openDelta0 := opens0 - closes0
2457
2458 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
2459 if err != nil {
2460 t.Fatal(err)
2461 }
2462
2463
2464 const (
2465 nquery = 50
2466 sleepMillis = 25
2467 nbatch = 2
2468 )
2469 var wg sync.WaitGroup
2470 for batch := 0; batch < nbatch; batch++ {
2471 for i := 0; i < nquery; i++ {
2472 wg.Add(1)
2473 go func() {
2474 defer wg.Done()
2475 var op string
2476 if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
2477 t.Error(err)
2478 }
2479 }()
2480 }
2481
2482 wg.Wait()
2483 }
2484
2485 if g, w := db.numFreeConns(), 2; g != w {
2486 t.Errorf("free conns = %d; want %d", g, w)
2487 }
2488
2489 if n := db.numDepsPoll(t, 4); n > 4 {
2490 t.Errorf("number of dependencies = %d; expected <= 4", n)
2491 db.dumpDeps(t)
2492 }
2493
2494 driver.mu.Lock()
2495 opens := driver.openCount - opens0
2496 closes := driver.closeCount - closes0
2497 openDelta := (driver.openCount - driver.closeCount) - openDelta0
2498 driver.mu.Unlock()
2499
2500 if openDelta > 2 {
2501 t.Logf("open calls = %d", opens)
2502 t.Logf("close calls = %d", closes)
2503 t.Logf("open delta = %d", openDelta)
2504 t.Errorf("db connections opened = %d; want <= 2", openDelta)
2505 db.dumpDeps(t)
2506 }
2507
2508 if !waitCondition(t, func() bool {
2509 return len(stmt.css) <= nquery
2510 }) {
2511 t.Errorf("len(stmt.css) = %d; want <= %d", len(stmt.css), nquery)
2512 }
2513
2514 if err := stmt.Close(); err != nil {
2515 t.Fatal(err)
2516 }
2517
2518 if g, w := db.numFreeConns(), 2; g != w {
2519 t.Errorf("free conns = %d; want %d", g, w)
2520 }
2521
2522 if n := db.numDepsPoll(t, 2); n > 2 {
2523 t.Errorf("number of dependencies = %d; expected <= 2", n)
2524 db.dumpDeps(t)
2525 }
2526
2527 db.clearAllConns(t)
2528 }
2529
2530
2531 func TestCloseConnBeforeStmts(t *testing.T) {
2532 db := newTestDB(t, "people")
2533 defer closeDB(t, db)
2534
2535 defer setHookpostCloseConn(nil)
2536 setHookpostCloseConn(func(_ *fakeConn, err error) {
2537 if err != nil {
2538 t.Errorf("Error closing fakeConn: %v; from %s", err, stack())
2539 db.dumpDeps(t)
2540 t.Errorf("DB = %#v", db)
2541 }
2542 })
2543
2544 stmt, err := db.Prepare("SELECT|people|name|")
2545 if err != nil {
2546 t.Fatal(err)
2547 }
2548
2549 if len(db.freeConn) != 1 {
2550 t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn))
2551 }
2552 dc := db.freeConn[0]
2553 if dc.closed {
2554 t.Errorf("conn shouldn't be closed")
2555 }
2556
2557 if n := len(dc.openStmt); n != 1 {
2558 t.Errorf("driverConn num openStmt = %d; want 1", n)
2559 }
2560 err = db.Close()
2561 if err != nil {
2562 t.Errorf("db Close = %v", err)
2563 }
2564 if !dc.closed {
2565 t.Errorf("after db.Close, driverConn should be closed")
2566 }
2567 if n := len(dc.openStmt); n != 0 {
2568 t.Errorf("driverConn num openStmt = %d; want 0", n)
2569 }
2570
2571 err = stmt.Close()
2572 if err != nil {
2573 t.Errorf("Stmt close = %v", err)
2574 }
2575
2576 if !dc.closed {
2577 t.Errorf("conn should be closed")
2578 }
2579 if dc.ci != nil {
2580 t.Errorf("after Stmt Close, driverConn's Conn interface should be nil")
2581 }
2582 }
2583
2584
2585
2586 func TestRowsCloseOrder(t *testing.T) {
2587 db := newTestDB(t, "people")
2588 defer closeDB(t, db)
2589
2590 db.SetMaxIdleConns(0)
2591 setStrictFakeConnClose(t)
2592 defer setStrictFakeConnClose(nil)
2593
2594 rows, err := db.Query("SELECT|people|age,name|")
2595 if err != nil {
2596 t.Fatal(err)
2597 }
2598 err = rows.Close()
2599 if err != nil {
2600 t.Fatal(err)
2601 }
2602 }
2603
2604 func TestRowsImplicitClose(t *testing.T) {
2605 db := newTestDB(t, "people")
2606 defer closeDB(t, db)
2607
2608 rows, err := db.Query("SELECT|people|age,name|")
2609 if err != nil {
2610 t.Fatal(err)
2611 }
2612
2613 want, fail := 2, errors.New("fail")
2614 r := rows.rowsi.(*rowsCursor)
2615 r.errPos, r.err = want, fail
2616
2617 got := 0
2618 for rows.Next() {
2619 got++
2620 }
2621 if got != want {
2622 t.Errorf("got %d rows, want %d", got, want)
2623 }
2624 if err := rows.Err(); err != fail {
2625 t.Errorf("got error %v, want %v", err, fail)
2626 }
2627 if !r.closed {
2628 t.Errorf("r.closed is false, want true")
2629 }
2630 }
2631
2632 func TestRowsCloseError(t *testing.T) {
2633 db := newTestDB(t, "people")
2634 defer db.Close()
2635 rows, err := db.Query("SELECT|people|age,name|")
2636 if err != nil {
2637 t.Fatalf("Query: %v", err)
2638 }
2639 type row struct {
2640 age int
2641 name string
2642 }
2643 got := []row{}
2644
2645 rc, ok := rows.rowsi.(*rowsCursor)
2646 if !ok {
2647 t.Fatal("not using *rowsCursor")
2648 }
2649 rc.closeErr = errors.New("rowsCursor: failed to close")
2650
2651 for rows.Next() {
2652 var r row
2653 err = rows.Scan(&r.age, &r.name)
2654 if err != nil {
2655 t.Fatalf("Scan: %v", err)
2656 }
2657 got = append(got, r)
2658 }
2659 err = rows.Err()
2660 if err != rc.closeErr {
2661 t.Fatalf("unexpected err: got %v, want %v", err, rc.closeErr)
2662 }
2663 }
2664
2665 func TestStmtCloseOrder(t *testing.T) {
2666 db := newTestDB(t, "people")
2667 defer closeDB(t, db)
2668
2669 db.SetMaxIdleConns(0)
2670 setStrictFakeConnClose(t)
2671 defer setStrictFakeConnClose(nil)
2672
2673 _, err := db.Query("SELECT|non_existent|name|")
2674 if err == nil {
2675 t.Fatal("Querying non-existent table should fail")
2676 }
2677 }
2678
2679
2680
2681 func TestManyErrBadConn(t *testing.T) {
2682 manyErrBadConnSetup := func(first ...func(db *DB)) *DB {
2683 db := newTestDB(t, "people")
2684
2685 for _, f := range first {
2686 f(db)
2687 }
2688
2689 nconn := maxBadConnRetries + 1
2690 db.SetMaxIdleConns(nconn)
2691 db.SetMaxOpenConns(nconn)
2692
2693 func() {
2694 for i := 0; i < nconn; i++ {
2695 rows, err := db.Query("SELECT|people|age,name|")
2696 if err != nil {
2697 t.Fatal(err)
2698 }
2699 defer rows.Close()
2700 }
2701 }()
2702
2703 db.mu.Lock()
2704 defer db.mu.Unlock()
2705 if db.numOpen != nconn {
2706 t.Fatalf("unexpected numOpen %d (was expecting %d)", db.numOpen, nconn)
2707 } else if len(db.freeConn) != nconn {
2708 t.Fatalf("unexpected len(db.freeConn) %d (was expecting %d)", len(db.freeConn), nconn)
2709 }
2710 for _, conn := range db.freeConn {
2711 conn.Lock()
2712 conn.ci.(*fakeConn).stickyBad = true
2713 conn.Unlock()
2714 }
2715 return db
2716 }
2717
2718
2719 db := manyErrBadConnSetup()
2720 defer closeDB(t, db)
2721 rows, err := db.Query("SELECT|people|age,name|")
2722 if err != nil {
2723 t.Fatal(err)
2724 }
2725 if err = rows.Close(); err != nil {
2726 t.Fatal(err)
2727 }
2728
2729
2730 db = manyErrBadConnSetup()
2731 defer closeDB(t, db)
2732 _, err = db.Exec("INSERT|people|name=Julia,age=19")
2733 if err != nil {
2734 t.Fatal(err)
2735 }
2736
2737
2738 db = manyErrBadConnSetup()
2739 defer closeDB(t, db)
2740 tx, err := db.Begin()
2741 if err != nil {
2742 t.Fatal(err)
2743 }
2744 if err = tx.Rollback(); err != nil {
2745 t.Fatal(err)
2746 }
2747
2748
2749 db = manyErrBadConnSetup()
2750 defer closeDB(t, db)
2751 stmt, err := db.Prepare("SELECT|people|age,name|")
2752 if err != nil {
2753 t.Fatal(err)
2754 }
2755 if err = stmt.Close(); err != nil {
2756 t.Fatal(err)
2757 }
2758
2759
2760 db = manyErrBadConnSetup(func(db *DB) {
2761 stmt, err = db.Prepare("INSERT|people|name=Julia,age=19")
2762 if err != nil {
2763 t.Fatal(err)
2764 }
2765 })
2766 defer closeDB(t, db)
2767 _, err = stmt.Exec()
2768 if err != nil {
2769 t.Fatal(err)
2770 }
2771 if err = stmt.Close(); err != nil {
2772 t.Fatal(err)
2773 }
2774
2775
2776 db = manyErrBadConnSetup(func(db *DB) {
2777 stmt, err = db.Prepare("SELECT|people|age,name|")
2778 if err != nil {
2779 t.Fatal(err)
2780 }
2781 })
2782 defer closeDB(t, db)
2783 rows, err = stmt.Query()
2784 if err != nil {
2785 t.Fatal(err)
2786 }
2787 if err = rows.Close(); err != nil {
2788 t.Fatal(err)
2789 }
2790 if err = stmt.Close(); err != nil {
2791 t.Fatal(err)
2792 }
2793
2794
2795 db = manyErrBadConnSetup()
2796 defer closeDB(t, db)
2797 ctx, cancel := context.WithCancel(context.Background())
2798 defer cancel()
2799 conn, err := db.Conn(ctx)
2800 if err != nil {
2801 t.Fatal(err)
2802 }
2803 conn.dc.ci.(*fakeConn).skipDirtySession = true
2804 err = conn.Close()
2805 if err != nil {
2806 t.Fatal(err)
2807 }
2808
2809
2810 db = manyErrBadConnSetup()
2811 defer closeDB(t, db)
2812 err = db.PingContext(ctx)
2813 if err != nil {
2814 t.Fatal(err)
2815 }
2816 }
2817
2818
2819 func TestTxCannotCommitAfterRollback(t *testing.T) {
2820 db := newTestDB(t, "tx_status")
2821 defer closeDB(t, db)
2822
2823
2824 var txStatus string
2825 err := db.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2826 if err != nil {
2827 t.Fatal(err)
2828 }
2829 if g, w := txStatus, "autocommit"; g != w {
2830 t.Fatalf("tx_status=%q, wanted %q", g, w)
2831 }
2832
2833 ctx, cancel := context.WithCancel(context.Background())
2834 defer cancel()
2835
2836 tx, err := db.BeginTx(ctx, nil)
2837 if err != nil {
2838 t.Fatal(err)
2839 }
2840
2841
2842
2843
2844 tx.txi.(*fakeTx).c.skipDirtySession = true
2845
2846 defer tx.Rollback()
2847
2848 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2849 if err != nil {
2850 t.Fatal(err)
2851 }
2852 if g, w := txStatus, "transaction"; g != w {
2853 t.Fatalf("tx_status=%q, wanted %q", g, w)
2854 }
2855
2856
2857
2858
2859 sendQuery := make(chan struct{})
2860
2861
2862 bypassRowsAwaitDone = true
2863 hookTxGrabConn = func() {
2864 cancel()
2865 <-sendQuery
2866 }
2867 rollbackHook = func() {
2868 close(sendQuery)
2869 }
2870 defer func() {
2871 hookTxGrabConn = nil
2872 rollbackHook = nil
2873 bypassRowsAwaitDone = false
2874 }()
2875
2876 err = tx.QueryRow("SELECT|tx_status|tx_status|").Scan(&txStatus)
2877 if err != nil {
2878
2879 t.Fatal(err)
2880 }
2881 if g, w := txStatus, "transaction"; g != w {
2882 t.Fatalf("tx_status=%q, wanted %q", g, w)
2883 }
2884 }
2885
2886
2887 func TestTxStmtDeadlock(t *testing.T) {
2888 db := newTestDB(t, "people")
2889 defer closeDB(t, db)
2890
2891 ctx, cancel := context.WithCancel(context.Background())
2892 defer cancel()
2893 tx, err := db.BeginTx(ctx, nil)
2894 if err != nil {
2895 t.Fatal(err)
2896 }
2897
2898 stmt, err := tx.Prepare("SELECT|people|name,age|age=?")
2899 if err != nil {
2900 t.Fatal(err)
2901 }
2902 cancel()
2903
2904 for i := 0; i < 1e3; i++ {
2905
2906
2907 _, err = stmt.Query(1)
2908 if err != nil {
2909 break
2910 }
2911 }
2912 _ = tx.Rollback()
2913 }
2914
2915
2916
2917
2918 func TestConnExpiresFreshOutOfPool(t *testing.T) {
2919 execCases := []struct {
2920 expired bool
2921 badReset bool
2922 }{
2923 {false, false},
2924 {true, false},
2925 {false, true},
2926 }
2927
2928 t0 := time.Unix(1000000, 0)
2929 offset := time.Duration(0)
2930 offsetMu := sync.RWMutex{}
2931
2932 nowFunc = func() time.Time {
2933 offsetMu.RLock()
2934 defer offsetMu.RUnlock()
2935 return t0.Add(offset)
2936 }
2937 defer func() { nowFunc = time.Now }()
2938
2939 ctx, cancel := context.WithCancel(context.Background())
2940 defer cancel()
2941
2942 db := newTestDB(t, "magicquery")
2943 defer closeDB(t, db)
2944
2945 db.SetMaxOpenConns(1)
2946
2947 for _, ec := range execCases {
2948 ec := ec
2949 name := fmt.Sprintf("expired=%t,badReset=%t", ec.expired, ec.badReset)
2950 t.Run(name, func(t *testing.T) {
2951 db.clearAllConns(t)
2952
2953 db.SetMaxIdleConns(1)
2954 db.SetConnMaxLifetime(10 * time.Second)
2955
2956 conn, err := db.conn(ctx, alwaysNewConn)
2957 if err != nil {
2958 t.Fatal(err)
2959 }
2960
2961 afterPutConn := make(chan struct{})
2962 waitingForConn := make(chan struct{})
2963
2964 go func() {
2965 defer close(afterPutConn)
2966
2967 conn, err := db.conn(ctx, alwaysNewConn)
2968 if err == nil {
2969 db.putConn(conn, err, false)
2970 } else {
2971 t.Errorf("db.conn: %v", err)
2972 }
2973 }()
2974 go func() {
2975 defer close(waitingForConn)
2976
2977 for {
2978 if t.Failed() {
2979 return
2980 }
2981 db.mu.Lock()
2982 ct := db.connRequests.Len()
2983 db.mu.Unlock()
2984 if ct > 0 {
2985 return
2986 }
2987 time.Sleep(pollDuration)
2988 }
2989 }()
2990
2991 <-waitingForConn
2992
2993 if t.Failed() {
2994 return
2995 }
2996
2997 offsetMu.Lock()
2998 if ec.expired {
2999 offset = 11 * time.Second
3000 } else {
3001 offset = time.Duration(0)
3002 }
3003 offsetMu.Unlock()
3004
3005 conn.ci.(*fakeConn).stickyBad = ec.badReset
3006
3007 db.putConn(conn, err, true)
3008
3009 <-afterPutConn
3010 })
3011 }
3012 }
3013
3014
3015
3016 func TestIssue20575(t *testing.T) {
3017 db := newTestDB(t, "people")
3018 defer closeDB(t, db)
3019
3020 tx, err := db.Begin()
3021 if err != nil {
3022 t.Fatal(err)
3023 }
3024 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
3025 defer cancel()
3026 _, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
3027 if err != nil {
3028 t.Fatal(err)
3029 }
3030
3031 err = tx.Rollback()
3032 if err != nil {
3033 t.Fatal(err)
3034 }
3035 select {
3036 default:
3037 case <-ctx.Done():
3038 t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err())
3039 }
3040 }
3041
3042
3043
3044 func TestIssue20622(t *testing.T) {
3045 db := newTestDB(t, "people")
3046 defer closeDB(t, db)
3047
3048 ctx, cancel := context.WithCancel(context.Background())
3049 defer cancel()
3050
3051 tx, err := db.BeginTx(ctx, nil)
3052 if err != nil {
3053 t.Fatal(err)
3054 }
3055
3056 rows, err := tx.Query("SELECT|people|age,name|")
3057 if err != nil {
3058 t.Fatal(err)
3059 }
3060
3061 count := 0
3062 for rows.Next() {
3063 count++
3064 var age int
3065 var name string
3066 if err := rows.Scan(&age, &name); err != nil {
3067 t.Fatal("scan failed", err)
3068 }
3069
3070 if count == 1 {
3071 cancel()
3072 }
3073 time.Sleep(100 * time.Millisecond)
3074 }
3075 rows.Close()
3076 tx.Commit()
3077 }
3078
3079
3080 func TestErrBadConnReconnect(t *testing.T) {
3081 db := newTestDB(t, "foo")
3082 defer closeDB(t, db)
3083 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
3084
3085 simulateBadConn := func(name string, hook *func() bool, op func() error) {
3086 broken, retried := false, false
3087 numOpen := db.numOpen
3088
3089
3090 *hook = func() bool {
3091 if !broken {
3092 broken = true
3093 return true
3094 }
3095 retried = true
3096 return false
3097 }
3098
3099 if err := op(); err != nil {
3100 t.Errorf(name+": %v", err)
3101 return
3102 }
3103
3104 if !broken || !retried {
3105 t.Error(name + ": Failed to simulate broken connection")
3106 }
3107 *hook = nil
3108
3109 if numOpen != db.numOpen {
3110 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
3111 numOpen = db.numOpen
3112 }
3113 }
3114
3115
3116 dbExec := func() error {
3117 _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3118 return err
3119 }
3120 simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec)
3121 simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec)
3122
3123
3124 dbQuery := func() error {
3125 rows, err := db.Query("SELECT|t1|age,name|")
3126 if err == nil {
3127 err = rows.Close()
3128 }
3129 return err
3130 }
3131 simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery)
3132 simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery)
3133
3134
3135 simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error {
3136 stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
3137 if err != nil {
3138 return err
3139 }
3140 stmt.Close()
3141 return nil
3142 })
3143
3144
3145 forcePrepare := func(stmt *Stmt) {
3146 stmt.css = nil
3147 }
3148
3149
3150 stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?")
3151 if err != nil {
3152 t.Fatalf("prepare: %v", err)
3153 }
3154 defer stmt1.Close()
3155
3156 forcePrepare(stmt1)
3157
3158 stmtExec := func() error {
3159 _, err := stmt1.Exec("Gopher", 3, false)
3160 return err
3161 }
3162 simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec)
3163 simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec)
3164
3165
3166 stmt2, err := db.Prepare("SELECT|t1|age,name|")
3167 if err != nil {
3168 t.Fatalf("prepare: %v", err)
3169 }
3170 defer stmt2.Close()
3171
3172 forcePrepare(stmt2)
3173
3174 stmtQuery := func() error {
3175 rows, err := stmt2.Query()
3176 if err == nil {
3177 err = rows.Close()
3178 }
3179 return err
3180 }
3181 simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery)
3182 simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery)
3183 }
3184
3185
3186 func TestTxEndBadConn(t *testing.T) {
3187 db := newTestDB(t, "foo")
3188 defer closeDB(t, db)
3189 db.SetMaxIdleConns(0)
3190 exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
3191 db.SetMaxIdleConns(1)
3192
3193 simulateBadConn := func(name string, hook *func() bool, op func() error) {
3194 broken := false
3195 numOpen := db.numOpen
3196
3197 *hook = func() bool {
3198 if !broken {
3199 broken = true
3200 }
3201 return broken
3202 }
3203
3204 if err := op(); !errors.Is(err, driver.ErrBadConn) {
3205 t.Errorf(name+": %v", err)
3206 return
3207 }
3208
3209 if !broken {
3210 t.Error(name + ": Failed to simulate broken connection")
3211 }
3212 *hook = nil
3213
3214 if numOpen != db.numOpen {
3215 t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
3216 }
3217 }
3218
3219
3220 dbExec := func(endTx func(tx *Tx) error) func() error {
3221 return func() error {
3222 tx, err := db.Begin()
3223 if err != nil {
3224 return err
3225 }
3226 _, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
3227 if err != nil {
3228 return err
3229 }
3230 return endTx(tx)
3231 }
3232 }
3233 simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit))
3234 simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback))
3235
3236
3237 dbQuery := func(endTx func(tx *Tx) error) func() error {
3238 return func() error {
3239 tx, err := db.Begin()
3240 if err != nil {
3241 return err
3242 }
3243 rows, err := tx.Query("SELECT|t1|age,name|")
3244 if err == nil {
3245 err = rows.Close()
3246 } else {
3247 return err
3248 }
3249 return endTx(tx)
3250 }
3251 }
3252 simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit))
3253 simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback))
3254 }
3255
3256 type concurrentTest interface {
3257 init(t testing.TB, db *DB)
3258 finish(t testing.TB)
3259 test(t testing.TB) error
3260 }
3261
3262 type concurrentDBQueryTest struct {
3263 db *DB
3264 }
3265
3266 func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) {
3267 c.db = db
3268 }
3269
3270 func (c *concurrentDBQueryTest) finish(t testing.TB) {
3271 c.db = nil
3272 }
3273
3274 func (c *concurrentDBQueryTest) test(t testing.TB) error {
3275 rows, err := c.db.Query("SELECT|people|name|")
3276 if err != nil {
3277 t.Error(err)
3278 return err
3279 }
3280 var name string
3281 for rows.Next() {
3282 rows.Scan(&name)
3283 }
3284 rows.Close()
3285 return nil
3286 }
3287
3288 type concurrentDBExecTest struct {
3289 db *DB
3290 }
3291
3292 func (c *concurrentDBExecTest) init(t testing.TB, db *DB) {
3293 c.db = db
3294 }
3295
3296 func (c *concurrentDBExecTest) finish(t testing.TB) {
3297 c.db = nil
3298 }
3299
3300 func (c *concurrentDBExecTest) test(t testing.TB) error {
3301 _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
3302 if err != nil {
3303 t.Error(err)
3304 return err
3305 }
3306 return nil
3307 }
3308
3309 type concurrentStmtQueryTest struct {
3310 db *DB
3311 stmt *Stmt
3312 }
3313
3314 func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) {
3315 c.db = db
3316 var err error
3317 c.stmt, err = db.Prepare("SELECT|people|name|")
3318 if err != nil {
3319 t.Fatal(err)
3320 }
3321 }
3322
3323 func (c *concurrentStmtQueryTest) finish(t testing.TB) {
3324 if c.stmt != nil {
3325 c.stmt.Close()
3326 c.stmt = nil
3327 }
3328 c.db = nil
3329 }
3330
3331 func (c *concurrentStmtQueryTest) test(t testing.TB) error {
3332 rows, err := c.stmt.Query()
3333 if err != nil {
3334 t.Errorf("error on query: %v", err)
3335 return err
3336 }
3337
3338 var name string
3339 for rows.Next() {
3340 rows.Scan(&name)
3341 }
3342 rows.Close()
3343 return nil
3344 }
3345
3346 type concurrentStmtExecTest struct {
3347 db *DB
3348 stmt *Stmt
3349 }
3350
3351 func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) {
3352 c.db = db
3353 var err error
3354 c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3355 if err != nil {
3356 t.Fatal(err)
3357 }
3358 }
3359
3360 func (c *concurrentStmtExecTest) finish(t testing.TB) {
3361 if c.stmt != nil {
3362 c.stmt.Close()
3363 c.stmt = nil
3364 }
3365 c.db = nil
3366 }
3367
3368 func (c *concurrentStmtExecTest) test(t testing.TB) error {
3369 _, err := c.stmt.Exec(3, chrisBirthday)
3370 if err != nil {
3371 t.Errorf("error on exec: %v", err)
3372 return err
3373 }
3374 return nil
3375 }
3376
3377 type concurrentTxQueryTest struct {
3378 db *DB
3379 tx *Tx
3380 }
3381
3382 func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) {
3383 c.db = db
3384 var err error
3385 c.tx, err = c.db.Begin()
3386 if err != nil {
3387 t.Fatal(err)
3388 }
3389 }
3390
3391 func (c *concurrentTxQueryTest) finish(t testing.TB) {
3392 if c.tx != nil {
3393 c.tx.Rollback()
3394 c.tx = nil
3395 }
3396 c.db = nil
3397 }
3398
3399 func (c *concurrentTxQueryTest) test(t testing.TB) error {
3400 rows, err := c.db.Query("SELECT|people|name|")
3401 if err != nil {
3402 t.Error(err)
3403 return err
3404 }
3405 var name string
3406 for rows.Next() {
3407 rows.Scan(&name)
3408 }
3409 rows.Close()
3410 return nil
3411 }
3412
3413 type concurrentTxExecTest struct {
3414 db *DB
3415 tx *Tx
3416 }
3417
3418 func (c *concurrentTxExecTest) init(t testing.TB, db *DB) {
3419 c.db = db
3420 var err error
3421 c.tx, err = c.db.Begin()
3422 if err != nil {
3423 t.Fatal(err)
3424 }
3425 }
3426
3427 func (c *concurrentTxExecTest) finish(t testing.TB) {
3428 if c.tx != nil {
3429 c.tx.Rollback()
3430 c.tx = nil
3431 }
3432 c.db = nil
3433 }
3434
3435 func (c *concurrentTxExecTest) test(t testing.TB) error {
3436 _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
3437 if err != nil {
3438 t.Error(err)
3439 return err
3440 }
3441 return nil
3442 }
3443
3444 type concurrentTxStmtQueryTest struct {
3445 db *DB
3446 tx *Tx
3447 stmt *Stmt
3448 }
3449
3450 func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) {
3451 c.db = db
3452 var err error
3453 c.tx, err = c.db.Begin()
3454 if err != nil {
3455 t.Fatal(err)
3456 }
3457 c.stmt, err = c.tx.Prepare("SELECT|people|name|")
3458 if err != nil {
3459 t.Fatal(err)
3460 }
3461 }
3462
3463 func (c *concurrentTxStmtQueryTest) finish(t testing.TB) {
3464 if c.stmt != nil {
3465 c.stmt.Close()
3466 c.stmt = nil
3467 }
3468 if c.tx != nil {
3469 c.tx.Rollback()
3470 c.tx = nil
3471 }
3472 c.db = nil
3473 }
3474
3475 func (c *concurrentTxStmtQueryTest) test(t testing.TB) error {
3476 rows, err := c.stmt.Query()
3477 if err != nil {
3478 t.Errorf("error on query: %v", err)
3479 return err
3480 }
3481
3482 var name string
3483 for rows.Next() {
3484 rows.Scan(&name)
3485 }
3486 rows.Close()
3487 return nil
3488 }
3489
3490 type concurrentTxStmtExecTest struct {
3491 db *DB
3492 tx *Tx
3493 stmt *Stmt
3494 }
3495
3496 func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) {
3497 c.db = db
3498 var err error
3499 c.tx, err = c.db.Begin()
3500 if err != nil {
3501 t.Fatal(err)
3502 }
3503 c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
3504 if err != nil {
3505 t.Fatal(err)
3506 }
3507 }
3508
3509 func (c *concurrentTxStmtExecTest) finish(t testing.TB) {
3510 if c.stmt != nil {
3511 c.stmt.Close()
3512 c.stmt = nil
3513 }
3514 if c.tx != nil {
3515 c.tx.Rollback()
3516 c.tx = nil
3517 }
3518 c.db = nil
3519 }
3520
3521 func (c *concurrentTxStmtExecTest) test(t testing.TB) error {
3522 _, err := c.stmt.Exec(3, chrisBirthday)
3523 if err != nil {
3524 t.Errorf("error on exec: %v", err)
3525 return err
3526 }
3527 return nil
3528 }
3529
3530 type concurrentRandomTest struct {
3531 tests []concurrentTest
3532 }
3533
3534 func (c *concurrentRandomTest) init(t testing.TB, db *DB) {
3535 c.tests = []concurrentTest{
3536 new(concurrentDBQueryTest),
3537 new(concurrentDBExecTest),
3538 new(concurrentStmtQueryTest),
3539 new(concurrentStmtExecTest),
3540 new(concurrentTxQueryTest),
3541 new(concurrentTxExecTest),
3542 new(concurrentTxStmtQueryTest),
3543 new(concurrentTxStmtExecTest),
3544 }
3545 for _, ct := range c.tests {
3546 ct.init(t, db)
3547 }
3548 }
3549
3550 func (c *concurrentRandomTest) finish(t testing.TB) {
3551 for _, ct := range c.tests {
3552 ct.finish(t)
3553 }
3554 }
3555
3556 func (c *concurrentRandomTest) test(t testing.TB) error {
3557 ct := c.tests[rand.Intn(len(c.tests))]
3558 return ct.test(t)
3559 }
3560
3561 func doConcurrentTest(t testing.TB, ct concurrentTest) {
3562 maxProcs, numReqs := 1, 500
3563 if testing.Short() {
3564 maxProcs, numReqs = 4, 50
3565 }
3566 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
3567
3568 db := newTestDB(t, "people")
3569 defer closeDB(t, db)
3570
3571 ct.init(t, db)
3572 defer ct.finish(t)
3573
3574 var wg sync.WaitGroup
3575 wg.Add(numReqs)
3576
3577 reqs := make(chan bool)
3578 defer close(reqs)
3579
3580 for i := 0; i < maxProcs*2; i++ {
3581 go func() {
3582 for range reqs {
3583 err := ct.test(t)
3584 if err != nil {
3585 wg.Done()
3586 continue
3587 }
3588 wg.Done()
3589 }
3590 }()
3591 }
3592
3593 for i := 0; i < numReqs; i++ {
3594 reqs <- true
3595 }
3596
3597 wg.Wait()
3598 }
3599
3600 func TestIssue6081(t *testing.T) {
3601 db := newTestDB(t, "people")
3602 defer closeDB(t, db)
3603
3604 drv := db.Driver().(*fakeDriver)
3605 drv.mu.Lock()
3606 opens0 := drv.openCount
3607 closes0 := drv.closeCount
3608 drv.mu.Unlock()
3609
3610 stmt, err := db.Prepare("SELECT|people|name|")
3611 if err != nil {
3612 t.Fatal(err)
3613 }
3614 setRowsCloseHook(func(rows *Rows, err *error) {
3615 *err = driver.ErrBadConn
3616 })
3617 defer setRowsCloseHook(nil)
3618 for i := 0; i < 10; i++ {
3619 rows, err := stmt.Query()
3620 if err != nil {
3621 t.Fatal(err)
3622 }
3623 rows.Close()
3624 }
3625 if n := len(stmt.css); n > 1 {
3626 t.Errorf("len(css slice) = %d; want <= 1", n)
3627 }
3628 stmt.Close()
3629 if n := len(stmt.css); n != 0 {
3630 t.Errorf("len(css slice) after Close = %d; want 0", n)
3631 }
3632
3633 drv.mu.Lock()
3634 opens := drv.openCount - opens0
3635 closes := drv.closeCount - closes0
3636 drv.mu.Unlock()
3637 if opens < 9 {
3638 t.Errorf("opens = %d; want >= 9", opens)
3639 }
3640 if closes < 9 {
3641 t.Errorf("closes = %d; want >= 9", closes)
3642 }
3643 }
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656 func TestIssue18429(t *testing.T) {
3657 db := newTestDB(t, "people")
3658 defer closeDB(t, db)
3659
3660 ctx := context.Background()
3661 sem := make(chan bool, 20)
3662 var wg sync.WaitGroup
3663
3664 const milliWait = 30
3665
3666 for i := 0; i < 100; i++ {
3667 sem <- true
3668 wg.Add(1)
3669 go func() {
3670 defer func() {
3671 <-sem
3672 wg.Done()
3673 }()
3674 qwait := (time.Duration(rand.Intn(milliWait)) * time.Millisecond).String()
3675
3676 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
3677 defer cancel()
3678
3679 tx, err := db.BeginTx(ctx, nil)
3680 if err != nil {
3681 return
3682 }
3683
3684
3685
3686 rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
3687 if rows != nil {
3688 var name string
3689
3690 for rows.Next() {
3691
3692 rows.Scan(&name)
3693 }
3694 rows.Close()
3695 }
3696
3697
3698 tx.Rollback()
3699 }()
3700 }
3701 wg.Wait()
3702 }
3703
3704
3705 func TestIssue20160(t *testing.T) {
3706 db := newTestDB(t, "people")
3707 defer closeDB(t, db)
3708
3709 ctx := context.Background()
3710 sem := make(chan bool, 20)
3711 var wg sync.WaitGroup
3712
3713 const milliWait = 30
3714
3715 stmt, err := db.PrepareContext(ctx, "SELECT|people|name|")
3716 if err != nil {
3717 t.Fatal(err)
3718 }
3719 defer stmt.Close()
3720
3721 for i := 0; i < 100; i++ {
3722 sem <- true
3723 wg.Add(1)
3724 go func() {
3725 defer func() {
3726 <-sem
3727 wg.Done()
3728 }()
3729 ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
3730 defer cancel()
3731
3732
3733
3734
3735 rows, _ := stmt.QueryContext(ctx)
3736 if rows != nil {
3737 rows.Close()
3738 }
3739 }()
3740 }
3741 wg.Wait()
3742 }
3743
3744
3745
3746
3747
3748
3749 func TestIssue18719(t *testing.T) {
3750 db := newTestDB(t, "people")
3751 defer closeDB(t, db)
3752
3753 ctx, cancel := context.WithCancel(context.Background())
3754 defer cancel()
3755
3756 tx, err := db.BeginTx(ctx, nil)
3757 if err != nil {
3758 t.Fatal(err)
3759 }
3760
3761 hookTxGrabConn = func() {
3762 cancel()
3763
3764
3765 for !tx.isDone() {
3766 time.Sleep(pollDuration)
3767 }
3768 }
3769 defer func() { hookTxGrabConn = nil }()
3770
3771
3772
3773 _, err = tx.QueryContext(ctx, "SELECT|people|name|")
3774 if err != nil {
3775 t.Fatalf("expected error %v but got %v", nil, err)
3776 }
3777
3778
3779
3780
3781
3782
3783 cancel()
3784 }
3785
3786 func TestIssue20647(t *testing.T) {
3787 db := newTestDB(t, "people")
3788 defer closeDB(t, db)
3789
3790 ctx, cancel := context.WithCancel(context.Background())
3791 defer cancel()
3792
3793 conn, err := db.Conn(ctx)
3794 if err != nil {
3795 t.Fatal(err)
3796 }
3797 conn.dc.ci.(*fakeConn).skipDirtySession = true
3798 defer conn.Close()
3799
3800 stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|")
3801 if err != nil {
3802 t.Fatal(err)
3803 }
3804 defer stmt.Close()
3805
3806 rows1, err := stmt.QueryContext(ctx)
3807 if err != nil {
3808 t.Fatal("rows1", err)
3809 }
3810 defer rows1.Close()
3811
3812 rows2, err := stmt.QueryContext(ctx)
3813 if err != nil {
3814 t.Fatal("rows2", err)
3815 }
3816 defer rows2.Close()
3817
3818 if rows1.dc != rows2.dc {
3819 t.Fatal("stmt prepared on Conn does not use same connection")
3820 }
3821 }
3822
3823 func TestConcurrency(t *testing.T) {
3824 list := []struct {
3825 name string
3826 ct concurrentTest
3827 }{
3828 {"Query", new(concurrentDBQueryTest)},
3829 {"Exec", new(concurrentDBExecTest)},
3830 {"StmtQuery", new(concurrentStmtQueryTest)},
3831 {"StmtExec", new(concurrentStmtExecTest)},
3832 {"TxQuery", new(concurrentTxQueryTest)},
3833 {"TxExec", new(concurrentTxExecTest)},
3834 {"TxStmtQuery", new(concurrentTxStmtQueryTest)},
3835 {"TxStmtExec", new(concurrentTxStmtExecTest)},
3836 {"Random", new(concurrentRandomTest)},
3837 }
3838 for _, item := range list {
3839 t.Run(item.name, func(t *testing.T) {
3840 doConcurrentTest(t, item.ct)
3841 })
3842 }
3843 }
3844
3845 func TestConnectionLeak(t *testing.T) {
3846 db := newTestDB(t, "people")
3847 defer closeDB(t, db)
3848
3849 rows := make([]*Rows, defaultMaxIdleConns)
3850
3851
3852
3853 db.SetMaxOpenConns(len(rows) + 1)
3854 for ii := range rows {
3855 r, err := db.Query("SELECT|people|name|")
3856 if err != nil {
3857 t.Fatal(err)
3858 }
3859 r.Next()
3860 if err := r.Err(); err != nil {
3861 t.Fatal(err)
3862 }
3863 rows[ii] = r
3864 }
3865
3866
3867
3868 drv := db.Driver().(*fakeDriver)
3869 drv.waitCh = make(chan struct{}, 1)
3870 drv.waitingCh = make(chan struct{}, 1)
3871 var wg sync.WaitGroup
3872 wg.Add(1)
3873 go func() {
3874 r, err := db.Query("SELECT|people|name|")
3875 if err != nil {
3876 t.Error(err)
3877 return
3878 }
3879 r.Close()
3880 wg.Done()
3881 }()
3882
3883 <-drv.waitingCh
3884
3885
3886 for _, v := range rows {
3887 v.Close()
3888 }
3889
3890
3891
3892
3893 drv.waitCh <- struct{}{}
3894 wg.Wait()
3895 }
3896
3897 func TestStatsMaxIdleClosedZero(t *testing.T) {
3898 db := newTestDB(t, "people")
3899 defer closeDB(t, db)
3900
3901 db.SetMaxOpenConns(1)
3902 db.SetMaxIdleConns(1)
3903 db.SetConnMaxLifetime(0)
3904
3905 preMaxIdleClosed := db.Stats().MaxIdleClosed
3906
3907 for i := 0; i < 10; i++ {
3908 rows, err := db.Query("SELECT|people|name|")
3909 if err != nil {
3910 t.Fatal(err)
3911 }
3912 rows.Close()
3913 }
3914
3915 st := db.Stats()
3916 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
3917 t.Logf("MaxIdleClosed: %d", maxIdleClosed)
3918 if maxIdleClosed != 0 {
3919 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
3920 }
3921 }
3922
3923 func TestStatsMaxIdleClosedTen(t *testing.T) {
3924 db := newTestDB(t, "people")
3925 defer closeDB(t, db)
3926
3927 db.SetMaxOpenConns(1)
3928 db.SetMaxIdleConns(0)
3929 db.SetConnMaxLifetime(0)
3930
3931 preMaxIdleClosed := db.Stats().MaxIdleClosed
3932
3933 for i := 0; i < 10; i++ {
3934 rows, err := db.Query("SELECT|people|name|")
3935 if err != nil {
3936 t.Fatal(err)
3937 }
3938 rows.Close()
3939 }
3940
3941 st := db.Stats()
3942 maxIdleClosed := st.MaxIdleClosed - preMaxIdleClosed
3943 t.Logf("MaxIdleClosed: %d", maxIdleClosed)
3944 if maxIdleClosed != 10 {
3945 t.Fatal("expected 0 max idle closed conns, got: ", maxIdleClosed)
3946 }
3947 }
3948
3949
3950
3951 func testUseConns(t *testing.T, count int, tm time.Time, db *DB) time.Time {
3952 conns := make([]*Conn, count)
3953 ctx := context.Background()
3954 for i := range conns {
3955 tm = tm.Add(time.Nanosecond)
3956 nowFunc = func() time.Time {
3957 return tm
3958 }
3959 c, err := db.Conn(ctx)
3960 if err != nil {
3961 t.Error(err)
3962 }
3963 conns[i] = c
3964 }
3965
3966 for i := len(conns) - 1; i >= 0; i-- {
3967 tm = tm.Add(time.Nanosecond)
3968 nowFunc = func() time.Time {
3969 return tm
3970 }
3971 if err := conns[i].Close(); err != nil {
3972 t.Error(err)
3973 }
3974 }
3975
3976 return tm
3977 }
3978
3979 func TestMaxIdleTime(t *testing.T) {
3980 usedConns := 5
3981 reusedConns := 2
3982 list := []struct {
3983 wantMaxIdleTime time.Duration
3984 wantMaxLifetime time.Duration
3985 wantNextCheck time.Duration
3986 wantIdleClosed int64
3987 wantMaxIdleClosed int64
3988 timeOffset time.Duration
3989 secondTimeOffset time.Duration
3990 }{
3991 {
3992 time.Millisecond,
3993 0,
3994 time.Millisecond - time.Nanosecond,
3995 int64(usedConns - reusedConns),
3996 int64(usedConns - reusedConns),
3997 10 * time.Millisecond,
3998 0,
3999 },
4000 {
4001
4002 time.Millisecond,
4003
4004
4005
4006 10*time.Millisecond + 100*time.Nanosecond + 3*time.Nanosecond,
4007 time.Nanosecond,
4008
4009 int64(usedConns - reusedConns + 1),
4010 int64(usedConns - reusedConns),
4011 10 * time.Millisecond,
4012
4013 100 * time.Nanosecond,
4014 },
4015 {
4016 time.Hour,
4017 0,
4018 time.Second,
4019 0,
4020 0,
4021 10 * time.Millisecond,
4022 0},
4023 }
4024 baseTime := time.Unix(0, 0)
4025 defer func() {
4026 nowFunc = time.Now
4027 }()
4028 for _, item := range list {
4029 nowFunc = func() time.Time {
4030 return baseTime
4031 }
4032 t.Run(fmt.Sprintf("%v", item.wantMaxIdleTime), func(t *testing.T) {
4033 db := newTestDB(t, "people")
4034 defer closeDB(t, db)
4035
4036 db.SetMaxOpenConns(usedConns)
4037 db.SetMaxIdleConns(usedConns)
4038 db.SetConnMaxIdleTime(item.wantMaxIdleTime)
4039 db.SetConnMaxLifetime(item.wantMaxLifetime)
4040
4041 preMaxIdleClosed := db.Stats().MaxIdleTimeClosed
4042
4043
4044 testUseConns(t, usedConns, baseTime, db)
4045
4046 tm := baseTime.Add(item.timeOffset)
4047
4048
4049
4050 tm = testUseConns(t, reusedConns, tm, db)
4051
4052 tm = tm.Add(item.secondTimeOffset)
4053 nowFunc = func() time.Time {
4054 return tm
4055 }
4056
4057 db.mu.Lock()
4058 nc, closing := db.connectionCleanerRunLocked(time.Second)
4059 if nc != item.wantNextCheck {
4060 t.Errorf("got %v; want %v next check duration", nc, item.wantNextCheck)
4061 }
4062
4063
4064 var last time.Time
4065 for _, c := range db.freeConn {
4066 if last.After(c.returnedAt) {
4067 t.Error("freeConn is not ordered by returnedAt")
4068 break
4069 }
4070 last = c.returnedAt
4071 }
4072
4073 db.mu.Unlock()
4074 for _, c := range closing {
4075 c.Close()
4076 }
4077 if g, w := int64(len(closing)), item.wantIdleClosed; g != w {
4078 t.Errorf("got: %d; want %d closed conns", g, w)
4079 }
4080
4081 st := db.Stats()
4082 maxIdleClosed := st.MaxIdleTimeClosed - preMaxIdleClosed
4083 if g, w := maxIdleClosed, item.wantMaxIdleClosed; g != w {
4084 t.Errorf("got: %d; want %d max idle closed conns", g, w)
4085 }
4086 })
4087 }
4088 }
4089
4090 type nvcDriver struct {
4091 fakeDriver
4092 skipNamedValueCheck bool
4093 }
4094
4095 func (d *nvcDriver) Open(dsn string) (driver.Conn, error) {
4096 c, err := d.fakeDriver.Open(dsn)
4097 fc := c.(*fakeConn)
4098 fc.db.allowAny = true
4099 return &nvcConn{fc, d.skipNamedValueCheck}, err
4100 }
4101
4102 type nvcConn struct {
4103 *fakeConn
4104 skipNamedValueCheck bool
4105 }
4106
4107 type decimalInt struct {
4108 value int
4109 }
4110
4111 type doNotInclude struct{}
4112
4113 var _ driver.NamedValueChecker = &nvcConn{}
4114
4115 func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error {
4116 if c.skipNamedValueCheck {
4117 return driver.ErrSkip
4118 }
4119 switch v := nv.Value.(type) {
4120 default:
4121 return driver.ErrSkip
4122 case Out:
4123 switch ov := v.Dest.(type) {
4124 default:
4125 return errors.New("unknown NameValueCheck OUTPUT type")
4126 case *string:
4127 *ov = "from-server"
4128 nv.Value = "OUT:*string"
4129 }
4130 return nil
4131 case decimalInt, []int64:
4132 return nil
4133 case doNotInclude:
4134 return driver.ErrRemoveArgument
4135 }
4136 }
4137
4138 func TestNamedValueChecker(t *testing.T) {
4139 Register("NamedValueCheck", &nvcDriver{})
4140 db, err := Open("NamedValueCheck", "")
4141 if err != nil {
4142 t.Fatal(err)
4143 }
4144 defer db.Close()
4145
4146 ctx, cancel := context.WithCancel(context.Background())
4147 defer cancel()
4148
4149 _, err = db.ExecContext(ctx, "WIPE")
4150 if err != nil {
4151 t.Fatal("exec wipe", err)
4152 }
4153
4154 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any")
4155 if err != nil {
4156 t.Fatal("exec create", err)
4157 }
4158
4159 o1 := ""
4160 _, 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{})
4161 if err != nil {
4162 t.Fatal("exec insert", err)
4163 }
4164 var (
4165 str1 string
4166 dec1 decimalInt
4167 arr1 []int64
4168 )
4169 err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1)
4170 if err != nil {
4171 t.Fatal("select", err)
4172 }
4173
4174 list := []struct{ got, want any }{
4175 {o1, "from-server"},
4176 {dec1, decimalInt{123}},
4177 {str1, "hello"},
4178 {arr1, []int64{42, 128, 707}},
4179 }
4180
4181 for index, item := range list {
4182 if !reflect.DeepEqual(item.got, item.want) {
4183 t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index)
4184 }
4185 }
4186 }
4187
4188 func TestNamedValueCheckerSkip(t *testing.T) {
4189 Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true})
4190 db, err := Open("NamedValueCheckSkip", "")
4191 if err != nil {
4192 t.Fatal(err)
4193 }
4194 defer db.Close()
4195
4196 ctx, cancel := context.WithCancel(context.Background())
4197 defer cancel()
4198
4199 _, err = db.ExecContext(ctx, "WIPE")
4200 if err != nil {
4201 t.Fatal("exec wipe", err)
4202 }
4203
4204 _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any")
4205 if err != nil {
4206 t.Fatal("exec create", err)
4207 }
4208
4209 _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimalInt{123}))
4210 if err == nil {
4211 t.Fatalf("expected error with bad argument, got %v", err)
4212 }
4213 }
4214
4215 func TestOpenConnector(t *testing.T) {
4216 Register("testctx", &fakeDriverCtx{})
4217 db, err := Open("testctx", "people")
4218 if err != nil {
4219 t.Fatal(err)
4220 }
4221 defer db.Close()
4222
4223 c, ok := db.connector.(*fakeConnector)
4224 if !ok {
4225 t.Fatal("not using *fakeConnector")
4226 }
4227
4228 if err := db.Close(); err != nil {
4229 t.Fatal(err)
4230 }
4231
4232 if !c.closed {
4233 t.Fatal("connector is not closed")
4234 }
4235 }
4236
4237 type ctxOnlyDriver struct {
4238 fakeDriver
4239 }
4240
4241 func (d *ctxOnlyDriver) Open(dsn string) (driver.Conn, error) {
4242 conn, err := d.fakeDriver.Open(dsn)
4243 if err != nil {
4244 return nil, err
4245 }
4246 return &ctxOnlyConn{fc: conn.(*fakeConn)}, nil
4247 }
4248
4249 var (
4250 _ driver.Conn = &ctxOnlyConn{}
4251 _ driver.QueryerContext = &ctxOnlyConn{}
4252 _ driver.ExecerContext = &ctxOnlyConn{}
4253 )
4254
4255 type ctxOnlyConn struct {
4256 fc *fakeConn
4257
4258 queryCtxCalled bool
4259 execCtxCalled bool
4260 }
4261
4262 func (c *ctxOnlyConn) Begin() (driver.Tx, error) {
4263 return c.fc.Begin()
4264 }
4265
4266 func (c *ctxOnlyConn) Close() error {
4267 return c.fc.Close()
4268 }
4269
4270
4271
4272 func (c *ctxOnlyConn) Prepare(q string) (driver.Stmt, error) {
4273 panic("not used")
4274 }
4275
4276 func (c *ctxOnlyConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) {
4277 return c.fc.PrepareContext(ctx, q)
4278 }
4279
4280 func (c *ctxOnlyConn) QueryContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Rows, error) {
4281 c.queryCtxCalled = true
4282 return c.fc.QueryContext(ctx, q, args)
4283 }
4284
4285 func (c *ctxOnlyConn) ExecContext(ctx context.Context, q string, args []driver.NamedValue) (driver.Result, error) {
4286 c.execCtxCalled = true
4287 return c.fc.ExecContext(ctx, q, args)
4288 }
4289
4290
4291
4292 func TestQueryExecContextOnly(t *testing.T) {
4293
4294 var connType driver.Conn = &ctxOnlyConn{}
4295 if _, ok := connType.(driver.Execer); ok {
4296 t.Fatalf("%T must not implement driver.Execer", connType)
4297 }
4298 if _, ok := connType.(driver.Queryer); ok {
4299 t.Fatalf("%T must not implement driver.Queryer", connType)
4300 }
4301
4302 Register("ContextOnly", &ctxOnlyDriver{})
4303 db, err := Open("ContextOnly", "")
4304 if err != nil {
4305 t.Fatal(err)
4306 }
4307 defer db.Close()
4308
4309 ctx, cancel := context.WithCancel(context.Background())
4310 defer cancel()
4311
4312 conn, err := db.Conn(ctx)
4313 if err != nil {
4314 t.Fatal("db.Conn", err)
4315 }
4316 defer conn.Close()
4317 coc := conn.dc.ci.(*ctxOnlyConn)
4318 coc.fc.skipDirtySession = true
4319
4320 _, err = conn.ExecContext(ctx, "WIPE")
4321 if err != nil {
4322 t.Fatal("exec wipe", err)
4323 }
4324
4325 _, err = conn.ExecContext(ctx, "CREATE|keys|v1=string")
4326 if err != nil {
4327 t.Fatal("exec create", err)
4328 }
4329 expectedValue := "value1"
4330 _, err = conn.ExecContext(ctx, "INSERT|keys|v1=?", expectedValue)
4331 if err != nil {
4332 t.Fatal("exec insert", err)
4333 }
4334 rows, err := conn.QueryContext(ctx, "SELECT|keys|v1|")
4335 if err != nil {
4336 t.Fatal("query select", err)
4337 }
4338 v1 := ""
4339 for rows.Next() {
4340 err = rows.Scan(&v1)
4341 if err != nil {
4342 t.Fatal("rows scan", err)
4343 }
4344 }
4345 rows.Close()
4346
4347 if v1 != expectedValue {
4348 t.Fatalf("expected %q, got %q", expectedValue, v1)
4349 }
4350
4351 if !coc.execCtxCalled {
4352 t.Error("ExecContext not called")
4353 }
4354 if !coc.queryCtxCalled {
4355 t.Error("QueryContext not called")
4356 }
4357 }
4358
4359 type alwaysErrScanner struct{}
4360
4361 var errTestScanWrap = errors.New("errTestScanWrap")
4362
4363 func (alwaysErrScanner) Scan(any) error {
4364 return errTestScanWrap
4365 }
4366
4367
4368 func TestRowsScanProperlyWrapsErrors(t *testing.T) {
4369 db := newTestDB(t, "people")
4370 defer closeDB(t, db)
4371
4372 rows, err := db.Query("SELECT|people|age|")
4373 if err != nil {
4374 t.Fatalf("Query: %v", err)
4375 }
4376
4377 var res alwaysErrScanner
4378
4379 for rows.Next() {
4380 err = rows.Scan(&res)
4381 if err == nil {
4382 t.Fatal("expecting back an error")
4383 }
4384 if !errors.Is(err, errTestScanWrap) {
4385 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errTestScanWrap)
4386 }
4387
4388 if !strings.Contains(err.Error(), errTestScanWrap.Error()) {
4389 t.Fatalf("Error %v does not contain %v", err, errTestScanWrap)
4390 }
4391 }
4392 }
4393
4394 type alwaysErrValuer struct{}
4395
4396
4397 var errEmpty = errors.New("empty value")
4398
4399 func (v alwaysErrValuer) Value() (driver.Value, error) {
4400 return nil, errEmpty
4401 }
4402
4403
4404 func TestDriverArgsWrapsErrors(t *testing.T) {
4405 db := newTestDB(t, "people")
4406 defer closeDB(t, db)
4407
4408 t.Run("exec", func(t *testing.T) {
4409 _, err := db.Exec("INSERT|keys|dec1=?", alwaysErrValuer{})
4410 if err == nil {
4411 t.Fatal("expecting back an error")
4412 }
4413 if !errors.Is(err, errEmpty) {
4414 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errEmpty)
4415 }
4416
4417 if !strings.Contains(err.Error(), errEmpty.Error()) {
4418 t.Fatalf("Error %v does not contain %v", err, errEmpty)
4419 }
4420 })
4421
4422 t.Run("query", func(t *testing.T) {
4423 _, err := db.Query("INSERT|keys|dec1=?", alwaysErrValuer{})
4424 if err == nil {
4425 t.Fatal("expecting back an error")
4426 }
4427 if !errors.Is(err, errEmpty) {
4428 t.Fatalf("errors.Is mismatch\n%v\nWant: %v", err, errEmpty)
4429 }
4430
4431 if !strings.Contains(err.Error(), errEmpty.Error()) {
4432 t.Fatalf("Error %v does not contain %v", err, errEmpty)
4433 }
4434 })
4435 }
4436
4437 func TestContextCancelDuringRawBytesScan(t *testing.T) {
4438 for _, mode := range []string{"nocancel", "top", "bottom", "go"} {
4439 t.Run(mode, func(t *testing.T) {
4440 testContextCancelDuringRawBytesScan(t, mode)
4441 })
4442 }
4443 }
4444
4445
4446 func testContextCancelDuringRawBytesScan(t *testing.T, mode string) {
4447 db := newTestDB(t, "people")
4448 defer closeDB(t, db)
4449
4450
4451
4452 ctx, cancel := context.WithCancel(context.Background())
4453 defer cancel()
4454
4455 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4456 if err != nil {
4457 t.Fatal(err)
4458 }
4459 numRows := 0
4460 var sink byte
4461 for r.Next() {
4462 if mode == "top" && numRows == 2 {
4463
4464
4465
4466 cancel()
4467 time.Sleep(100 * time.Millisecond)
4468 }
4469 numRows++
4470 var s RawBytes
4471 err = r.Scan(&s)
4472 if numRows == 3 && err == context.Canceled {
4473 if r.closemuScanHold {
4474 t.Errorf("expected closemu NOT to be held")
4475 }
4476 break
4477 }
4478 if !r.closemuScanHold {
4479 t.Errorf("expected closemu to be held")
4480 }
4481 if err != nil {
4482 t.Fatal(err)
4483 }
4484 t.Logf("read %q", s)
4485 if mode == "bottom" && numRows == 2 {
4486
4487
4488
4489 cancel()
4490 time.Sleep(100 * time.Millisecond)
4491 }
4492 if mode == "go" && numRows == 2 {
4493
4494 go cancel()
4495 }
4496 for _, b := range s {
4497 sink += b
4498 }
4499 }
4500 if r.closemuScanHold {
4501 t.Errorf("closemu held; should not be")
4502 }
4503
4504
4505
4506 switch numRows {
4507 case 0, 1:
4508 t.Errorf("got %d rows; want 2+", numRows)
4509 case 2:
4510 if err := r.Err(); err != context.Canceled {
4511 t.Errorf("unexpected error: %v (%T)", err, err)
4512 }
4513 default:
4514
4515 }
4516
4517 if err := r.Close(); err != nil {
4518 t.Fatal(err)
4519 }
4520 }
4521
4522 func TestContextCancelBetweenNextAndErr(t *testing.T) {
4523 db := newTestDB(t, "people")
4524 defer closeDB(t, db)
4525 ctx, cancel := context.WithCancel(context.Background())
4526 defer cancel()
4527
4528 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4529 if err != nil {
4530 t.Fatal(err)
4531 }
4532 for r.Next() {
4533 }
4534 cancel()
4535 time.Sleep(10 * time.Millisecond)
4536 if err := r.Err(); err != nil {
4537 t.Fatal(err)
4538 }
4539 }
4540
4541 type testScanner struct {
4542 scanf func(src any) error
4543 }
4544
4545 func (ts testScanner) Scan(src any) error { return ts.scanf(src) }
4546
4547 func TestContextCancelDuringScan(t *testing.T) {
4548 db := newTestDB(t, "people")
4549 defer closeDB(t, db)
4550
4551 ctx, cancel := context.WithCancel(context.Background())
4552 defer cancel()
4553
4554 scanStart := make(chan any)
4555 scanEnd := make(chan error)
4556 scanner := &testScanner{
4557 scanf: func(src any) error {
4558 scanStart <- src
4559 return <-scanEnd
4560 },
4561 }
4562
4563
4564 want := []byte("Alice")
4565 r, err := db.QueryContext(ctx, "SELECT|people|name|name=?", string(want))
4566 if err != nil {
4567 t.Fatal(err)
4568 }
4569 if !r.Next() {
4570 t.Fatalf("r.Next() = false, want true")
4571 }
4572 go func() {
4573 r.Scan(scanner)
4574 }()
4575 got := <-scanStart
4576 defer close(scanEnd)
4577 gotBytes, ok := got.([]byte)
4578 if !ok {
4579 t.Fatalf("r.Scan returned %T, want []byte", got)
4580 }
4581 if !bytes.Equal(gotBytes, want) {
4582 t.Fatalf("before cancel: r.Scan returned %q, want %q", gotBytes, want)
4583 }
4584
4585
4586
4587 cancel()
4588 time.Sleep(10 * time.Millisecond)
4589
4590
4591 if !bytes.Equal(gotBytes, want) {
4592 t.Fatalf("after cancel: r.Scan result is now %q, want %q", gotBytes, want)
4593 }
4594 }
4595
4596 func TestNilErrorAfterClose(t *testing.T) {
4597 db := newTestDB(t, "people")
4598 defer closeDB(t, db)
4599
4600
4601
4602
4603 ctx, cancel := context.WithCancel(context.Background())
4604 defer cancel()
4605
4606 r, err := db.QueryContext(ctx, "SELECT|people|name|")
4607 if err != nil {
4608 t.Fatal(err)
4609 }
4610
4611 if err := r.Close(); err != nil {
4612 t.Fatal(err)
4613 }
4614
4615 time.Sleep(10 * time.Millisecond)
4616 if err := r.Err(); err != nil {
4617 t.Fatal(err)
4618 }
4619 }
4620
4621
4622
4623
4624
4625 func TestRawBytesReuse(t *testing.T) {
4626 db := newTestDB(t, "people")
4627 defer closeDB(t, db)
4628
4629 var raw RawBytes
4630
4631
4632 rows, err := db.Query("SELECT|people|name|")
4633 if err != nil {
4634 t.Fatal(err)
4635 }
4636 rows.Next()
4637 rows.Scan(&raw)
4638 name1 := string(raw)
4639 rows.Close()
4640
4641
4642 rows, err = db.Query("SELECT|people|age|")
4643 if err != nil {
4644 t.Fatal(err)
4645 }
4646 rows.Next()
4647 rows.Scan(&raw)
4648 rows.Close()
4649
4650
4651 rows, err = db.Query("SELECT|people|name|")
4652 if err != nil {
4653 t.Fatal(err)
4654 }
4655 rows.Next()
4656 rows.Scan(&raw)
4657 name2 := string(raw)
4658 rows.Close()
4659 if name1 != name2 {
4660 t.Fatalf("Scan read name %q, want %q", name2, name1)
4661 }
4662 }
4663
4664
4665
4666 type badConn struct{}
4667
4668 func (bc badConn) Prepare(query string) (driver.Stmt, error) {
4669 return nil, errors.New("badConn Prepare")
4670 }
4671
4672 func (bc badConn) Close() error {
4673 return nil
4674 }
4675
4676 func (bc badConn) Begin() (driver.Tx, error) {
4677 return nil, errors.New("badConn Begin")
4678 }
4679
4680 func (bc badConn) Exec(query string, args []driver.Value) (driver.Result, error) {
4681 panic("badConn.Exec")
4682 }
4683
4684
4685 type badDriver struct{}
4686
4687 func (bd badDriver) Open(name string) (driver.Conn, error) {
4688 return badConn{}, nil
4689 }
4690
4691
4692 func TestBadDriver(t *testing.T) {
4693 Register("bad", badDriver{})
4694 db, err := Open("bad", "ignored")
4695 if err != nil {
4696 t.Fatal(err)
4697 }
4698 defer func() {
4699 if r := recover(); r == nil {
4700 t.Error("expected panic")
4701 } else {
4702 if want := "badConn.Exec"; r.(string) != want {
4703 t.Errorf("panic was %v, expected %v", r, want)
4704 }
4705 }
4706 }()
4707 defer db.Close()
4708 db.Exec("ignored")
4709 }
4710
4711 type pingDriver struct {
4712 fails bool
4713 }
4714
4715 type pingConn struct {
4716 badConn
4717 driver *pingDriver
4718 }
4719
4720 var pingError = errors.New("Ping failed")
4721
4722 func (pc pingConn) Ping(ctx context.Context) error {
4723 if pc.driver.fails {
4724 return pingError
4725 }
4726 return nil
4727 }
4728
4729 var _ driver.Pinger = pingConn{}
4730
4731 func (pd *pingDriver) Open(name string) (driver.Conn, error) {
4732 return pingConn{driver: pd}, nil
4733 }
4734
4735 func TestPing(t *testing.T) {
4736 driver := &pingDriver{}
4737 Register("ping", driver)
4738
4739 db, err := Open("ping", "ignored")
4740 if err != nil {
4741 t.Fatal(err)
4742 }
4743
4744 if err := db.Ping(); err != nil {
4745 t.Errorf("err was %#v, expected nil", err)
4746 return
4747 }
4748
4749 driver.fails = true
4750 if err := db.Ping(); err != pingError {
4751 t.Errorf("err was %#v, expected pingError", err)
4752 }
4753 }
4754
4755
4756 func TestTypedString(t *testing.T) {
4757 db := newTestDB(t, "people")
4758 defer closeDB(t, db)
4759
4760 type Str string
4761 var scanned Str
4762
4763 err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned)
4764 if err != nil {
4765 t.Fatal(err)
4766 }
4767 expected := Str("Alice")
4768 if scanned != expected {
4769 t.Errorf("expected %+v, got %+v", expected, scanned)
4770 }
4771 }
4772
4773 func BenchmarkConcurrentDBExec(b *testing.B) {
4774 b.ReportAllocs()
4775 ct := new(concurrentDBExecTest)
4776 for i := 0; i < b.N; i++ {
4777 doConcurrentTest(b, ct)
4778 }
4779 }
4780
4781 func BenchmarkConcurrentStmtQuery(b *testing.B) {
4782 b.ReportAllocs()
4783 ct := new(concurrentStmtQueryTest)
4784 for i := 0; i < b.N; i++ {
4785 doConcurrentTest(b, ct)
4786 }
4787 }
4788
4789 func BenchmarkConcurrentStmtExec(b *testing.B) {
4790 b.ReportAllocs()
4791 ct := new(concurrentStmtExecTest)
4792 for i := 0; i < b.N; i++ {
4793 doConcurrentTest(b, ct)
4794 }
4795 }
4796
4797 func BenchmarkConcurrentTxQuery(b *testing.B) {
4798 b.ReportAllocs()
4799 ct := new(concurrentTxQueryTest)
4800 for i := 0; i < b.N; i++ {
4801 doConcurrentTest(b, ct)
4802 }
4803 }
4804
4805 func BenchmarkConcurrentTxExec(b *testing.B) {
4806 b.ReportAllocs()
4807 ct := new(concurrentTxExecTest)
4808 for i := 0; i < b.N; i++ {
4809 doConcurrentTest(b, ct)
4810 }
4811 }
4812
4813 func BenchmarkConcurrentTxStmtQuery(b *testing.B) {
4814 b.ReportAllocs()
4815 ct := new(concurrentTxStmtQueryTest)
4816 for i := 0; i < b.N; i++ {
4817 doConcurrentTest(b, ct)
4818 }
4819 }
4820
4821 func BenchmarkConcurrentTxStmtExec(b *testing.B) {
4822 b.ReportAllocs()
4823 ct := new(concurrentTxStmtExecTest)
4824 for i := 0; i < b.N; i++ {
4825 doConcurrentTest(b, ct)
4826 }
4827 }
4828
4829 func BenchmarkConcurrentRandom(b *testing.B) {
4830 b.ReportAllocs()
4831 ct := new(concurrentRandomTest)
4832 for i := 0; i < b.N; i++ {
4833 doConcurrentTest(b, ct)
4834 }
4835 }
4836
4837 func BenchmarkManyConcurrentQueries(b *testing.B) {
4838 b.ReportAllocs()
4839
4840 const parallelism = 16
4841
4842 db := newTestDB(b, "magicquery")
4843 defer closeDB(b, db)
4844 db.SetMaxIdleConns(runtime.GOMAXPROCS(0) * parallelism)
4845
4846 stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
4847 if err != nil {
4848 b.Fatal(err)
4849 }
4850 defer stmt.Close()
4851
4852 b.SetParallelism(parallelism)
4853 b.RunParallel(func(pb *testing.PB) {
4854 for pb.Next() {
4855 rows, err := stmt.Query("sleep", 1)
4856 if err != nil {
4857 b.Error(err)
4858 return
4859 }
4860 rows.Close()
4861 }
4862 })
4863 }
4864
4865 func TestGrabConnAllocs(t *testing.T) {
4866 testenv.SkipIfOptimizationOff(t)
4867 if race.Enabled {
4868 t.Skip("skipping allocation test when using race detector")
4869 }
4870 c := new(Conn)
4871 ctx := context.Background()
4872 n := int(testing.AllocsPerRun(1000, func() {
4873 _, release, err := c.grabConn(ctx)
4874 if err != nil {
4875 t.Fatal(err)
4876 }
4877 release(nil)
4878 }))
4879 if n > 0 {
4880 t.Fatalf("Conn.grabConn allocated %v objects; want 0", n)
4881 }
4882 }
4883
4884 func BenchmarkGrabConn(b *testing.B) {
4885 b.ReportAllocs()
4886 c := new(Conn)
4887 ctx := context.Background()
4888 for i := 0; i < b.N; i++ {
4889 _, release, err := c.grabConn(ctx)
4890 if err != nil {
4891 b.Fatal(err)
4892 }
4893 release(nil)
4894 }
4895 }
4896
4897 func TestConnRequestSet(t *testing.T) {
4898 var s connRequestSet
4899 wantLen := func(want int) {
4900 t.Helper()
4901 if got := s.Len(); got != want {
4902 t.Errorf("Len = %d; want %d", got, want)
4903 }
4904 if want == 0 && !t.Failed() {
4905 if _, ok := s.TakeRandom(); ok {
4906 t.Fatalf("TakeRandom returned result when empty")
4907 }
4908 }
4909 }
4910 reset := func() { s = connRequestSet{} }
4911
4912 t.Run("add-delete", func(t *testing.T) {
4913 reset()
4914 wantLen(0)
4915 dh := s.Add(nil)
4916 wantLen(1)
4917 if !s.Delete(dh) {
4918 t.Fatal("failed to delete")
4919 }
4920 wantLen(0)
4921 if s.Delete(dh) {
4922 t.Error("delete worked twice")
4923 }
4924 wantLen(0)
4925 })
4926 t.Run("take-before-delete", func(t *testing.T) {
4927 reset()
4928 ch1 := make(chan connRequest)
4929 dh := s.Add(ch1)
4930 wantLen(1)
4931 if got, ok := s.TakeRandom(); !ok || got != ch1 {
4932 t.Fatalf("wrong take; ok=%v", ok)
4933 }
4934 wantLen(0)
4935 if s.Delete(dh) {
4936 t.Error("unexpected delete after take")
4937 }
4938 })
4939 t.Run("get-take-many", func(t *testing.T) {
4940 reset()
4941 m := map[chan connRequest]bool{}
4942 const N = 100
4943 var inOrder, backOut []chan connRequest
4944 for range N {
4945 c := make(chan connRequest)
4946 m[c] = true
4947 s.Add(c)
4948 inOrder = append(inOrder, c)
4949 }
4950 if s.Len() != N {
4951 t.Fatalf("Len = %v; want %v", s.Len(), N)
4952 }
4953 for s.Len() > 0 {
4954 c, ok := s.TakeRandom()
4955 if !ok {
4956 t.Fatal("failed to take when non-empty")
4957 }
4958 if !m[c] {
4959 t.Fatal("returned item not in remaining set")
4960 }
4961 delete(m, c)
4962 backOut = append(backOut, c)
4963 }
4964 if len(m) > 0 {
4965 t.Error("items remain in expected map")
4966 }
4967 if slices.Equal(inOrder, backOut) {
4968 t.Error("wasn't random")
4969 }
4970 })
4971 t.Run("close-delete", func(t *testing.T) {
4972 reset()
4973 ch := make(chan connRequest)
4974 dh := s.Add(ch)
4975 wantLen(1)
4976 s.CloseAndRemoveAll()
4977 wantLen(0)
4978 if s.Delete(dh) {
4979 t.Error("unexpected delete after CloseAndRemoveAll")
4980 }
4981 })
4982 }
4983
4984 func BenchmarkConnRequestSet(b *testing.B) {
4985 var s connRequestSet
4986 for range b.N {
4987 for range 16 {
4988 s.Add(nil)
4989 }
4990 for range 8 {
4991 if _, ok := s.TakeRandom(); !ok {
4992 b.Fatal("want ok")
4993 }
4994 }
4995 for range 8 {
4996 s.Add(nil)
4997 }
4998 for range 16 {
4999 if _, ok := s.TakeRandom(); !ok {
5000 b.Fatal("want ok")
5001 }
5002 }
5003 if _, ok := s.TakeRandom(); ok {
5004 b.Fatal("unexpected ok")
5005 }
5006 }
5007 }
5008
5009 func TestIssue69837(t *testing.T) {
5010 u := Null[uint]{V: 1, Valid: true}
5011 val, err := driver.DefaultParameterConverter.ConvertValue(u)
5012 if err != nil {
5013 t.Errorf("ConvertValue() error = %v, want nil", err)
5014 }
5015
5016 if v, ok := val.(int64); !ok {
5017 t.Errorf("val.(type): got %T, expected int64", val)
5018 } else if v != 1 {
5019 t.Errorf("val: got %d, expected 1", v)
5020 }
5021 }
5022
5023 type issue69728Type struct {
5024 ID int
5025 Name string
5026 }
5027
5028 func (t issue69728Type) Value() (driver.Value, error) {
5029 return []byte(fmt.Sprintf("%d, %s", t.ID, t.Name)), nil
5030 }
5031
5032 func TestIssue69728(t *testing.T) {
5033 forValue := Null[issue69728Type]{
5034 Valid: true,
5035 V: issue69728Type{
5036 ID: 42,
5037 Name: "foobar",
5038 },
5039 }
5040
5041 v1, err := forValue.Value()
5042 if err != nil {
5043 t.Errorf("forValue.Value() error = %v, want nil", err)
5044 }
5045
5046 v2, err := forValue.V.Value()
5047 if err != nil {
5048 t.Errorf("forValue.V.Value() error = %v, want nil", err)
5049 }
5050
5051 if !reflect.DeepEqual(v1, v2) {
5052 t.Errorf("not equal; v1 = %v, v2 = %v", v1, v2)
5053 }
5054 }
5055
View as plain text