diff --git a/VERSION b/VERSION index af3e71ec..62af1c7f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -xorm v0.4.3.0520 +xorm v0.4.3.0806 diff --git a/processors.go b/processors.go index 18071c1f..8f95ae3b 100644 --- a/processors.go +++ b/processors.go @@ -23,6 +23,10 @@ type BeforeSetProcessor interface { BeforeSet(string, Cell) } +type AfterSetProcessor interface { + AfterSet(string, Cell) +} + // !nashtsai! TODO enable BeforeValidateProcessor when xorm start to support validations //// Executed before an object is validated //type BeforeValidateProcessor interface { diff --git a/session.go b/session.go index b50c46cf..af146496 100644 --- a/session.go +++ b/session.go @@ -1626,6 +1626,14 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount } } + defer func() { + if b, hasAfterSet := bean.(AfterSetProcessor); hasAfterSet { + for ii, key := range fields { + b.AfterSet(key, Cell(scanResults[ii].(*interface{}))) + } + } + }() + var tempMap = make(map[string]int) for ii, key := range fields { var idx int @@ -1675,7 +1683,6 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount hasAssigned := false switch fieldType.Kind() { - case reflect.Complex64, reflect.Complex128: if rawValueType.Kind() == reflect.String { hasAssigned = true @@ -1686,6 +1693,15 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount return err } fieldValue.Set(x.Elem()) + } else if rawValueType.Kind() == reflect.Slice { + hasAssigned = true + x := reflect.New(fieldType) + err := json.Unmarshal(vv.Bytes(), x.Interface()) + if err != nil { + session.Engine.LogError(err) + return err + } + fieldValue.Set(x.Elem()) } case reflect.Slice, reflect.Array: switch rawValueType.Kind() { @@ -1730,6 +1746,7 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount fieldValue.SetUint(uint64(vv.Int())) } case reflect.Struct: + col := table.GetColumn(key) if fieldType.ConvertibleTo(core.TimeType) { if rawValueType == core.TimeType { hasAssigned = true @@ -1763,11 +1780,31 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount session.Engine.LogError("sql.Sanner error:", err.Error()) hasAssigned = false } + } else if col.SQLType.IsJson() { + if rawValueType.Kind() == reflect.String { + hasAssigned = true + x := reflect.New(fieldType) + err := json.Unmarshal([]byte(vv.String()), x.Interface()) + if err != nil { + session.Engine.LogError(err) + return err + } + fieldValue.Set(x.Elem()) + } else if rawValueType.Kind() == reflect.Slice { + hasAssigned = true + x := reflect.New(fieldType) + err := json.Unmarshal(vv.Bytes(), x.Interface()) + if err != nil { + session.Engine.LogError(err) + return err + } + fieldValue.Set(x.Elem()) + } } else if session.Statement.UseCascade { table := session.Engine.autoMapType(*fieldValue) if table != nil { - if len(table.PrimaryKeys) > 1 { - panic("unsupported composited primary key cascade") + if len(table.PrimaryKeys) != 1 { + panic("unsupported non or composited primary key cascade") } var pk = make(core.PK, len(table.PrimaryKeys)) @@ -2952,17 +2989,31 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val if len(fieldTable.PrimaryKeys) == 1 { pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName) return pkField.Interface(), nil - } else { - return 0, fmt.Errorf("no primary key for col %v", col.Name) } - } else { - // !! 增加支持driver.Valuer接口的结构,如sql.NullString - if v, ok := fieldValue.Interface().(driver.Valuer); ok { - return v.Value() - } - - return 0, fmt.Errorf("Unsupported type %v", fieldValue.Type()) + return 0, fmt.Errorf("no primary key for col %v", col.Name) } + // !! 增加支持driver.Valuer接口的结构,如sql.NullString + if v, ok := fieldValue.Interface().(driver.Valuer); ok { + return v.Value() + } + + if col.SQLType.IsText() { + bytes, err := json.Marshal(fieldValue.Interface()) + if err != nil { + session.Engine.LogError(err) + return 0, err + } + return string(bytes), nil + } else if col.SQLType.IsBlob() { + bytes, err := json.Marshal(fieldValue.Interface()) + if err != nil { + session.Engine.LogError(err) + return 0, err + } + return bytes, nil + } + + return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type()) case reflect.Complex64, reflect.Complex128: bytes, err := json.Marshal(fieldValue.Interface()) if err != nil { @@ -2996,9 +3047,8 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val } } return bytes, nil - } else { - return nil, ErrUnSupportedType } + return nil, ErrUnSupportedType case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return int64(fieldValue.Uint()), nil default: diff --git a/statement.go b/statement.go index 6919b6c5..c3e93eed 100644 --- a/statement.go +++ b/statement.go @@ -417,6 +417,9 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text { continue } + if col.SQLType.IsJson() { + continue + } var colName string if addedTableName { @@ -519,23 +522,43 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, continue } } else { - engine.autoMapType(fieldValue) - if table, ok := engine.Tables[fieldValue.Type()]; ok { - if len(table.PrimaryKeys) == 1 { - pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName) - // fix non-int pk issues - //if pkField.Int() != 0 { - if pkField.IsValid() && !isZero(pkField.Interface()) { - val = pkField.Interface() - } else { + if col.SQLType.IsJson() { + if col.SQLType.IsText() { + bytes, err := json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogError(err) continue } - } else { - //TODO: how to handler? - panic(fmt.Sprintln("not supported", fieldValue.Interface(), "as", table.PrimaryKeys)) + val = string(bytes) + } else if col.SQLType.IsBlob() { + var bytes []byte + var err error + bytes, err = json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogError(err) + continue + } + val = bytes } } else { - val = fieldValue.Interface() + engine.autoMapType(fieldValue) + if table, ok := engine.Tables[fieldValue.Type()]; ok { + if len(table.PrimaryKeys) == 1 { + pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName) + // fix non-int pk issues + //if pkField.Int() != 0 { + if pkField.IsValid() && !isZero(pkField.Interface()) { + val = pkField.Interface() + } else { + continue + } + } else { + //TODO: how to handler? + panic(fmt.Sprintln("not supported", fieldValue.Interface(), "as", table.PrimaryKeys)) + } + } else { + val = fieldValue.Interface() + } } } case reflect.Array, reflect.Slice, reflect.Map: diff --git a/xorm.go b/xorm.go index 8e630b9a..341160c5 100644 --- a/xorm.go +++ b/xorm.go @@ -17,7 +17,7 @@ import ( ) const ( - Version string = "0.4.3.0627" + Version string = "0.4.3.0806" ) func regDrvsNDialects() bool {