MCPcopy
hub / github.com/ent/ent / scanStruct

Function scanStruct

dialect/sql/scan.go:195–276  ·  view source on GitHub ↗

scanStruct returns the configuration for scanning a sql.Row into a struct.

(typ reflect.Type, columns []string)

Source from the content-addressed store, hash-verified

193
194// scanStruct returns the configuration for scanning a sql.Row into a struct.
195func scanStruct(typ reflect.Type, columns []string) (*rowScan, error) {
196 var (
197 scan = &rowScan{}
198 idxs = make([][]int, 0, typ.NumField())
199 names = make(map[string][]int, typ.NumField())
200 )
201 for i := 0; i < typ.NumField(); i++ {
202 f := typ.Field(i)
203 // Skip unexported fields.
204 if f.PkgPath != "" {
205 continue
206 }
207 // Support 1-level embedding to accept types as `type T struct {ent.T; V int}`.
208 if typ := f.Type; f.Anonymous && typ.Kind() == reflect.Struct {
209 for j := 0; j < typ.NumField(); j++ {
210 names[columnName(typ.Field(j))] = []int{i, j}
211 }
212 continue
213 }
214 names[columnName(f)] = []int{i}
215 }
216 for _, c := range columns {
217 var idx []int
218 // Normalize columns if necessary,
219 // for example: COUNT(*) => count.
220 switch name := strings.Split(c, "(")[0]; {
221 case names[name] != nil:
222 idx = names[name]
223 case names[strings.ToLower(name)] != nil:
224 idx = names[strings.ToLower(name)]
225 default:
226 return nil, fmt.Errorf("sql/scan: missing struct field for column: %s (%s)", c, name)
227 }
228 idxs = append(idxs, idx)
229 rtype := typ.Field(idx[0]).Type
230 if len(idx) > 1 {
231 rtype = rtype.Field(idx[1]).Type
232 }
233 switch {
234 // If the field is not support by the standard
235 // convertAssign, assume it is a JSON field.
236 case !supportsScan(rtype):
237 rtype = nullJSONType
238 // Create a pointer to the actual reflect
239 // types to accept optional struct fields.
240 case !nillable(rtype):
241 rtype = reflect.PtrTo(rtype)
242 }
243 scan.columns = append(scan.columns, rtype)
244 }
245 scan.value = func(vs ...any) (reflect.Value, error) {
246 st := reflect.New(typ).Elem()
247 for i, v := range vs {
248 rv := reflect.Indirect(reflect.ValueOf(v))
249 if rv.IsNil() {
250 continue
251 }
252 idx := idxs[i]

Callers 1

scanTypeFunction · 0.85

Calls 8

columnNameFunction · 0.85
supportsScanFunction · 0.85
nillableFunction · 0.85
NewMethod · 0.80
AddrMethod · 0.80
FieldMethod · 0.65
TypeMethod · 0.65
SetMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…