model_slice.go (1421B)
1 package bun 2 3 import ( 4 "context" 5 "database/sql" 6 "reflect" 7 8 "github.com/uptrace/bun/internal" 9 "github.com/uptrace/bun/schema" 10 ) 11 12 type sliceInfo struct { 13 nextElem func() reflect.Value 14 scan schema.ScannerFunc 15 } 16 17 type sliceModel struct { 18 dest []interface{} 19 values []reflect.Value 20 scanIndex int 21 info []sliceInfo 22 } 23 24 var _ Model = (*sliceModel)(nil) 25 26 func newSliceModel(db *DB, dest []interface{}, values []reflect.Value) *sliceModel { 27 return &sliceModel{ 28 dest: dest, 29 values: values, 30 } 31 } 32 33 func (m *sliceModel) Value() interface{} { 34 return m.dest 35 } 36 37 func (m *sliceModel) ScanRows(ctx context.Context, rows *sql.Rows) (int, error) { 38 columns, err := rows.Columns() 39 if err != nil { 40 return 0, err 41 } 42 43 m.info = make([]sliceInfo, len(m.values)) 44 for i, v := range m.values { 45 if v.IsValid() && v.Len() > 0 { 46 v.Set(v.Slice(0, 0)) 47 } 48 49 m.info[i] = sliceInfo{ 50 nextElem: internal.MakeSliceNextElemFunc(v), 51 scan: schema.Scanner(v.Type().Elem()), 52 } 53 } 54 55 if len(columns) == 0 { 56 return 0, nil 57 } 58 dest := makeDest(m, len(columns)) 59 60 var n int 61 62 for rows.Next() { 63 m.scanIndex = 0 64 if err := rows.Scan(dest...); err != nil { 65 return 0, err 66 } 67 n++ 68 } 69 if err := rows.Err(); err != nil { 70 return 0, err 71 } 72 73 return n, nil 74 } 75 76 func (m *sliceModel) Scan(src interface{}) error { 77 info := m.info[m.scanIndex] 78 m.scanIndex++ 79 80 dest := info.nextElem() 81 return info.scan(dest, src) 82 }