github.com/aacfactory/fns-contrib/databases/sql@v1.2.84/dac/specifications/scanner.go (about) 1 package specifications 2 3 import ( 4 "fmt" 5 "github.com/aacfactory/errors" 6 "reflect" 7 "sync" 8 ) 9 10 var ( 11 genericsPool = sync.Pool{} 12 ) 13 14 func acquireGenerics(n int) (v Generics) { 15 c := genericsPool.Get() 16 if c == nil { 17 v = make(Generics, n) 18 for i := 0; i < n; i++ { 19 v[i] = &Generic{} 20 } 21 } else { 22 v = c.(Generics) 23 vLen := len(v) 24 if delta := n - vLen; delta < 0 { 25 v = v[0:n] 26 } else if delta > 0 { 27 for i := 0; i < delta; i++ { 28 v = append(v, &Generic{}) 29 } 30 } 31 } 32 return 33 } 34 35 func releaseGenerics(generics Generics) { 36 for _, generic := range generics { 37 generic.(*Generic).Reset() 38 } 39 genericsPool.Put(generics) 40 } 41 42 type Generics []any 43 44 func (generics Generics) WriteTo(spec *Specification, fieldNames []string, entryPtr any) (err error) { 45 rv := reflect.Indirect(reflect.ValueOf(entryPtr)) 46 for i, fieldName := range fieldNames { 47 column, has := spec.ColumnByField(fieldName) 48 if !has { 49 err = errors.Warning(fmt.Sprintf("sql: %s field was not found in %s", fieldName, spec.Key)). 50 WithMeta("field", fieldName).WithMeta("table", spec.Key) 51 return 52 } 53 fv := column.ReadValue(rv) 54 generic := generics[i].(*Generic) 55 if generic.Valid { 56 err = column.WriteValue(fv, generic.Value) 57 if err != nil { 58 err = errors.Warning(fmt.Sprintf("sql: write value into %s.%s field failed", spec.Key, fieldName)).WithCause(err). 59 WithMeta("field", fieldName).WithMeta("table", spec.Key) 60 return 61 } 62 } 63 } 64 return 65 } 66 67 type Generic struct { 68 Valid bool 69 Value any 70 } 71 72 func (v *Generic) Scan(src any) (err error) { 73 if src == nil { 74 return 75 } 76 v.Valid = true 77 v.Value = src 78 return 79 } 80 81 func (v *Generic) Reset() { 82 v.Valid = false 83 v.Value = nil 84 }