/* ScanFieldToStruct scans a field of the *Row from a database query into the given fatstruct and returns the value that would be inserted into a json representation or an error, if scan or validation fails */ func (c *CRUD) scanFieldToStruct(queryRow *Row, structField reflect.Value, dbField *Field) (jsonVal interface{}, err error) { fatField := structField.Interface().(*fat.Field) var stringInMap bool switch dbField.Type { case TimeType, DateType, TimeStampType, TimeStampTZType: stringInMap = true var t time.Time queryRow.Get(dbField, &t) err = fatField.Set(t) case IntsType: err = fatField.ScanString("[" + pgsqlfat.TrimCurly(queryRow.GetString(dbField)) + "]") case StringsType: ss := []string{} s__ := pgsqlfat.TrimCurly(queryRow.GetString(dbField)) if s__ != "" { s_s := strings.Split(s__, ",") for _, sss := range s_s { ss = append(ss, strings.Trim(sss, `" `)) } } err = fatField.Set(fat.Strings(ss...)) case JsonType: err = fatField.ScanString(queryRow.GetString(dbField)) case BoolsType: s__ := pgsqlfat.TrimCurly(queryRow.GetString(dbField)) var bs []bool if s__ != "" { vls := strings.Split(s__, ",") bs = make([]bool, len(vls)) for j, bstri := range vls { switch strings.TrimSpace(bstri) { case "t": bs[j] = true case "f": bs[j] = false default: return nil, fmt.Errorf("%s is no []bool", queryRow.GetString(dbField)) } } } err = fatField.Set(fat.Bools(bs...)) case FloatsType: err = fatField.ScanString("[" + pgsqlfat.TrimCurly(queryRow.GetString(dbField)) + "]") case TimeStampsTZType: //var t []time.Time var ts string queryRow.Get(dbField, &ts) s__ := pgsqlfat.TrimCurly(ts) var tms []time.Time if s__ != "" { vls := strings.Split(s__, ",") tms = make([]time.Time, len(vls)) for j, tmsStri := range vls { tm, e := fmtdate.Parse("YYYY-MM-DD hh:mm:ss+00", strings.Trim(tmsStri, `"`)) if e != nil { return nil, fmt.Errorf("can't parse time %s: %s", tmsStri, e.Error()) } tms[j] = tm } } // fmt.Printf("times: %#v\n", tms) err = fatField.Set(fat.Times(tms...)) /* err = fatField.ScanString("[" + pgsqlfat.TrimCurly(queryRow.GetString(dbField)) + "]") */ default: err = fatField.Scan(queryRow.GetString(dbField)) } if err != nil { return nil, err } errs := fatField.Validate() if len(errs) > 0 { var errStr bytes.Buffer for _, e := range errs { errStr.WriteString(e.Error() + "\n") } return nil, fmt.Errorf("Can't set field %s: %s", fatField.Name(), errStr.String()) } if stringInMap { jsonVal = fatField.String() } else { jsonVal = fatField.Get() } return }
func (c *CRUD) setFieldToStruct(jsonVal interface{}, taggedField string, fatStructVal reflect.Value, backupStruct reflect.Value) (err error) { structField := fatStructVal.FieldByName(taggedField) backupField := backupStruct.FieldByName(taggedField) newFatField := backupField.Interface().(*fat.Field) if jsonVal == nil { if newFatField.Default() != nil { structField.Set(backupField) return nil } dbField := c.field(taggedField) if dbField.Is(NullAllowed) { structField.Set(fatFieldNil) return nil } return fmt.Errorf("null not allowed") } // fmt.Printf("json val is: %T\n", jsonVal) switch jsonValTyped := jsonVal.(type) { case map[string]interface{}: var bt []byte bt, err = json.Marshal(jsonValTyped) if err == nil { err = newFatField.ScanString(string(bt)) } //case map[interface{}]interface{}: case []interface{}: var inputTypeOk bool switch newFatField.Typ() { case "[]float": flts := make([]float64, len(jsonValTyped)) for i, intf := range jsonValTyped { flts[i], inputTypeOk = intf.(float64) if !inputTypeOk { //err = fmt.Errorf("is no float64: %v (%T)", intf, intf) err = fmt.Errorf("is no float") break } } err = newFatField.Set(fat.Floats(flts...)) case "[]int": ints := make([]int64, len(jsonValTyped)) for i, intf := range jsonValTyped { var fl float64 fl, inputTypeOk = intf.(float64) ints[i] = toInt64(fl) if !inputTypeOk { //err = fmt.Errorf("is no float64: %v (%T)", intf, intf) err = fmt.Errorf("is no float") break } } err = newFatField.Set(fat.Ints(ints...)) case "[]string": strings := make([]string, len(jsonValTyped)) for i, intf := range jsonValTyped { strings[i], inputTypeOk = intf.(string) if !inputTypeOk { //err = fmt.Errorf("is no string: %v (%T)", intf, intf) err = fmt.Errorf("is no string") break } } err = newFatField.Set(fat.Strings(strings...)) case "[]bool": bools := make([]bool, len(jsonValTyped)) for i, intf := range jsonValTyped { bools[i], inputTypeOk = intf.(bool) if !inputTypeOk { //err = fmt.Errorf("is no bool: %v (%T)", intf, intf) err = fmt.Errorf("is no bool") break } } err = newFatField.Set(fat.Bools(bools...)) case "[]time": times := make([]time.Time, len(jsonValTyped)) for i, intf := range jsonValTyped { // fmt.Printf("[]Time: %#v\n", intf) var timestr string timestr, inputTypeOk = intf.(string) //times[i], inputTypeOk = intf.(time.Time) if !inputTypeOk { //err = fmt.Errorf("is no time: %v (%T)", intf, intf) err = fmt.Errorf("is no time") break } ti, e := time.Parse(time.RFC3339, timestr) if e != nil { //err = fmt.Errorf("can't parse time: %v: %s ", timestr, e.Error()) err = fmt.Errorf("invalid time") break } times[i] = ti } err = newFatField.Set(fat.Times(times...)) default: //err = fmt.Errorf("unsupported type: %#v", newFatField.Typ()) err = fmt.Errorf("unsupported type") } case float64: switch newFatField.Typ() { case "float": err = newFatField.Set(jsonVal) case "int": err = newFatField.Set(int64(jsonValTyped)) default: err = newFatField.Set(jsonVal) } case string: err = newFatField.ScanString(jsonValTyped) if err != nil { err = fmt.Errorf("is no %s", newFatField.Typ()) } default: err = newFatField.Set(jsonVal) } errs := newFatField.Validate() if len(errs) > 0 { //var errStr bytes.Buffer errStrings := make([]string, len(errs)) for j, e := range errs { errStrings[j] = e.Error() // errStr.WriteString(e.Error() + "\n") } //return fmt.Errorf("Can't set field %s: %s", taggedField, errStr.String()) //return fmt.Errorf("error while setting") //return fmt.Errorf(errStr.String()) return fmt.Errorf(strings.Join(errStrings, "\n")) } if err != nil { return err } structField.Set(backupField) return }
func scanFieldToStruct(row *Row, fatField *fat.Field, dbField *Field) (err error) { switch dbField.Type { case TimeType, DateType, TimeStampType, TimeStampTZType: var t time.Time row.Get(dbField, &t) err = fatField.Set(t) case IntsType: err = fatField.ScanString("[" + TrimCurly(row.GetString(dbField)) + "]") case StringsType: ss := []string{} s_s := strings.Split(TrimCurly(row.GetString(dbField)), ",") for _, sss := range s_s { ss = append(ss, strings.Trim(sss, `" `)) } err = fatField.Set(fat.Strings(ss...)) case JsonType: err = fatField.ScanString(row.GetString(dbField)) case BoolsType: vls := strings.Split(TrimCurly(row.GetString(dbField)), ",") bs := make([]bool, len(vls)) for j, bstri := range vls { switch strings.TrimSpace(bstri) { case "t": bs[j] = true case "f": bs[j] = false default: return fmt.Errorf("%s is no []bool", row.GetString(dbField)) } } err = fatField.Set(fat.Bools(bs...)) case FloatsType: err = fatField.ScanString("[" + TrimCurly(row.GetString(dbField)) + "]") case TimeStampsTZType: var ts string row.Get(dbField, &ts) vls := strings.Split(TrimCurly(ts), ",") tms := make([]time.Time, len(vls)) for j, tmsStri := range vls { tm, e := fmtdate.Parse("YYYY-MM-DD hh:mm:ss+00", strings.Trim(tmsStri, `"`)) if e != nil { return fmt.Errorf("can't parse time %s: %s", tmsStri, e.Error()) } tms[j] = tm } err = fatField.Set(fat.Times(tms...)) default: err = fatField.Scan(row.GetString(dbField)) } if err != nil { return err } errs := fatField.Validate() if len(errs) > 0 { var errStr bytes.Buffer for _, e := range errs { errStr.WriteString(e.Error() + "\n") } return fmt.Errorf("Can't set field %s: %s", fatField.Name(), errStr.String()) } return nil }