diff --git a/base_test.go b/base_test.go index 93c11d4c..d07e8950 100644 --- a/base_test.go +++ b/base_test.go @@ -1706,6 +1706,48 @@ func testPrefixTableName(engine *Engine, t *testing.T) { } } +type CreatedUpdated struct { + Id int64 + Name string + Value float64 `xorm:"numeric"` + Created time.Time `xorm:"created"` + Created2 time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + +func testCreatedUpdated(engine *Engine, t *testing.T) { + err := engine.Sync(&CreatedUpdated{}) + if err != nil { + t.Error(err) + panic(err) + } + + c := &CreatedUpdated{Name: "test"} + _, err = engine.Insert(c) + if err != nil { + t.Error(err) + panic(err) + } + + c2 := new(CreatedUpdated) + has, err := engine.Id(c.Id).Get(c2) + if err != nil { + t.Error(err) + panic(err) + } + + if !has { + panic(errors.New("no id")) + } + + c2.Value -= 1 + _, err = engine.Id(c2.Id).Update(c2) + if err != nil { + t.Error(err) + panic(err) + } +} + func testAll(engine *Engine, t *testing.T) { fmt.Println("-------------- directCreateTable --------------") directCreateTable(engine, t) @@ -1800,6 +1842,8 @@ func testAll2(engine *Engine, t *testing.T) { testTime(engine, t) fmt.Println("-------------- testPrefixTableName --------------") testPrefixTableName(engine, t) + fmt.Println("-------------- testCreatedUpdated --------------") + testCreatedUpdated(engine, t) fmt.Println("-------------- transaction --------------") transaction(engine, t) } diff --git a/statement.go b/statement.go index 1dc06dc6..8400f0f8 100644 --- a/statement.go +++ b/statement.go @@ -116,6 +116,122 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { return statement } +func (statement *Statement) genFields(bean interface{}) map[string]interface{} { + results := make(map[string]interface{}) + table := statement.Engine.autoMap(bean) + for _, col := range table.Columns { + fieldValue := col.ValueOf(bean) + fieldType := reflect.TypeOf(fieldValue.Interface()) + var val interface{} + switch fieldType.Kind() { + case reflect.Bool: + if allUseBool { + val = fieldValue.Interface() + } else if _, ok := boolColumnMap[col.Name]; ok { + val = fieldValue.Interface() + } else { + // if a bool in a struct, it will not be as a condition because it default is false, + // please use Where() instead + continue + } + case reflect.String: + if fieldValue.String() == "" { + continue + } + // for MyString, should convert to string or panic + if fieldType.String() != reflect.String.String() { + val = fieldValue.String() + } else { + val = fieldValue.Interface() + } + case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64: + if fieldValue.Int() == 0 { + continue + } + val = fieldValue.Interface() + case reflect.Float32, reflect.Float64: + if fieldValue.Float() == 0.0 { + continue + } + val = fieldValue.Interface() + case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64: + if fieldValue.Uint() == 0 { + continue + } + val = fieldValue.Interface() + case reflect.Struct: + if fieldType == reflect.TypeOf(time.Now()) { + t := fieldValue.Interface().(time.Time) + if t.IsZero() || !fieldValue.IsValid() { + continue + } + var str string + if col.SQLType.Name == Time { + s := t.UTC().Format("2006-01-02 15:04:05") + val = s[11:19] + } else if col.SQLType.Name == Date { + str = t.Format("2006-01-02") + val = str + } else { + val = t + } + } else { + engine.autoMapType(fieldValue.Type()) + if table, ok := engine.Tables[fieldValue.Type()]; ok { + pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName) + if pkField.Int() != 0 { + val = pkField.Interface() + } else { + continue + } + } else { + val = fieldValue.Interface() + } + } + case reflect.Array, reflect.Slice, reflect.Map: + if fieldValue == reflect.Zero(fieldType) { + continue + } + if fieldValue.IsNil() || !fieldValue.IsValid() { + continue + } + + if col.SQLType.IsText() { + bytes, err := json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogSQL(err) + continue + } + val = string(bytes) + } else if col.SQLType.IsBlob() { + var bytes []byte + var err error + if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) && + fieldType.Elem().Kind() == reflect.Uint8 { + if fieldValue.Len() > 0 { + val = fieldValue.Bytes() + } else { + continue + } + } else { + bytes, err = json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogSQL(err) + continue + } + val = bytes + } + } else { + continue + } + default: + val = fieldValue.Interface() + } + results[col.Name] = val + } + return results +} + // Auto generating conditions according a struct func buildConditions(engine *Engine, table *Table, bean interface{}, includeVersion bool, allUseBool bool, boolColumnMap map[string]bool) ([]string, []interface{}) { colNames := make([]string, 0)