1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package sql
17
18 import (
19 "context"
20 "database/sql/driver"
21 "errors"
22 "fmt"
23 "io"
24 "reflect"
25 "runtime"
26 "sort"
27 "strconv"
28 "sync"
29 "sync/atomic"
30 "time"
31 )
32
33 var (
34 driversMu sync.RWMutex
35 drivers = make(map[string]driver.Driver)
36 )
37
38
39 var nowFunc = time.Now
40
41
42
43
44 func Register(name string, driver driver.Driver) {
45 driversMu.Lock()
46 defer driversMu.Unlock()
47 if driver == nil {
48 panic("sql: Register driver is nil")
49 }
50 if _, dup := drivers[name]; dup {
51 panic("sql: Register called twice for driver " + name)
52 }
53 drivers[name] = driver
54 }
55
56 func unregisterAllDrivers() {
57 driversMu.Lock()
58 defer driversMu.Unlock()
59
60 drivers = make(map[string]driver.Driver)
61 }
62
63
64 func Drivers() []string {
65 driversMu.RLock()
66 defer driversMu.RUnlock()
67 list := make([]string, 0, len(drivers))
68 for name := range drivers {
69 list = append(list, name)
70 }
71 sort.Strings(list)
72 return list
73 }
74
75
76
77
78
79
80
81 type NamedArg struct {
82 _NamedFieldsRequired struct{}
83
84
85
86
87
88
89
90 Name string
91
92
93
94
95 Value any
96 }
97
98
99
100
101
102
103
104
105
106
107
108
109
110 func Named(name string, value any) NamedArg {
111
112
113
114
115 return NamedArg{Name: name, Value: value}
116 }
117
118
119 type IsolationLevel int
120
121
122
123
124
125 const (
126 LevelDefault IsolationLevel = iota
127 LevelReadUncommitted
128 LevelReadCommitted
129 LevelWriteCommitted
130 LevelRepeatableRead
131 LevelSnapshot
132 LevelSerializable
133 LevelLinearizable
134 )
135
136
137 func (i IsolationLevel) String() string {
138 switch i {
139 case LevelDefault:
140 return "Default"
141 case LevelReadUncommitted:
142 return "Read Uncommitted"
143 case LevelReadCommitted:
144 return "Read Committed"
145 case LevelWriteCommitted:
146 return "Write Committed"
147 case LevelRepeatableRead:
148 return "Repeatable Read"
149 case LevelSnapshot:
150 return "Snapshot"
151 case LevelSerializable:
152 return "Serializable"
153 case LevelLinearizable:
154 return "Linearizable"
155 default:
156 return "IsolationLevel(" + strconv.Itoa(int(i)) + ")"
157 }
158 }
159
160 var _ fmt.Stringer = LevelDefault
161
162
163 type TxOptions struct {
164
165
166 Isolation IsolationLevel
167 ReadOnly bool
168 }
169
170
171
172
173 type RawBytes []byte
174
175
176
177
178
179
180
181
182
183
184
185
186
187 type NullString struct {
188 String string
189 Valid bool
190 }
191
192
193 func (ns *NullString) Scan(value any) error {
194 if value == nil {
195 ns.String, ns.Valid = "", false
196 return nil
197 }
198 ns.Valid = true
199 return convertAssign(&ns.String, value)
200 }
201
202
203 func (ns NullString) Value() (driver.Value, error) {
204 if !ns.Valid {
205 return nil, nil
206 }
207 return ns.String, nil
208 }
209
210
211
212
213 type NullInt64 struct {
214 Int64 int64
215 Valid bool
216 }
217
218
219 func (n *NullInt64) Scan(value any) error {
220 if value == nil {
221 n.Int64, n.Valid = 0, false
222 return nil
223 }
224 n.Valid = true
225 return convertAssign(&n.Int64, value)
226 }
227
228
229 func (n NullInt64) Value() (driver.Value, error) {
230 if !n.Valid {
231 return nil, nil
232 }
233 return n.Int64, nil
234 }
235
236
237
238
239 type NullInt32 struct {
240 Int32 int32
241 Valid bool
242 }
243
244
245 func (n *NullInt32) Scan(value any) error {
246 if value == nil {
247 n.Int32, n.Valid = 0, false
248 return nil
249 }
250 n.Valid = true
251 return convertAssign(&n.Int32, value)
252 }
253
254
255 func (n NullInt32) Value() (driver.Value, error) {
256 if !n.Valid {
257 return nil, nil
258 }
259 return int64(n.Int32), nil
260 }
261
262
263
264
265 type NullInt16 struct {
266 Int16 int16
267 Valid bool
268 }
269
270
271 func (n *NullInt16) Scan(value any) error {
272 if value == nil {
273 n.Int16, n.Valid = 0, false
274 return nil
275 }
276 err := convertAssign(&n.Int16, value)
277 n.Valid = err == nil
278 return err
279 }
280
281
282 func (n NullInt16) Value() (driver.Value, error) {
283 if !n.Valid {
284 return nil, nil
285 }
286 return int64(n.Int16), nil
287 }
288
289
290
291
292 type NullByte struct {
293 Byte byte
294 Valid bool
295 }
296
297
298 func (n *NullByte) Scan(value any) error {
299 if value == nil {
300 n.Byte, n.Valid = 0, false
301 return nil
302 }
303 err := convertAssign(&n.Byte, value)
304 n.Valid = err == nil
305 return err
306 }
307
308
309 func (n NullByte) Value() (driver.Value, error) {
310 if !n.Valid {
311 return nil, nil
312 }
313 return int64(n.Byte), nil
314 }
315
316
317
318
319 type NullFloat64 struct {
320 Float64 float64
321 Valid bool
322 }
323
324
325 func (n *NullFloat64) Scan(value any) error {
326 if value == nil {
327 n.Float64, n.Valid = 0, false
328 return nil
329 }
330 n.Valid = true
331 return convertAssign(&n.Float64, value)
332 }
333
334
335 func (n NullFloat64) Value() (driver.Value, error) {
336 if !n.Valid {
337 return nil, nil
338 }
339 return n.Float64, nil
340 }
341
342
343
344
345 type NullBool struct {
346 Bool bool
347 Valid bool
348 }
349
350
351 func (n *NullBool) Scan(value any) error {
352 if value == nil {
353 n.Bool, n.Valid = false, false
354 return nil
355 }
356 n.Valid = true
357 return convertAssign(&n.Bool, value)
358 }
359
360
361 func (n NullBool) Value() (driver.Value, error) {
362 if !n.Valid {
363 return nil, nil
364 }
365 return n.Bool, nil
366 }
367
368
369
370
371 type NullTime struct {
372 Time time.Time
373 Valid bool
374 }
375
376
377 func (n *NullTime) Scan(value any) error {
378 if value == nil {
379 n.Time, n.Valid = time.Time{}, false
380 return nil
381 }
382 n.Valid = true
383 return convertAssign(&n.Time, value)
384 }
385
386
387 func (n NullTime) Value() (driver.Value, error) {
388 if !n.Valid {
389 return nil, nil
390 }
391 return n.Time, nil
392 }
393
394
395 type Scanner interface {
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414 Scan(src any) error
415 }
416
417
418
419
420
421
422
423
424
425 type Out struct {
426 _NamedFieldsRequired struct{}
427
428
429
430 Dest any
431
432
433
434
435 In bool
436 }
437
438
439
440
441 var ErrNoRows = errors.New("sql: no rows in result set")
442
443
444
445
446
447
448
449
450
451
452
453
454
455 type DB struct {
456
457 waitDuration atomic.Int64
458
459 connector driver.Connector
460
461
462
463 numClosed atomic.Uint64
464
465 mu sync.Mutex
466 freeConn []*driverConn
467 connRequests map[uint64]chan connRequest
468 nextRequest uint64
469 numOpen int
470
471
472
473
474
475 openerCh chan struct{}
476 closed bool
477 dep map[finalCloser]depSet
478 lastPut map[*driverConn]string
479 maxIdleCount int
480 maxOpen int
481 maxLifetime time.Duration
482 maxIdleTime time.Duration
483 cleanerCh chan struct{}
484 waitCount int64
485 maxIdleClosed int64
486 maxIdleTimeClosed int64
487 maxLifetimeClosed int64
488
489 stop func()
490 }
491
492
493 type connReuseStrategy uint8
494
495 const (
496
497 alwaysNewConn connReuseStrategy = iota
498
499
500
501 cachedOrNewConn
502 )
503
504
505
506
507
508 type driverConn struct {
509 db *DB
510 createdAt time.Time
511
512 sync.Mutex
513 ci driver.Conn
514 needReset bool
515 closed bool
516 finalClosed bool
517 openStmt map[*driverStmt]bool
518
519
520 inUse bool
521 returnedAt time.Time
522 onPut []func()
523 dbmuClosed bool
524 }
525
526 func (dc *driverConn) releaseConn(err error) {
527 dc.db.putConn(dc, err, true)
528 }
529
530 func (dc *driverConn) removeOpenStmt(ds *driverStmt) {
531 dc.Lock()
532 defer dc.Unlock()
533 delete(dc.openStmt, ds)
534 }
535
536 func (dc *driverConn) expired(timeout time.Duration) bool {
537 if timeout <= 0 {
538 return false
539 }
540 return dc.createdAt.Add(timeout).Before(nowFunc())
541 }
542
543
544
545 func (dc *driverConn) resetSession(ctx context.Context) error {
546 dc.Lock()
547 defer dc.Unlock()
548
549 if !dc.needReset {
550 return nil
551 }
552 if cr, ok := dc.ci.(driver.SessionResetter); ok {
553 return cr.ResetSession(ctx)
554 }
555 return nil
556 }
557
558
559
560 func (dc *driverConn) validateConnection(needsReset bool) bool {
561 dc.Lock()
562 defer dc.Unlock()
563
564 if needsReset {
565 dc.needReset = true
566 }
567 if cv, ok := dc.ci.(driver.Validator); ok {
568 return cv.IsValid()
569 }
570 return true
571 }
572
573
574
575 func (dc *driverConn) prepareLocked(ctx context.Context, cg stmtConnGrabber, query string) (*driverStmt, error) {
576 si, err := ctxDriverPrepare(ctx, dc.ci, query)
577 if err != nil {
578 return nil, err
579 }
580 ds := &driverStmt{Locker: dc, si: si}
581
582
583 if cg != nil {
584 return ds, nil
585 }
586
587
588
589
590
591 if dc.openStmt == nil {
592 dc.openStmt = make(map[*driverStmt]bool)
593 }
594 dc.openStmt[ds] = true
595 return ds, nil
596 }
597
598
599 func (dc *driverConn) closeDBLocked() func() error {
600 dc.Lock()
601 defer dc.Unlock()
602 if dc.closed {
603 return func() error { return errors.New("sql: duplicate driverConn close") }
604 }
605 dc.closed = true
606 return dc.db.removeDepLocked(dc, dc)
607 }
608
609 func (dc *driverConn) Close() error {
610 dc.Lock()
611 if dc.closed {
612 dc.Unlock()
613 return errors.New("sql: duplicate driverConn close")
614 }
615 dc.closed = true
616 dc.Unlock()
617
618
619 dc.db.mu.Lock()
620 dc.dbmuClosed = true
621 fn := dc.db.removeDepLocked(dc, dc)
622 dc.db.mu.Unlock()
623 return fn()
624 }
625
626 func (dc *driverConn) finalClose() error {
627 var err error
628
629
630
631 var openStmt []*driverStmt
632 withLock(dc, func() {
633 openStmt = make([]*driverStmt, 0, len(dc.openStmt))
634 for ds := range dc.openStmt {
635 openStmt = append(openStmt, ds)
636 }
637 dc.openStmt = nil
638 })
639 for _, ds := range openStmt {
640 ds.Close()
641 }
642 withLock(dc, func() {
643 dc.finalClosed = true
644 err = dc.ci.Close()
645 dc.ci = nil
646 })
647
648 dc.db.mu.Lock()
649 dc.db.numOpen--
650 dc.db.maybeOpenNewConnections()
651 dc.db.mu.Unlock()
652
653 dc.db.numClosed.Add(1)
654 return err
655 }
656
657
658
659
660 type driverStmt struct {
661 sync.Locker
662 si driver.Stmt
663 closed bool
664 closeErr error
665 }
666
667
668
669 func (ds *driverStmt) Close() error {
670 ds.Lock()
671 defer ds.Unlock()
672 if ds.closed {
673 return ds.closeErr
674 }
675 ds.closed = true
676 ds.closeErr = ds.si.Close()
677 return ds.closeErr
678 }
679
680
681 type depSet map[any]bool
682
683
684
685 type finalCloser interface {
686
687
688 finalClose() error
689 }
690
691
692
693 func (db *DB) addDep(x finalCloser, dep any) {
694 db.mu.Lock()
695 defer db.mu.Unlock()
696 db.addDepLocked(x, dep)
697 }
698
699 func (db *DB) addDepLocked(x finalCloser, dep any) {
700 if db.dep == nil {
701 db.dep = make(map[finalCloser]depSet)
702 }
703 xdep := db.dep[x]
704 if xdep == nil {
705 xdep = make(depSet)
706 db.dep[x] = xdep
707 }
708 xdep[dep] = true
709 }
710
711
712
713
714
715 func (db *DB) removeDep(x finalCloser, dep any) error {
716 db.mu.Lock()
717 fn := db.removeDepLocked(x, dep)
718 db.mu.Unlock()
719 return fn()
720 }
721
722 func (db *DB) removeDepLocked(x finalCloser, dep any) func() error {
723 xdep, ok := db.dep[x]
724 if !ok {
725 panic(fmt.Sprintf("unpaired removeDep: no deps for %T", x))
726 }
727
728 l0 := len(xdep)
729 delete(xdep, dep)
730
731 switch len(xdep) {
732 case l0:
733
734 panic(fmt.Sprintf("unpaired removeDep: no %T dep on %T", dep, x))
735 case 0:
736
737 delete(db.dep, x)
738 return x.finalClose
739 default:
740
741 return func() error { return nil }
742 }
743 }
744
745
746
747
748
749
750 var connectionRequestQueueSize = 1000000
751
752 type dsnConnector struct {
753 dsn string
754 driver driver.Driver
755 }
756
757 func (t dsnConnector) Connect(_ context.Context) (driver.Conn, error) {
758 return t.driver.Open(t.dsn)
759 }
760
761 func (t dsnConnector) Driver() driver.Driver {
762 return t.driver
763 }
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781 func OpenDB(c driver.Connector) *DB {
782 ctx, cancel := context.WithCancel(context.Background())
783 db := &DB{
784 connector: c,
785 openerCh: make(chan struct{}, connectionRequestQueueSize),
786 lastPut: make(map[*driverConn]string),
787 connRequests: make(map[uint64]chan connRequest),
788 stop: cancel,
789 }
790
791 go db.connectionOpener(ctx)
792
793 return db
794 }
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813 func Open(driverName, dataSourceName string) (*DB, error) {
814 driversMu.RLock()
815 driveri, ok := drivers[driverName]
816 driversMu.RUnlock()
817 if !ok {
818 return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
819 }
820
821 if driverCtx, ok := driveri.(driver.DriverContext); ok {
822 connector, err := driverCtx.OpenConnector(dataSourceName)
823 if err != nil {
824 return nil, err
825 }
826 return OpenDB(connector), nil
827 }
828
829 return OpenDB(dsnConnector{dsn: dataSourceName, driver: driveri}), nil
830 }
831
832 func (db *DB) pingDC(ctx context.Context, dc *driverConn, release func(error)) error {
833 var err error
834 if pinger, ok := dc.ci.(driver.Pinger); ok {
835 withLock(dc, func() {
836 err = pinger.Ping(ctx)
837 })
838 }
839 release(err)
840 return err
841 }
842
843
844
845 func (db *DB) PingContext(ctx context.Context) error {
846 var dc *driverConn
847 var err error
848
849 err = db.retry(func(strategy connReuseStrategy) error {
850 dc, err = db.conn(ctx, strategy)
851 return err
852 })
853
854 if err != nil {
855 return err
856 }
857
858 return db.pingDC(ctx, dc, dc.releaseConn)
859 }
860
861
862
863
864
865
866 func (db *DB) Ping() error {
867 return db.PingContext(context.Background())
868 }
869
870
871
872
873
874
875
876 func (db *DB) Close() error {
877 db.mu.Lock()
878 if db.closed {
879 db.mu.Unlock()
880 return nil
881 }
882 if db.cleanerCh != nil {
883 close(db.cleanerCh)
884 }
885 var err error
886 fns := make([]func() error, 0, len(db.freeConn))
887 for _, dc := range db.freeConn {
888 fns = append(fns, dc.closeDBLocked())
889 }
890 db.freeConn = nil
891 db.closed = true
892 for _, req := range db.connRequests {
893 close(req)
894 }
895 db.mu.Unlock()
896 for _, fn := range fns {
897 err1 := fn()
898 if err1 != nil {
899 err = err1
900 }
901 }
902 db.stop()
903 if c, ok := db.connector.(io.Closer); ok {
904 err1 := c.Close()
905 if err1 != nil {
906 err = err1
907 }
908 }
909 return err
910 }
911
912 const defaultMaxIdleConns = 2
913
914 func (db *DB) maxIdleConnsLocked() int {
915 n := db.maxIdleCount
916 switch {
917 case n == 0:
918
919 return defaultMaxIdleConns
920 case n < 0:
921 return 0
922 default:
923 return n
924 }
925 }
926
927 func (db *DB) shortestIdleTimeLocked() time.Duration {
928 if db.maxIdleTime <= 0 {
929 return db.maxLifetime
930 }
931 if db.maxLifetime <= 0 {
932 return db.maxIdleTime
933 }
934
935 min := db.maxIdleTime
936 if min > db.maxLifetime {
937 min = db.maxLifetime
938 }
939 return min
940 }
941
942
943
944
945
946
947
948
949
950
951
952 func (db *DB) SetMaxIdleConns(n int) {
953 db.mu.Lock()
954 if n > 0 {
955 db.maxIdleCount = n
956 } else {
957
958 db.maxIdleCount = -1
959 }
960
961 if db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen {
962 db.maxIdleCount = db.maxOpen
963 }
964 var closing []*driverConn
965 idleCount := len(db.freeConn)
966 maxIdle := db.maxIdleConnsLocked()
967 if idleCount > maxIdle {
968 closing = db.freeConn[maxIdle:]
969 db.freeConn = db.freeConn[:maxIdle]
970 }
971 db.maxIdleClosed += int64(len(closing))
972 db.mu.Unlock()
973 for _, c := range closing {
974 c.Close()
975 }
976 }
977
978
979
980
981
982
983
984
985
986 func (db *DB) SetMaxOpenConns(n int) {
987 db.mu.Lock()
988 db.maxOpen = n
989 if n < 0 {
990 db.maxOpen = 0
991 }
992 syncMaxIdle := db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen
993 db.mu.Unlock()
994 if syncMaxIdle {
995 db.SetMaxIdleConns(n)
996 }
997 }
998
999
1000
1001
1002
1003
1004 func (db *DB) SetConnMaxLifetime(d time.Duration) {
1005 if d < 0 {
1006 d = 0
1007 }
1008 db.mu.Lock()
1009
1010 if d > 0 && d < db.maxLifetime && db.cleanerCh != nil {
1011 select {
1012 case db.cleanerCh <- struct{}{}:
1013 default:
1014 }
1015 }
1016 db.maxLifetime = d
1017 db.startCleanerLocked()
1018 db.mu.Unlock()
1019 }
1020
1021
1022
1023
1024
1025
1026 func (db *DB) SetConnMaxIdleTime(d time.Duration) {
1027 if d < 0 {
1028 d = 0
1029 }
1030 db.mu.Lock()
1031 defer db.mu.Unlock()
1032
1033
1034 if d > 0 && d < db.maxIdleTime && db.cleanerCh != nil {
1035 select {
1036 case db.cleanerCh <- struct{}{}:
1037 default:
1038 }
1039 }
1040 db.maxIdleTime = d
1041 db.startCleanerLocked()
1042 }
1043
1044
1045 func (db *DB) startCleanerLocked() {
1046 if (db.maxLifetime > 0 || db.maxIdleTime > 0) && db.numOpen > 0 && db.cleanerCh == nil {
1047 db.cleanerCh = make(chan struct{}, 1)
1048 go db.connectionCleaner(db.shortestIdleTimeLocked())
1049 }
1050 }
1051
1052 func (db *DB) connectionCleaner(d time.Duration) {
1053 const minInterval = time.Second
1054
1055 if d < minInterval {
1056 d = minInterval
1057 }
1058 t := time.NewTimer(d)
1059
1060 for {
1061 select {
1062 case <-t.C:
1063 case <-db.cleanerCh:
1064 }
1065
1066 db.mu.Lock()
1067
1068 d = db.shortestIdleTimeLocked()
1069 if db.closed || db.numOpen == 0 || d <= 0 {
1070 db.cleanerCh = nil
1071 db.mu.Unlock()
1072 return
1073 }
1074
1075 d, closing := db.connectionCleanerRunLocked(d)
1076 db.mu.Unlock()
1077 for _, c := range closing {
1078 c.Close()
1079 }
1080
1081 if d < minInterval {
1082 d = minInterval
1083 }
1084
1085 if !t.Stop() {
1086 select {
1087 case <-t.C:
1088 default:
1089 }
1090 }
1091 t.Reset(d)
1092 }
1093 }
1094
1095
1096
1097
1098 func (db *DB) connectionCleanerRunLocked(d time.Duration) (time.Duration, []*driverConn) {
1099 var idleClosing int64
1100 var closing []*driverConn
1101 if db.maxIdleTime > 0 {
1102
1103
1104 idleSince := nowFunc().Add(-db.maxIdleTime)
1105 last := len(db.freeConn) - 1
1106 for i := last; i >= 0; i-- {
1107 c := db.freeConn[i]
1108 if c.returnedAt.Before(idleSince) {
1109 i++
1110 closing = db.freeConn[:i:i]
1111 db.freeConn = db.freeConn[i:]
1112 idleClosing = int64(len(closing))
1113 db.maxIdleTimeClosed += idleClosing
1114 break
1115 }
1116 }
1117
1118 if len(db.freeConn) > 0 {
1119 c := db.freeConn[0]
1120 if d2 := c.returnedAt.Sub(idleSince); d2 < d {
1121
1122
1123 d = d2
1124 }
1125 }
1126 }
1127
1128 if db.maxLifetime > 0 {
1129 expiredSince := nowFunc().Add(-db.maxLifetime)
1130 for i := 0; i < len(db.freeConn); i++ {
1131 c := db.freeConn[i]
1132 if c.createdAt.Before(expiredSince) {
1133 closing = append(closing, c)
1134
1135 last := len(db.freeConn) - 1
1136
1137
1138 copy(db.freeConn[i:], db.freeConn[i+1:])
1139 db.freeConn[last] = nil
1140 db.freeConn = db.freeConn[:last]
1141 i--
1142 } else if d2 := c.createdAt.Sub(expiredSince); d2 < d {
1143
1144
1145 d = d2
1146 }
1147 }
1148 db.maxLifetimeClosed += int64(len(closing)) - idleClosing
1149 }
1150
1151 return d, closing
1152 }
1153
1154
1155 type DBStats struct {
1156 MaxOpenConnections int
1157
1158
1159 OpenConnections int
1160 InUse int
1161 Idle int
1162
1163
1164 WaitCount int64
1165 WaitDuration time.Duration
1166 MaxIdleClosed int64
1167 MaxIdleTimeClosed int64
1168 MaxLifetimeClosed int64
1169 }
1170
1171
1172 func (db *DB) Stats() DBStats {
1173 wait := db.waitDuration.Load()
1174
1175 db.mu.Lock()
1176 defer db.mu.Unlock()
1177
1178 stats := DBStats{
1179 MaxOpenConnections: db.maxOpen,
1180
1181 Idle: len(db.freeConn),
1182 OpenConnections: db.numOpen,
1183 InUse: db.numOpen - len(db.freeConn),
1184
1185 WaitCount: db.waitCount,
1186 WaitDuration: time.Duration(wait),
1187 MaxIdleClosed: db.maxIdleClosed,
1188 MaxIdleTimeClosed: db.maxIdleTimeClosed,
1189 MaxLifetimeClosed: db.maxLifetimeClosed,
1190 }
1191 return stats
1192 }
1193
1194
1195
1196
1197 func (db *DB) maybeOpenNewConnections() {
1198 numRequests := len(db.connRequests)
1199 if db.maxOpen > 0 {
1200 numCanOpen := db.maxOpen - db.numOpen
1201 if numRequests > numCanOpen {
1202 numRequests = numCanOpen
1203 }
1204 }
1205 for numRequests > 0 {
1206 db.numOpen++
1207 numRequests--
1208 if db.closed {
1209 return
1210 }
1211 db.openerCh <- struct{}{}
1212 }
1213 }
1214
1215
1216 func (db *DB) connectionOpener(ctx context.Context) {
1217 for {
1218 select {
1219 case <-ctx.Done():
1220 return
1221 case <-db.openerCh:
1222 db.openNewConnection(ctx)
1223 }
1224 }
1225 }
1226
1227
1228 func (db *DB) openNewConnection(ctx context.Context) {
1229
1230
1231
1232 ci, err := db.connector.Connect(ctx)
1233 db.mu.Lock()
1234 defer db.mu.Unlock()
1235 if db.closed {
1236 if err == nil {
1237 ci.Close()
1238 }
1239 db.numOpen--
1240 return
1241 }
1242 if err != nil {
1243 db.numOpen--
1244 db.putConnDBLocked(nil, err)
1245 db.maybeOpenNewConnections()
1246 return
1247 }
1248 dc := &driverConn{
1249 db: db,
1250 createdAt: nowFunc(),
1251 returnedAt: nowFunc(),
1252 ci: ci,
1253 }
1254 if db.putConnDBLocked(dc, err) {
1255 db.addDepLocked(dc, dc)
1256 } else {
1257 db.numOpen--
1258 ci.Close()
1259 }
1260 }
1261
1262
1263
1264
1265 type connRequest struct {
1266 conn *driverConn
1267 err error
1268 }
1269
1270 var errDBClosed = errors.New("sql: database is closed")
1271
1272
1273
1274 func (db *DB) nextRequestKeyLocked() uint64 {
1275 next := db.nextRequest
1276 db.nextRequest++
1277 return next
1278 }
1279
1280
1281 func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn, error) {
1282 db.mu.Lock()
1283 if db.closed {
1284 db.mu.Unlock()
1285 return nil, errDBClosed
1286 }
1287
1288 select {
1289 default:
1290 case <-ctx.Done():
1291 db.mu.Unlock()
1292 return nil, ctx.Err()
1293 }
1294 lifetime := db.maxLifetime
1295
1296
1297 last := len(db.freeConn) - 1
1298 if strategy == cachedOrNewConn && last >= 0 {
1299
1300
1301 conn := db.freeConn[last]
1302 db.freeConn = db.freeConn[:last]
1303 conn.inUse = true
1304 if conn.expired(lifetime) {
1305 db.maxLifetimeClosed++
1306 db.mu.Unlock()
1307 conn.Close()
1308 return nil, driver.ErrBadConn
1309 }
1310 db.mu.Unlock()
1311
1312
1313 if err := conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) {
1314 conn.Close()
1315 return nil, err
1316 }
1317
1318 return conn, nil
1319 }
1320
1321
1322
1323 if db.maxOpen > 0 && db.numOpen >= db.maxOpen {
1324
1325
1326 req := make(chan connRequest, 1)
1327 reqKey := db.nextRequestKeyLocked()
1328 db.connRequests[reqKey] = req
1329 db.waitCount++
1330 db.mu.Unlock()
1331
1332 waitStart := nowFunc()
1333
1334
1335 select {
1336 case <-ctx.Done():
1337
1338
1339 db.mu.Lock()
1340 delete(db.connRequests, reqKey)
1341 db.mu.Unlock()
1342
1343 db.waitDuration.Add(int64(time.Since(waitStart)))
1344
1345 select {
1346 default:
1347 case ret, ok := <-req:
1348 if ok && ret.conn != nil {
1349 db.putConn(ret.conn, ret.err, false)
1350 }
1351 }
1352 return nil, ctx.Err()
1353 case ret, ok := <-req:
1354 db.waitDuration.Add(int64(time.Since(waitStart)))
1355
1356 if !ok {
1357 return nil, errDBClosed
1358 }
1359
1360
1361
1362
1363
1364
1365 if strategy == cachedOrNewConn && ret.err == nil && ret.conn.expired(lifetime) {
1366 db.mu.Lock()
1367 db.maxLifetimeClosed++
1368 db.mu.Unlock()
1369 ret.conn.Close()
1370 return nil, driver.ErrBadConn
1371 }
1372 if ret.conn == nil {
1373 return nil, ret.err
1374 }
1375
1376
1377 if err := ret.conn.resetSession(ctx); errors.Is(err, driver.ErrBadConn) {
1378 ret.conn.Close()
1379 return nil, err
1380 }
1381 return ret.conn, ret.err
1382 }
1383 }
1384
1385 db.numOpen++
1386 db.mu.Unlock()
1387 ci, err := db.connector.Connect(ctx)
1388 if err != nil {
1389 db.mu.Lock()
1390 db.numOpen--
1391 db.maybeOpenNewConnections()
1392 db.mu.Unlock()
1393 return nil, err
1394 }
1395 db.mu.Lock()
1396 dc := &driverConn{
1397 db: db,
1398 createdAt: nowFunc(),
1399 returnedAt: nowFunc(),
1400 ci: ci,
1401 inUse: true,
1402 }
1403 db.addDepLocked(dc, dc)
1404 db.mu.Unlock()
1405 return dc, nil
1406 }
1407
1408
1409 var putConnHook func(*DB, *driverConn)
1410
1411
1412
1413
1414 func (db *DB) noteUnusedDriverStatement(c *driverConn, ds *driverStmt) {
1415 db.mu.Lock()
1416 defer db.mu.Unlock()
1417 if c.inUse {
1418 c.onPut = append(c.onPut, func() {
1419 ds.Close()
1420 })
1421 } else {
1422 c.Lock()
1423 fc := c.finalClosed
1424 c.Unlock()
1425 if !fc {
1426 ds.Close()
1427 }
1428 }
1429 }
1430
1431
1432
1433 const debugGetPut = false
1434
1435
1436
1437 func (db *DB) putConn(dc *driverConn, err error, resetSession bool) {
1438 if !errors.Is(err, driver.ErrBadConn) {
1439 if !dc.validateConnection(resetSession) {
1440 err = driver.ErrBadConn
1441 }
1442 }
1443 db.mu.Lock()
1444 if !dc.inUse {
1445 db.mu.Unlock()
1446 if debugGetPut {
1447 fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", dc, stack(), db.lastPut[dc])
1448 }
1449 panic("sql: connection returned that was never out")
1450 }
1451
1452 if !errors.Is(err, driver.ErrBadConn) && dc.expired(db.maxLifetime) {
1453 db.maxLifetimeClosed++
1454 err = driver.ErrBadConn
1455 }
1456 if debugGetPut {
1457 db.lastPut[dc] = stack()
1458 }
1459 dc.inUse = false
1460 dc.returnedAt = nowFunc()
1461
1462 for _, fn := range dc.onPut {
1463 fn()
1464 }
1465 dc.onPut = nil
1466
1467 if errors.Is(err, driver.ErrBadConn) {
1468
1469
1470
1471
1472 db.maybeOpenNewConnections()
1473 db.mu.Unlock()
1474 dc.Close()
1475 return
1476 }
1477 if putConnHook != nil {
1478 putConnHook(db, dc)
1479 }
1480 added := db.putConnDBLocked(dc, nil)
1481 db.mu.Unlock()
1482
1483 if !added {
1484 dc.Close()
1485 return
1486 }
1487 }
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498 func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
1499 if db.closed {
1500 return false
1501 }
1502 if db.maxOpen > 0 && db.numOpen > db.maxOpen {
1503 return false
1504 }
1505 if c := len(db.connRequests); c > 0 {
1506 var req chan connRequest
1507 var reqKey uint64
1508 for reqKey, req = range db.connRequests {
1509 break
1510 }
1511 delete(db.connRequests, reqKey)
1512 if err == nil {
1513 dc.inUse = true
1514 }
1515 req <- connRequest{
1516 conn: dc,
1517 err: err,
1518 }
1519 return true
1520 } else if err == nil && !db.closed {
1521 if db.maxIdleConnsLocked() > len(db.freeConn) {
1522 db.freeConn = append(db.freeConn, dc)
1523 db.startCleanerLocked()
1524 return true
1525 }
1526 db.maxIdleClosed++
1527 }
1528 return false
1529 }
1530
1531
1532
1533
1534 const maxBadConnRetries = 2
1535
1536 func (db *DB) retry(fn func(strategy connReuseStrategy) error) error {
1537 for i := int64(0); i < maxBadConnRetries; i++ {
1538 err := fn(cachedOrNewConn)
1539
1540 if err == nil || !errors.Is(err, driver.ErrBadConn) {
1541 return err
1542 }
1543 }
1544
1545 return fn(alwaysNewConn)
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556 func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
1557 var stmt *Stmt
1558 var err error
1559
1560 err = db.retry(func(strategy connReuseStrategy) error {
1561 stmt, err = db.prepare(ctx, query, strategy)
1562 return err
1563 })
1564
1565 return stmt, err
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576 func (db *DB) Prepare(query string) (*Stmt, error) {
1577 return db.PrepareContext(context.Background(), query)
1578 }
1579
1580 func (db *DB) prepare(ctx context.Context, query string, strategy connReuseStrategy) (*Stmt, error) {
1581
1582
1583
1584
1585
1586
1587 dc, err := db.conn(ctx, strategy)
1588 if err != nil {
1589 return nil, err
1590 }
1591 return db.prepareDC(ctx, dc, dc.releaseConn, nil, query)
1592 }
1593
1594
1595
1596
1597 func (db *DB) prepareDC(ctx context.Context, dc *driverConn, release func(error), cg stmtConnGrabber, query string) (*Stmt, error) {
1598 var ds *driverStmt
1599 var err error
1600 defer func() {
1601 release(err)
1602 }()
1603 withLock(dc, func() {
1604 ds, err = dc.prepareLocked(ctx, cg, query)
1605 })
1606 if err != nil {
1607 return nil, err
1608 }
1609 stmt := &Stmt{
1610 db: db,
1611 query: query,
1612 cg: cg,
1613 cgds: ds,
1614 }
1615
1616
1617
1618
1619 if cg == nil {
1620 stmt.css = []connStmt{{dc, ds}}
1621 stmt.lastNumClosed = db.numClosed.Load()
1622 db.addDep(stmt, stmt)
1623 }
1624 return stmt, nil
1625 }
1626
1627
1628
1629 func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error) {
1630 var res Result
1631 var err error
1632
1633 err = db.retry(func(strategy connReuseStrategy) error {
1634 res, err = db.exec(ctx, query, args, strategy)
1635 return err
1636 })
1637
1638 return res, err
1639 }
1640
1641
1642
1643
1644
1645
1646 func (db *DB) Exec(query string, args ...any) (Result, error) {
1647 return db.ExecContext(context.Background(), query, args...)
1648 }
1649
1650 func (db *DB) exec(ctx context.Context, query string, args []any, strategy connReuseStrategy) (Result, error) {
1651 dc, err := db.conn(ctx, strategy)
1652 if err != nil {
1653 return nil, err
1654 }
1655 return db.execDC(ctx, dc, dc.releaseConn, query, args)
1656 }
1657
1658 func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), query string, args []any) (res Result, err error) {
1659 defer func() {
1660 release(err)
1661 }()
1662 execerCtx, ok := dc.ci.(driver.ExecerContext)
1663 var execer driver.Execer
1664 if !ok {
1665 execer, ok = dc.ci.(driver.Execer)
1666 }
1667 if ok {
1668 var nvdargs []driver.NamedValue
1669 var resi driver.Result
1670 withLock(dc, func() {
1671 nvdargs, err = driverArgsConnLocked(dc.ci, nil, args)
1672 if err != nil {
1673 return
1674 }
1675 resi, err = ctxDriverExec(ctx, execerCtx, execer, query, nvdargs)
1676 })
1677 if err != driver.ErrSkip {
1678 if err != nil {
1679 return nil, err
1680 }
1681 return driverResult{dc, resi}, nil
1682 }
1683 }
1684
1685 var si driver.Stmt
1686 withLock(dc, func() {
1687 si, err = ctxDriverPrepare(ctx, dc.ci, query)
1688 })
1689 if err != nil {
1690 return nil, err
1691 }
1692 ds := &driverStmt{Locker: dc, si: si}
1693 defer ds.Close()
1694 return resultFromStatement(ctx, dc.ci, ds, args...)
1695 }
1696
1697
1698
1699 func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) {
1700 var rows *Rows
1701 var err error
1702
1703 err = db.retry(func(strategy connReuseStrategy) error {
1704 rows, err = db.query(ctx, query, args, strategy)
1705 return err
1706 })
1707
1708 return rows, err
1709 }
1710
1711
1712
1713
1714
1715
1716 func (db *DB) Query(query string, args ...any) (*Rows, error) {
1717 return db.QueryContext(context.Background(), query, args...)
1718 }
1719
1720 func (db *DB) query(ctx context.Context, query string, args []any, strategy connReuseStrategy) (*Rows, error) {
1721 dc, err := db.conn(ctx, strategy)
1722 if err != nil {
1723 return nil, err
1724 }
1725
1726 return db.queryDC(ctx, nil, dc, dc.releaseConn, query, args)
1727 }
1728
1729
1730
1731
1732
1733 func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) (*Rows, error) {
1734 queryerCtx, ok := dc.ci.(driver.QueryerContext)
1735 var queryer driver.Queryer
1736 if !ok {
1737 queryer, ok = dc.ci.(driver.Queryer)
1738 }
1739 if ok {
1740 var nvdargs []driver.NamedValue
1741 var rowsi driver.Rows
1742 var err error
1743 withLock(dc, func() {
1744 nvdargs, err = driverArgsConnLocked(dc.ci, nil, args)
1745 if err != nil {
1746 return
1747 }
1748 rowsi, err = ctxDriverQuery(ctx, queryerCtx, queryer, query, nvdargs)
1749 })
1750 if err != driver.ErrSkip {
1751 if err != nil {
1752 releaseConn(err)
1753 return nil, err
1754 }
1755
1756
1757 rows := &Rows{
1758 dc: dc,
1759 releaseConn: releaseConn,
1760 rowsi: rowsi,
1761 }
1762 rows.initContextClose(ctx, txctx)
1763 return rows, nil
1764 }
1765 }
1766
1767 var si driver.Stmt
1768 var err error
1769 withLock(dc, func() {
1770 si, err = ctxDriverPrepare(ctx, dc.ci, query)
1771 })
1772 if err != nil {
1773 releaseConn(err)
1774 return nil, err
1775 }
1776
1777 ds := &driverStmt{Locker: dc, si: si}
1778 rowsi, err := rowsiFromStatement(ctx, dc.ci, ds, args...)
1779 if err != nil {
1780 ds.Close()
1781 releaseConn(err)
1782 return nil, err
1783 }
1784
1785
1786
1787 rows := &Rows{
1788 dc: dc,
1789 releaseConn: releaseConn,
1790 rowsi: rowsi,
1791 closeStmt: ds,
1792 }
1793 rows.initContextClose(ctx, txctx)
1794 return rows, nil
1795 }
1796
1797
1798
1799
1800
1801
1802
1803 func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row {
1804 rows, err := db.QueryContext(ctx, query, args...)
1805 return &Row{rows: rows, err: err}
1806 }
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817 func (db *DB) QueryRow(query string, args ...any) *Row {
1818 return db.QueryRowContext(context.Background(), query, args...)
1819 }
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831 func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
1832 var tx *Tx
1833 var err error
1834
1835 err = db.retry(func(strategy connReuseStrategy) error {
1836 tx, err = db.begin(ctx, opts, strategy)
1837 return err
1838 })
1839
1840 return tx, err
1841 }
1842
1843
1844
1845
1846
1847
1848 func (db *DB) Begin() (*Tx, error) {
1849 return db.BeginTx(context.Background(), nil)
1850 }
1851
1852 func (db *DB) begin(ctx context.Context, opts *TxOptions, strategy connReuseStrategy) (tx *Tx, err error) {
1853 dc, err := db.conn(ctx, strategy)
1854 if err != nil {
1855 return nil, err
1856 }
1857 return db.beginDC(ctx, dc, dc.releaseConn, opts)
1858 }
1859
1860
1861 func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error), opts *TxOptions) (tx *Tx, err error) {
1862 var txi driver.Tx
1863 keepConnOnRollback := false
1864 withLock(dc, func() {
1865 _, hasSessionResetter := dc.ci.(driver.SessionResetter)
1866 _, hasConnectionValidator := dc.ci.(driver.Validator)
1867 keepConnOnRollback = hasSessionResetter && hasConnectionValidator
1868 txi, err = ctxDriverBegin(ctx, opts, dc.ci)
1869 })
1870 if err != nil {
1871 release(err)
1872 return nil, err
1873 }
1874
1875
1876
1877 ctx, cancel := context.WithCancel(ctx)
1878 tx = &Tx{
1879 db: db,
1880 dc: dc,
1881 releaseConn: release,
1882 txi: txi,
1883 cancel: cancel,
1884 keepConnOnRollback: keepConnOnRollback,
1885 ctx: ctx,
1886 }
1887 go tx.awaitDone()
1888 return tx, nil
1889 }
1890
1891
1892 func (db *DB) Driver() driver.Driver {
1893 return db.connector.Driver()
1894 }
1895
1896
1897
1898 var ErrConnDone = errors.New("sql: connection is already closed")
1899
1900
1901
1902
1903
1904
1905
1906
1907 func (db *DB) Conn(ctx context.Context) (*Conn, error) {
1908 var dc *driverConn
1909 var err error
1910
1911 err = db.retry(func(strategy connReuseStrategy) error {
1912 dc, err = db.conn(ctx, strategy)
1913 return err
1914 })
1915
1916 if err != nil {
1917 return nil, err
1918 }
1919
1920 conn := &Conn{
1921 db: db,
1922 dc: dc,
1923 }
1924 return conn, nil
1925 }
1926
1927 type releaseConn func(error)
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938 type Conn struct {
1939 db *DB
1940
1941
1942
1943
1944 closemu sync.RWMutex
1945
1946
1947
1948 dc *driverConn
1949
1950
1951
1952
1953 done int32
1954 }
1955
1956
1957
1958 func (c *Conn) grabConn(context.Context) (*driverConn, releaseConn, error) {
1959 if atomic.LoadInt32(&c.done) != 0 {
1960 return nil, nil, ErrConnDone
1961 }
1962 c.closemu.RLock()
1963 return c.dc, c.closemuRUnlockCondReleaseConn, nil
1964 }
1965
1966
1967 func (c *Conn) PingContext(ctx context.Context) error {
1968 dc, release, err := c.grabConn(ctx)
1969 if err != nil {
1970 return err
1971 }
1972 return c.db.pingDC(ctx, dc, release)
1973 }
1974
1975
1976
1977 func (c *Conn) ExecContext(ctx context.Context, query string, args ...any) (Result, error) {
1978 dc, release, err := c.grabConn(ctx)
1979 if err != nil {
1980 return nil, err
1981 }
1982 return c.db.execDC(ctx, dc, release, query, args)
1983 }
1984
1985
1986
1987 func (c *Conn) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) {
1988 dc, release, err := c.grabConn(ctx)
1989 if err != nil {
1990 return nil, err
1991 }
1992 return c.db.queryDC(ctx, nil, dc, release, query, args)
1993 }
1994
1995
1996
1997
1998
1999
2000
2001 func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...any) *Row {
2002 rows, err := c.QueryContext(ctx, query, args...)
2003 return &Row{rows: rows, err: err}
2004 }
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
2015 dc, release, err := c.grabConn(ctx)
2016 if err != nil {
2017 return nil, err
2018 }
2019 return c.db.prepareDC(ctx, dc, release, c, query)
2020 }
2021
2022
2023
2024
2025
2026
2027 func (c *Conn) Raw(f func(driverConn any) error) (err error) {
2028 var dc *driverConn
2029 var release releaseConn
2030
2031
2032 dc, release, err = c.grabConn(nil)
2033 if err != nil {
2034 return
2035 }
2036 fPanic := true
2037 dc.Mutex.Lock()
2038 defer func() {
2039 dc.Mutex.Unlock()
2040
2041
2042
2043
2044 if fPanic {
2045 err = driver.ErrBadConn
2046 }
2047 release(err)
2048 }()
2049 err = f(dc.ci)
2050 fPanic = false
2051
2052 return
2053 }
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065 func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
2066 dc, release, err := c.grabConn(ctx)
2067 if err != nil {
2068 return nil, err
2069 }
2070 return c.db.beginDC(ctx, dc, release, opts)
2071 }
2072
2073
2074
2075 func (c *Conn) closemuRUnlockCondReleaseConn(err error) {
2076 c.closemu.RUnlock()
2077 if errors.Is(err, driver.ErrBadConn) {
2078 c.close(err)
2079 }
2080 }
2081
2082 func (c *Conn) txCtx() context.Context {
2083 return nil
2084 }
2085
2086 func (c *Conn) close(err error) error {
2087 if !atomic.CompareAndSwapInt32(&c.done, 0, 1) {
2088 return ErrConnDone
2089 }
2090
2091
2092
2093 c.closemu.Lock()
2094 defer c.closemu.Unlock()
2095
2096 c.dc.releaseConn(err)
2097 c.dc = nil
2098 c.db = nil
2099 return err
2100 }
2101
2102
2103
2104
2105
2106
2107 func (c *Conn) Close() error {
2108 return c.close(nil)
2109 }
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121 type Tx struct {
2122 db *DB
2123
2124
2125
2126
2127 closemu sync.RWMutex
2128
2129
2130
2131 dc *driverConn
2132 txi driver.Tx
2133
2134
2135
2136 releaseConn func(error)
2137
2138
2139
2140
2141 done atomic.Bool
2142
2143
2144
2145
2146 keepConnOnRollback bool
2147
2148
2149
2150 stmts struct {
2151 sync.Mutex
2152 v []*Stmt
2153 }
2154
2155
2156 cancel func()
2157
2158
2159 ctx context.Context
2160 }
2161
2162
2163
2164 func (tx *Tx) awaitDone() {
2165
2166
2167 <-tx.ctx.Done()
2168
2169
2170
2171
2172
2173
2174
2175 discardConnection := !tx.keepConnOnRollback
2176 tx.rollback(discardConnection)
2177 }
2178
2179 func (tx *Tx) isDone() bool {
2180 return tx.done.Load()
2181 }
2182
2183
2184
2185 var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back")
2186
2187
2188
2189
2190 func (tx *Tx) close(err error) {
2191 tx.releaseConn(err)
2192 tx.dc = nil
2193 tx.txi = nil
2194 }
2195
2196
2197
2198 var hookTxGrabConn func()
2199
2200 func (tx *Tx) grabConn(ctx context.Context) (*driverConn, releaseConn, error) {
2201 select {
2202 default:
2203 case <-ctx.Done():
2204 return nil, nil, ctx.Err()
2205 }
2206
2207
2208
2209 tx.closemu.RLock()
2210 if tx.isDone() {
2211 tx.closemu.RUnlock()
2212 return nil, nil, ErrTxDone
2213 }
2214 if hookTxGrabConn != nil {
2215 hookTxGrabConn()
2216 }
2217 return tx.dc, tx.closemuRUnlockRelease, nil
2218 }
2219
2220 func (tx *Tx) txCtx() context.Context {
2221 return tx.ctx
2222 }
2223
2224
2225
2226
2227
2228 func (tx *Tx) closemuRUnlockRelease(error) {
2229 tx.closemu.RUnlock()
2230 }
2231
2232
2233 func (tx *Tx) closePrepared() {
2234 tx.stmts.Lock()
2235 defer tx.stmts.Unlock()
2236 for _, stmt := range tx.stmts.v {
2237 stmt.Close()
2238 }
2239 }
2240
2241
2242 func (tx *Tx) Commit() error {
2243
2244
2245
2246 select {
2247 default:
2248 case <-tx.ctx.Done():
2249 if tx.done.Load() {
2250 return ErrTxDone
2251 }
2252 return tx.ctx.Err()
2253 }
2254 if !tx.done.CompareAndSwap(false, true) {
2255 return ErrTxDone
2256 }
2257
2258
2259
2260
2261
2262 tx.cancel()
2263 tx.closemu.Lock()
2264 tx.closemu.Unlock()
2265
2266 var err error
2267 withLock(tx.dc, func() {
2268 err = tx.txi.Commit()
2269 })
2270 if !errors.Is(err, driver.ErrBadConn) {
2271 tx.closePrepared()
2272 }
2273 tx.close(err)
2274 return err
2275 }
2276
2277 var rollbackHook func()
2278
2279
2280
2281 func (tx *Tx) rollback(discardConn bool) error {
2282 if !tx.done.CompareAndSwap(false, true) {
2283 return ErrTxDone
2284 }
2285
2286 if rollbackHook != nil {
2287 rollbackHook()
2288 }
2289
2290
2291
2292
2293
2294 tx.cancel()
2295 tx.closemu.Lock()
2296 tx.closemu.Unlock()
2297
2298 var err error
2299 withLock(tx.dc, func() {
2300 err = tx.txi.Rollback()
2301 })
2302 if !errors.Is(err, driver.ErrBadConn) {
2303 tx.closePrepared()
2304 }
2305 if discardConn {
2306 err = driver.ErrBadConn
2307 }
2308 tx.close(err)
2309 return err
2310 }
2311
2312
2313 func (tx *Tx) Rollback() error {
2314 return tx.rollback(false)
2315 }
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327 func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
2328 dc, release, err := tx.grabConn(ctx)
2329 if err != nil {
2330 return nil, err
2331 }
2332
2333 stmt, err := tx.db.prepareDC(ctx, dc, release, tx, query)
2334 if err != nil {
2335 return nil, err
2336 }
2337 tx.stmts.Lock()
2338 tx.stmts.v = append(tx.stmts.v, stmt)
2339 tx.stmts.Unlock()
2340 return stmt, nil
2341 }
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352 func (tx *Tx) Prepare(query string) (*Stmt, error) {
2353 return tx.PrepareContext(context.Background(), query)
2354 }
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372 func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
2373 dc, release, err := tx.grabConn(ctx)
2374 if err != nil {
2375 return &Stmt{stickyErr: err}
2376 }
2377 defer release(nil)
2378
2379 if tx.db != stmt.db {
2380 return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
2381 }
2382 var si driver.Stmt
2383 var parentStmt *Stmt
2384 stmt.mu.Lock()
2385 if stmt.closed || stmt.cg != nil {
2386
2387
2388
2389
2390
2391
2392 stmt.mu.Unlock()
2393 withLock(dc, func() {
2394 si, err = ctxDriverPrepare(ctx, dc.ci, stmt.query)
2395 })
2396 if err != nil {
2397 return &Stmt{stickyErr: err}
2398 }
2399 } else {
2400 stmt.removeClosedStmtLocked()
2401
2402
2403 for _, v := range stmt.css {
2404 if v.dc == dc {
2405 si = v.ds.si
2406 break
2407 }
2408 }
2409
2410 stmt.mu.Unlock()
2411
2412 if si == nil {
2413 var ds *driverStmt
2414 withLock(dc, func() {
2415 ds, err = stmt.prepareOnConnLocked(ctx, dc)
2416 })
2417 if err != nil {
2418 return &Stmt{stickyErr: err}
2419 }
2420 si = ds.si
2421 }
2422 parentStmt = stmt
2423 }
2424
2425 txs := &Stmt{
2426 db: tx.db,
2427 cg: tx,
2428 cgds: &driverStmt{
2429 Locker: dc,
2430 si: si,
2431 },
2432 parentStmt: parentStmt,
2433 query: stmt.query,
2434 }
2435 if parentStmt != nil {
2436 tx.db.addDep(parentStmt, txs)
2437 }
2438 tx.stmts.Lock()
2439 tx.stmts.v = append(tx.stmts.v, txs)
2440 tx.stmts.Unlock()
2441 return txs
2442 }
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460 func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
2461 return tx.StmtContext(context.Background(), stmt)
2462 }
2463
2464
2465
2466 func (tx *Tx) ExecContext(ctx context.Context, query string, args ...any) (Result, error) {
2467 dc, release, err := tx.grabConn(ctx)
2468 if err != nil {
2469 return nil, err
2470 }
2471 return tx.db.execDC(ctx, dc, release, query, args)
2472 }
2473
2474
2475
2476
2477
2478
2479 func (tx *Tx) Exec(query string, args ...any) (Result, error) {
2480 return tx.ExecContext(context.Background(), query, args...)
2481 }
2482
2483
2484 func (tx *Tx) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) {
2485 dc, release, err := tx.grabConn(ctx)
2486 if err != nil {
2487 return nil, err
2488 }
2489
2490 return tx.db.queryDC(ctx, tx.ctx, dc, release, query, args)
2491 }
2492
2493
2494
2495
2496
2497 func (tx *Tx) Query(query string, args ...any) (*Rows, error) {
2498 return tx.QueryContext(context.Background(), query, args...)
2499 }
2500
2501
2502
2503
2504
2505
2506
2507 func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...any) *Row {
2508 rows, err := tx.QueryContext(ctx, query, args...)
2509 return &Row{rows: rows, err: err}
2510 }
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521 func (tx *Tx) QueryRow(query string, args ...any) *Row {
2522 return tx.QueryRowContext(context.Background(), query, args...)
2523 }
2524
2525
2526 type connStmt struct {
2527 dc *driverConn
2528 ds *driverStmt
2529 }
2530
2531
2532
2533 type stmtConnGrabber interface {
2534
2535
2536 grabConn(context.Context) (*driverConn, releaseConn, error)
2537
2538
2539
2540
2541 txCtx() context.Context
2542 }
2543
2544 var (
2545 _ stmtConnGrabber = &Tx{}
2546 _ stmtConnGrabber = &Conn{}
2547 )
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558 type Stmt struct {
2559
2560 db *DB
2561 query string
2562 stickyErr error
2563
2564 closemu sync.RWMutex
2565
2566
2567
2568
2569
2570
2571 cg stmtConnGrabber
2572 cgds *driverStmt
2573
2574
2575
2576
2577
2578
2579
2580 parentStmt *Stmt
2581
2582 mu sync.Mutex
2583 closed bool
2584
2585
2586
2587
2588
2589 css []connStmt
2590
2591
2592
2593 lastNumClosed uint64
2594 }
2595
2596
2597
2598 func (s *Stmt) ExecContext(ctx context.Context, args ...any) (Result, error) {
2599 s.closemu.RLock()
2600 defer s.closemu.RUnlock()
2601
2602 var res Result
2603 err := s.db.retry(func(strategy connReuseStrategy) error {
2604 dc, releaseConn, ds, err := s.connStmt(ctx, strategy)
2605 if err != nil {
2606 return err
2607 }
2608
2609 res, err = resultFromStatement(ctx, dc.ci, ds, args...)
2610 releaseConn(err)
2611 return err
2612 })
2613
2614 return res, err
2615 }
2616
2617
2618
2619
2620
2621
2622 func (s *Stmt) Exec(args ...any) (Result, error) {
2623 return s.ExecContext(context.Background(), args...)
2624 }
2625
2626 func resultFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...any) (Result, error) {
2627 ds.Lock()
2628 defer ds.Unlock()
2629
2630 dargs, err := driverArgsConnLocked(ci, ds, args)
2631 if err != nil {
2632 return nil, err
2633 }
2634
2635 resi, err := ctxDriverStmtExec(ctx, ds.si, dargs)
2636 if err != nil {
2637 return nil, err
2638 }
2639 return driverResult{ds.Locker, resi}, nil
2640 }
2641
2642
2643
2644
2645
2646 func (s *Stmt) removeClosedStmtLocked() {
2647 t := len(s.css)/2 + 1
2648 if t > 10 {
2649 t = 10
2650 }
2651 dbClosed := s.db.numClosed.Load()
2652 if dbClosed-s.lastNumClosed < uint64(t) {
2653 return
2654 }
2655
2656 s.db.mu.Lock()
2657 for i := 0; i < len(s.css); i++ {
2658 if s.css[i].dc.dbmuClosed {
2659 s.css[i] = s.css[len(s.css)-1]
2660 s.css = s.css[:len(s.css)-1]
2661 i--
2662 }
2663 }
2664 s.db.mu.Unlock()
2665 s.lastNumClosed = dbClosed
2666 }
2667
2668
2669
2670
2671 func (s *Stmt) connStmt(ctx context.Context, strategy connReuseStrategy) (dc *driverConn, releaseConn func(error), ds *driverStmt, err error) {
2672 if err = s.stickyErr; err != nil {
2673 return
2674 }
2675 s.mu.Lock()
2676 if s.closed {
2677 s.mu.Unlock()
2678 err = errors.New("sql: statement is closed")
2679 return
2680 }
2681
2682
2683
2684 if s.cg != nil {
2685 s.mu.Unlock()
2686 dc, releaseConn, err = s.cg.grabConn(ctx)
2687 if err != nil {
2688 return
2689 }
2690 return dc, releaseConn, s.cgds, nil
2691 }
2692
2693 s.removeClosedStmtLocked()
2694 s.mu.Unlock()
2695
2696 dc, err = s.db.conn(ctx, strategy)
2697 if err != nil {
2698 return nil, nil, nil, err
2699 }
2700
2701 s.mu.Lock()
2702 for _, v := range s.css {
2703 if v.dc == dc {
2704 s.mu.Unlock()
2705 return dc, dc.releaseConn, v.ds, nil
2706 }
2707 }
2708 s.mu.Unlock()
2709
2710
2711 withLock(dc, func() {
2712 ds, err = s.prepareOnConnLocked(ctx, dc)
2713 })
2714 if err != nil {
2715 dc.releaseConn(err)
2716 return nil, nil, nil, err
2717 }
2718
2719 return dc, dc.releaseConn, ds, nil
2720 }
2721
2722
2723
2724 func (s *Stmt) prepareOnConnLocked(ctx context.Context, dc *driverConn) (*driverStmt, error) {
2725 si, err := dc.prepareLocked(ctx, s.cg, s.query)
2726 if err != nil {
2727 return nil, err
2728 }
2729 cs := connStmt{dc, si}
2730 s.mu.Lock()
2731 s.css = append(s.css, cs)
2732 s.mu.Unlock()
2733 return cs.ds, nil
2734 }
2735
2736
2737
2738 func (s *Stmt) QueryContext(ctx context.Context, args ...any) (*Rows, error) {
2739 s.closemu.RLock()
2740 defer s.closemu.RUnlock()
2741
2742 var rowsi driver.Rows
2743 var rows *Rows
2744
2745 err := s.db.retry(func(strategy connReuseStrategy) error {
2746 dc, releaseConn, ds, err := s.connStmt(ctx, strategy)
2747 if err != nil {
2748 return err
2749 }
2750
2751 rowsi, err = rowsiFromStatement(ctx, dc.ci, ds, args...)
2752 if err == nil {
2753
2754
2755 rows = &Rows{
2756 dc: dc,
2757 rowsi: rowsi,
2758
2759 }
2760
2761
2762 s.db.addDep(s, rows)
2763
2764
2765
2766 rows.releaseConn = func(err error) {
2767 releaseConn(err)
2768 s.db.removeDep(s, rows)
2769 }
2770 var txctx context.Context
2771 if s.cg != nil {
2772 txctx = s.cg.txCtx()
2773 }
2774 rows.initContextClose(ctx, txctx)
2775 return nil
2776 }
2777
2778 releaseConn(err)
2779 return err
2780 })
2781
2782 return rows, err
2783 }
2784
2785
2786
2787
2788
2789
2790 func (s *Stmt) Query(args ...any) (*Rows, error) {
2791 return s.QueryContext(context.Background(), args...)
2792 }
2793
2794 func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...any) (driver.Rows, error) {
2795 ds.Lock()
2796 defer ds.Unlock()
2797 dargs, err := driverArgsConnLocked(ci, ds, args)
2798 if err != nil {
2799 return nil, err
2800 }
2801 return ctxDriverStmtQuery(ctx, ds.si, dargs)
2802 }
2803
2804
2805
2806
2807
2808
2809
2810 func (s *Stmt) QueryRowContext(ctx context.Context, args ...any) *Row {
2811 rows, err := s.QueryContext(ctx, args...)
2812 if err != nil {
2813 return &Row{err: err}
2814 }
2815 return &Row{rows: rows}
2816 }
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832 func (s *Stmt) QueryRow(args ...any) *Row {
2833 return s.QueryRowContext(context.Background(), args...)
2834 }
2835
2836
2837 func (s *Stmt) Close() error {
2838 s.closemu.Lock()
2839 defer s.closemu.Unlock()
2840
2841 if s.stickyErr != nil {
2842 return s.stickyErr
2843 }
2844 s.mu.Lock()
2845 if s.closed {
2846 s.mu.Unlock()
2847 return nil
2848 }
2849 s.closed = true
2850 txds := s.cgds
2851 s.cgds = nil
2852
2853 s.mu.Unlock()
2854
2855 if s.cg == nil {
2856 return s.db.removeDep(s, s)
2857 }
2858
2859 if s.parentStmt != nil {
2860
2861
2862 return s.db.removeDep(s.parentStmt, s)
2863 }
2864 return txds.Close()
2865 }
2866
2867 func (s *Stmt) finalClose() error {
2868 s.mu.Lock()
2869 defer s.mu.Unlock()
2870 if s.css != nil {
2871 for _, v := range s.css {
2872 s.db.noteUnusedDriverStatement(v.dc, v.ds)
2873 v.dc.removeOpenStmt(v.ds)
2874 }
2875 s.css = nil
2876 }
2877 return nil
2878 }
2879
2880
2881
2882 type Rows struct {
2883 dc *driverConn
2884 releaseConn func(error)
2885 rowsi driver.Rows
2886 cancel func()
2887 closeStmt *driverStmt
2888
2889
2890
2891
2892
2893
2894 closemu sync.RWMutex
2895 closed bool
2896 lasterr error
2897
2898
2899
2900 lastcols []driver.Value
2901 }
2902
2903
2904
2905 func (rs *Rows) lasterrOrErrLocked(err error) error {
2906 if rs.lasterr != nil && rs.lasterr != io.EOF {
2907 return rs.lasterr
2908 }
2909 return err
2910 }
2911
2912
2913
2914 var bypassRowsAwaitDone = false
2915
2916 func (rs *Rows) initContextClose(ctx, txctx context.Context) {
2917 if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) {
2918 return
2919 }
2920 if bypassRowsAwaitDone {
2921 return
2922 }
2923 ctx, rs.cancel = context.WithCancel(ctx)
2924 go rs.awaitDone(ctx, txctx)
2925 }
2926
2927
2928
2929
2930
2931 func (rs *Rows) awaitDone(ctx, txctx context.Context) {
2932 var txctxDone <-chan struct{}
2933 if txctx != nil {
2934 txctxDone = txctx.Done()
2935 }
2936 select {
2937 case <-ctx.Done():
2938 case <-txctxDone:
2939 }
2940 rs.close(ctx.Err())
2941 }
2942
2943
2944
2945
2946
2947
2948
2949 func (rs *Rows) Next() bool {
2950 var doClose, ok bool
2951 withLock(rs.closemu.RLocker(), func() {
2952 doClose, ok = rs.nextLocked()
2953 })
2954 if doClose {
2955 rs.Close()
2956 }
2957 return ok
2958 }
2959
2960 func (rs *Rows) nextLocked() (doClose, ok bool) {
2961 if rs.closed {
2962 return false, false
2963 }
2964
2965
2966
2967 rs.dc.Lock()
2968 defer rs.dc.Unlock()
2969
2970 if rs.lastcols == nil {
2971 rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
2972 }
2973
2974 rs.lasterr = rs.rowsi.Next(rs.lastcols)
2975 if rs.lasterr != nil {
2976
2977 if rs.lasterr != io.EOF {
2978 return true, false
2979 }
2980 nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
2981 if !ok {
2982 return true, false
2983 }
2984
2985
2986
2987 if !nextResultSet.HasNextResultSet() {
2988 doClose = true
2989 }
2990 return doClose, false
2991 }
2992 return false, true
2993 }
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003 func (rs *Rows) NextResultSet() bool {
3004 var doClose bool
3005 defer func() {
3006 if doClose {
3007 rs.Close()
3008 }
3009 }()
3010 rs.closemu.RLock()
3011 defer rs.closemu.RUnlock()
3012
3013 if rs.closed {
3014 return false
3015 }
3016
3017 rs.lastcols = nil
3018 nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
3019 if !ok {
3020 doClose = true
3021 return false
3022 }
3023
3024
3025
3026 rs.dc.Lock()
3027 defer rs.dc.Unlock()
3028
3029 rs.lasterr = nextResultSet.NextResultSet()
3030 if rs.lasterr != nil {
3031 doClose = true
3032 return false
3033 }
3034 return true
3035 }
3036
3037
3038
3039 func (rs *Rows) Err() error {
3040 rs.closemu.RLock()
3041 defer rs.closemu.RUnlock()
3042 return rs.lasterrOrErrLocked(nil)
3043 }
3044
3045 var errRowsClosed = errors.New("sql: Rows are closed")
3046 var errNoRows = errors.New("sql: no Rows available")
3047
3048
3049
3050 func (rs *Rows) Columns() ([]string, error) {
3051 rs.closemu.RLock()
3052 defer rs.closemu.RUnlock()
3053 if rs.closed {
3054 return nil, rs.lasterrOrErrLocked(errRowsClosed)
3055 }
3056 if rs.rowsi == nil {
3057 return nil, rs.lasterrOrErrLocked(errNoRows)
3058 }
3059 rs.dc.Lock()
3060 defer rs.dc.Unlock()
3061
3062 return rs.rowsi.Columns(), nil
3063 }
3064
3065
3066
3067 func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
3068 rs.closemu.RLock()
3069 defer rs.closemu.RUnlock()
3070 if rs.closed {
3071 return nil, rs.lasterrOrErrLocked(errRowsClosed)
3072 }
3073 if rs.rowsi == nil {
3074 return nil, rs.lasterrOrErrLocked(errNoRows)
3075 }
3076 rs.dc.Lock()
3077 defer rs.dc.Unlock()
3078
3079 return rowsColumnInfoSetupConnLocked(rs.rowsi), nil
3080 }
3081
3082
3083 type ColumnType struct {
3084 name string
3085
3086 hasNullable bool
3087 hasLength bool
3088 hasPrecisionScale bool
3089
3090 nullable bool
3091 length int64
3092 databaseType string
3093 precision int64
3094 scale int64
3095 scanType reflect.Type
3096 }
3097
3098
3099 func (ci *ColumnType) Name() string {
3100 return ci.name
3101 }
3102
3103
3104
3105
3106
3107
3108 func (ci *ColumnType) Length() (length int64, ok bool) {
3109 return ci.length, ci.hasLength
3110 }
3111
3112
3113
3114 func (ci *ColumnType) DecimalSize() (precision, scale int64, ok bool) {
3115 return ci.precision, ci.scale, ci.hasPrecisionScale
3116 }
3117
3118
3119
3120
3121 func (ci *ColumnType) ScanType() reflect.Type {
3122 return ci.scanType
3123 }
3124
3125
3126
3127 func (ci *ColumnType) Nullable() (nullable, ok bool) {
3128 return ci.nullable, ci.hasNullable
3129 }
3130
3131
3132
3133
3134
3135
3136
3137 func (ci *ColumnType) DatabaseTypeName() string {
3138 return ci.databaseType
3139 }
3140
3141 func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType {
3142 names := rowsi.Columns()
3143
3144 list := make([]*ColumnType, len(names))
3145 for i := range list {
3146 ci := &ColumnType{
3147 name: names[i],
3148 }
3149 list[i] = ci
3150
3151 if prop, ok := rowsi.(driver.RowsColumnTypeScanType); ok {
3152 ci.scanType = prop.ColumnTypeScanType(i)
3153 } else {
3154 ci.scanType = reflect.TypeOf(new(any)).Elem()
3155 }
3156 if prop, ok := rowsi.(driver.RowsColumnTypeDatabaseTypeName); ok {
3157 ci.databaseType = prop.ColumnTypeDatabaseTypeName(i)
3158 }
3159 if prop, ok := rowsi.(driver.RowsColumnTypeLength); ok {
3160 ci.length, ci.hasLength = prop.ColumnTypeLength(i)
3161 }
3162 if prop, ok := rowsi.(driver.RowsColumnTypeNullable); ok {
3163 ci.nullable, ci.hasNullable = prop.ColumnTypeNullable(i)
3164 }
3165 if prop, ok := rowsi.(driver.RowsColumnTypePrecisionScale); ok {
3166 ci.precision, ci.scale, ci.hasPrecisionScale = prop.ColumnTypePrecisionScale(i)
3167 }
3168 }
3169 return list
3170 }
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232 func (rs *Rows) Scan(dest ...any) error {
3233 rs.closemu.RLock()
3234
3235 if rs.lasterr != nil && rs.lasterr != io.EOF {
3236 rs.closemu.RUnlock()
3237 return rs.lasterr
3238 }
3239 if rs.closed {
3240 err := rs.lasterrOrErrLocked(errRowsClosed)
3241 rs.closemu.RUnlock()
3242 return err
3243 }
3244 rs.closemu.RUnlock()
3245
3246 if rs.lastcols == nil {
3247 return errors.New("sql: Scan called without calling Next")
3248 }
3249 if len(dest) != len(rs.lastcols) {
3250 return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
3251 }
3252 for i, sv := range rs.lastcols {
3253 err := convertAssignRows(dest[i], sv, rs)
3254 if err != nil {
3255 return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err)
3256 }
3257 }
3258 return nil
3259 }
3260
3261
3262
3263 var rowsCloseHook = func() func(*Rows, *error) { return nil }
3264
3265
3266
3267
3268
3269 func (rs *Rows) Close() error {
3270 return rs.close(nil)
3271 }
3272
3273 func (rs *Rows) close(err error) error {
3274 rs.closemu.Lock()
3275 defer rs.closemu.Unlock()
3276
3277 if rs.closed {
3278 return nil
3279 }
3280 rs.closed = true
3281
3282 if rs.lasterr == nil {
3283 rs.lasterr = err
3284 }
3285
3286 withLock(rs.dc, func() {
3287 err = rs.rowsi.Close()
3288 })
3289 if fn := rowsCloseHook(); fn != nil {
3290 fn(rs, &err)
3291 }
3292 if rs.cancel != nil {
3293 rs.cancel()
3294 }
3295
3296 if rs.closeStmt != nil {
3297 rs.closeStmt.Close()
3298 }
3299 rs.releaseConn(err)
3300
3301 rs.lasterr = rs.lasterrOrErrLocked(err)
3302 return err
3303 }
3304
3305
3306 type Row struct {
3307
3308 err error
3309 rows *Rows
3310 }
3311
3312
3313
3314
3315
3316
3317 func (r *Row) Scan(dest ...any) error {
3318 if r.err != nil {
3319 return r.err
3320 }
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335 defer r.rows.Close()
3336 for _, dp := range dest {
3337 if _, ok := dp.(*RawBytes); ok {
3338 return errors.New("sql: RawBytes isn't allowed on Row.Scan")
3339 }
3340 }
3341
3342 if !r.rows.Next() {
3343 if err := r.rows.Err(); err != nil {
3344 return err
3345 }
3346 return ErrNoRows
3347 }
3348 err := r.rows.Scan(dest...)
3349 if err != nil {
3350 return err
3351 }
3352
3353 return r.rows.Close()
3354 }
3355
3356
3357
3358
3359
3360 func (r *Row) Err() error {
3361 return r.err
3362 }
3363
3364
3365 type Result interface {
3366
3367
3368
3369
3370
3371 LastInsertId() (int64, error)
3372
3373
3374
3375
3376 RowsAffected() (int64, error)
3377 }
3378
3379 type driverResult struct {
3380 sync.Locker
3381 resi driver.Result
3382 }
3383
3384 func (dr driverResult) LastInsertId() (int64, error) {
3385 dr.Lock()
3386 defer dr.Unlock()
3387 return dr.resi.LastInsertId()
3388 }
3389
3390 func (dr driverResult) RowsAffected() (int64, error) {
3391 dr.Lock()
3392 defer dr.Unlock()
3393 return dr.resi.RowsAffected()
3394 }
3395
3396 func stack() string {
3397 var buf [2 << 10]byte
3398 return string(buf[:runtime.Stack(buf[:], false)])
3399 }
3400
3401
3402 func withLock(lk sync.Locker, fn func()) {
3403 lk.Lock()
3404 defer lk.Unlock()
3405 fn()
3406 }
3407
View as plain text