package orm import ( "github.com/jackc/pgx/v5" "reflect" ) func rowsToMaps(rows pgx.Rows) ([]map[string]any, error) { var result []map[string]any fieldDescs := rows.FieldDescriptions() for rows.Next() { m := make(map[string]any) scanArgs := make([]any, len(fieldDescs)) for i := range fieldDescs { var v any scanArgs[i] = &v } if err := rows.Scan(scanArgs...); err != nil { return nil, err } for i, fd := range fieldDescs { name := fd.Name m[name] = *(scanArgs[i].(*any)) } result = append(result, m) } return result, rows.Err() } func fillNested(row map[string]any, t reflect.Type, mm *ModelMap, depth, maxDepth int) any { cm := mm.Map[t.Name()] pp := reflect.New(cm.Type).Elem() for _, field := range cm.Fields { _, alias := field.alias() if v, ok := row[alias]; ok && !field.isForeignKey { reflectSet(pp.Field(field.Index), v) } } for _, rel := range cm.Relationships { if rel.Idx > -1 && rel.Idx < pp.NumField() { relType := rel.RelatedModel.Type for relType.Kind() == reflect.Pointer { relType = relType.Elem() } nv := reflect.New(relType) if rel.Kind == reflect.Struct || rel.Kind == reflect.Pointer { if depth < maxDepth { nv = reflect.ValueOf(fillNested(row, relType, mm, depth+1, maxDepth)) } if rel.Kind != reflect.Pointer && nv.Kind() == reflect.Pointer { nv = nv.Elem() } reflectSet(pp.Field(rel.Idx), nv) } else if rel.Kind == reflect.Slice || rel.Kind == reflect.Array { relType2 := relType for relType2.Kind() == reflect.Slice || relType2.Kind() == reflect.Array { relType2 = relType2.Elem() } if depth < maxDepth { nv = reflect.ValueOf(fillNested(row, relType2, mm, depth+1, maxDepth)) } if nv.Kind() == reflect.Pointer { nv = nv.Elem() } reflectSet(pp.Field(rel.Idx), reflect.Append(pp.Field(rel.Idx), nv)) } } } return pp.Interface() } // fillSlice - note that it's the caller's responsibility to indirect // the type in `t`. func fillSlice(rows []map[string]any, t reflect.Type, mm *ModelMap) any { pslice := reflect.MakeSlice(reflect.SliceOf(t), 0, 0) rt := t for rt.Kind() == reflect.Ptr { rt = rt.Elem() } for _, row := range rows { pp := fillNested(row, rt, mm, 0, 10) pslice = reflect.Append(pslice, reflect.ValueOf(pp)) } return pslice.Interface() }