(rows *sql.Rows, target interface{})
| 28 | } |
| 29 | |
| 30 | func scanIntoStruct(rows *sql.Rows, target interface{}) (results interface{}, |
| 31 | err error) { |
| 32 | targetVal := reflect.ValueOf(target) |
| 33 | if (targetVal.Kind() == reflect.Ptr) { |
| 34 | targetVal = targetVal.Elem() |
| 35 | } |
| 36 | if (targetVal.Kind() != reflect.Struct) { |
| 37 | return |
| 38 | } |
| 39 | colNames, _ := rows.Columns() |
| 40 | colTypes, _ := rows.ColumnTypes() |
| 41 | references := []interface{} {} |
| 42 | fieldVal := reflect.Value{} |
| 43 | var placeholder interface{} |
| 44 | |
| 45 | for i, colName := range colNames { |
| 46 | colNameParts := strings.Split(colName, ".") |
| 47 | fieldVal = targetVal.FieldByName(colNameParts[0]) |
| 48 | if (fieldVal.IsValid() && fieldVal.Kind() == reflect.Struct && |
| 49 | len(colNameParts) > 1 ) { |
| 50 | var namePart string |
| 51 | for _, namePart = range colNameParts[1:] { |
| 52 | compFunction := matchColName(namePart) |
| 53 | fieldVal = fieldVal.FieldByNameFunc(compFunction) |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | if (!fieldVal.IsValid() || |
| 58 | !colTypes[i].ScanType().ConvertibleTo(fieldVal.Type())) { |
| 59 | references = append(references, &placeholder) |
| 60 | } else if (fieldVal.Kind() != reflect.Ptr && fieldVal.CanAddr()) { |
| 61 | fieldVal = fieldVal.Addr() |
| 62 | references = append(references, fieldVal.Interface()) |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | resultSlice := reflect.MakeSlice(reflect.SliceOf(targetVal.Type()), 0, 10) |
| 67 | for rows.Next() { |
| 68 | err = rows.Scan(references...) |
| 69 | if (err == nil) { |
| 70 | resultSlice = reflect.Append(resultSlice, targetVal) |
| 71 | } else { |
| 72 | break |
| 73 | } |
| 74 | } |
| 75 | results = resultSlice.Interface() |
| 76 | return |
| 77 | } |
| 78 | |
| 79 | |
| 80 | func matchColName(colName string) func(string) bool { |
no test coverage detected