/* only the fields that are *fat.Field and not nil are chosen to be set from the row. fields that are not set in the row, are set to nil */ func (r *Registry) FromRow(row *Row, øptrToFatStruct interface{}) (err error) { fn := func(field *meta.Field) { if err != nil { return } if field.Value.IsNil() { return } ff, isFat := field.Value.Interface().(*fat.Field) if !isFat { return } dbField := r.FieldOf(ff) if row.Values()[dbField] != nil { fatField := field.Value.Interface().(*fat.Field) err = scanFieldToStruct(row, fatField, dbField) return } field.Value.Set(fatFieldNil) // ff.Set(fatFieldNil) /* if dbField.Is(NullAllowed) { ff.Set(fatFieldNil) } */ } var stru *meta.Struct stru, err = meta.StructByValue(reflect.ValueOf(øptrToFatStruct)) if err == nil { stru.Each(fn) } return }
func (r *CRUD) scanFields() (err error) { var hasDeleteField bool //fn := func(fld reflect.StructField, vl reflect.Value, tag string) { fn := func(fld *meta.Field) { if err != nil { return } tag := fld.Type.Tag.Get("rest") if tag == "" { return } methods := map[string]bool{} if strings.Contains(tag, "C") { methods["C"] = true } if strings.Contains(tag, "D") { if hasDeleteField { err = fmt.Errorf("more than one delete field (key) is not supported") return } methods["D"] = true hasDeleteField = true } if strings.Contains(tag, "L") { methods["L"] = true } if strings.Contains(tag, "U") { methods["U"] = true } if strings.Contains(tag, "R") { methods["R"] = true } if len(methods) == 0 { return } //ff := r.field(fld.Name) ff := r.field(fld.Type.Name) if ff == nil { err = fmt.Errorf("can't find field for table %s field %s\n", r.typeString(), fld.Type.Name) return } // pgsql.flags if strings.Contains(fld.Type.Tag.Get("db"), "PKEY") { if r.primaryKey != nil { err = fmt.Errorf("can't have more than one primary key %s and %s\n", r.primaryKey, fld.Type.Name) return } r.primaryKey = r.field(fld.Type.Name) } r.fields[fld.Type.Name] = methods } var stru *meta.Struct stru, err = meta.StructByValue(reflect.ValueOf(r.prototype)) stru.Each(fn) //meta.Struct.EachTag(r.prototype, "rest", fn) if r.primaryKey == nil { err = fmt.Errorf("has not primary key, add db:\"PKEY\"") } pkType := r.primaryKey.Type if !pkType.IsCompatible(IntType) { if pkType.IsCompatible(TextType) { r.pKeyIsString = true return } err = fmt.Errorf("primary key %s (%s) is not compatible to int or string", r.primaryKey.Name, pkType.String()) } return }
/* only the fields that are *fat.Field and not nil are chosen to set the row. øptrToFatStruct must be registered with RegisterTable before using this function */ func (r *Registry) ToRow(øptrToFatStruct interface{}, row *Row) (err error) { var stru *meta.Struct stru, err = meta.StructByValue(reflect.ValueOf(øptrToFatStruct)) if err != nil { return } t := r.TableOf(øptrToFatStruct) if t == nil { err = fmt.Errorf("%T is not registered, use RegisterTable", øptrToFatStruct) return } if row.Table != t { err = fmt.Errorf("table of the given fatstruct (%s) is not the same as table of the given row (%s)", t.Sql().String(), row.Table.Sql().String(), ) } if err != nil { return } fn := func(field *meta.Field) { // stop on first error if err != nil { return } if field.Value.IsNil() { return } ff, isFat := field.Value.Interface().(*fat.Field) if !isFat { return } rowField := r.FieldOf(ff) v := ff.Get() switch v.(type) { case []fat.Type: vl := ff.String() vl = strings.Replace(vl, "[", "{", -1) vl = strings.Replace(vl, "]", "}", -1) err = row.Set(rowField, vl) case map[string]fat.Type: err = row.Set(rowField, ff.String()) default: err = row.Set(rowField, v) } } stru.Each(fn) return }