add cascade non-int64 primary key support & bug fixed #178
This commit is contained in:
parent
7e3812ca28
commit
5cdb680945
|
@ -990,8 +990,12 @@ func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) {
|
|||
}
|
||||
|
||||
func (engine *Engine) IdOf(bean interface{}) core.PK {
|
||||
table := engine.TableInfo(bean)
|
||||
v := reflect.Indirect(reflect.ValueOf(bean))
|
||||
return engine.IdOfV(reflect.ValueOf(bean))
|
||||
}
|
||||
|
||||
func (engine *Engine) IdOfV(rv reflect.Value) core.PK {
|
||||
v := reflect.Indirect(rv)
|
||||
table := engine.autoMapType(v)
|
||||
pk := make([]interface{}, len(table.PrimaryKeys))
|
||||
for i, col := range table.PKColumns() {
|
||||
pkField := v.FieldByName(col.FieldName)
|
||||
|
|
37
helpers.go
37
helpers.go
|
@ -11,6 +11,43 @@ import (
|
|||
"github.com/go-xorm/core"
|
||||
)
|
||||
|
||||
func isZero(k interface{}) bool {
|
||||
switch k.(type) {
|
||||
case int:
|
||||
return k.(int) == 0
|
||||
case int8:
|
||||
return k.(int8) == 0
|
||||
case int16:
|
||||
return k.(int16) == 0
|
||||
case int32:
|
||||
return k.(int32) == 0
|
||||
case int64:
|
||||
return k.(int64) == 0
|
||||
case uint:
|
||||
return k.(uint) == 0
|
||||
case uint8:
|
||||
return k.(uint8) == 0
|
||||
case uint16:
|
||||
return k.(uint16) == 0
|
||||
case uint32:
|
||||
return k.(uint32) == 0
|
||||
case uint64:
|
||||
return k.(uint64) == 0
|
||||
case string:
|
||||
return k.(string) == ""
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isPKZero(pk core.PK) bool {
|
||||
for _, k := range pk {
|
||||
if isZero(k) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func indexNoCase(s, sep string) int {
|
||||
return strings.Index(strings.ToLower(s), strings.ToLower(sep))
|
||||
}
|
||||
|
|
|
@ -218,6 +218,9 @@ func (db *mysql) SqlType(c *core.Column) string {
|
|||
res += ")"
|
||||
case core.NVarchar:
|
||||
res = core.Varchar
|
||||
case core.Uuid:
|
||||
res = core.Varchar
|
||||
c.Length = 40
|
||||
default:
|
||||
res = t
|
||||
}
|
||||
|
|
196
session.go
196
session.go
|
@ -648,11 +648,6 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
|
|||
return false, ErrCacheFailed
|
||||
}
|
||||
|
||||
// TODO: remove this after support multi pk cache
|
||||
/*if len(session.Statement.RefTable.PrimaryKeys) != 1 {
|
||||
return false, ErrCacheFailed
|
||||
}*/
|
||||
|
||||
for _, filter := range session.Engine.dialect.Filters() {
|
||||
sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
|
||||
}
|
||||
|
@ -1775,18 +1770,45 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
|
|||
} else if session.Statement.UseCascade {
|
||||
table := session.Engine.autoMapType(*fieldValue)
|
||||
if table != nil {
|
||||
var x int64
|
||||
if rawValueType.Kind() == reflect.Int64 {
|
||||
x = vv.Int()
|
||||
if len(table.PrimaryKeys) > 1 {
|
||||
panic("unsupported composited primary key cascade")
|
||||
}
|
||||
if x != 0 {
|
||||
var pk = make(core.PK, len(table.PrimaryKeys))
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Int64:
|
||||
pk[0] = vv.Int()
|
||||
case reflect.Int:
|
||||
pk[0] = int(vv.Int())
|
||||
case reflect.Int32:
|
||||
pk[0] = int32(vv.Int())
|
||||
case reflect.Int16:
|
||||
pk[0] = int16(vv.Int())
|
||||
case reflect.Int8:
|
||||
pk[0] = int8(vv.Int())
|
||||
case reflect.Uint64:
|
||||
pk[0] = vv.Uint()
|
||||
case reflect.Uint:
|
||||
pk[0] = uint(vv.Uint())
|
||||
case reflect.Uint32:
|
||||
pk[0] = uint32(vv.Uint())
|
||||
case reflect.Uint16:
|
||||
pk[0] = uint16(vv.Uint())
|
||||
case reflect.Uint8:
|
||||
pk[0] = uint8(vv.Uint())
|
||||
case reflect.String:
|
||||
pk[0] = vv.String()
|
||||
default:
|
||||
panic("unsupported primary key type cascade")
|
||||
}
|
||||
|
||||
if !isPKZero(pk) {
|
||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||
// property to be fetched lazily
|
||||
structInter := reflect.New(fieldValue.Type())
|
||||
newsession := session.Engine.NewSession()
|
||||
defer newsession.Close()
|
||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
||||
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2415,18 +2437,86 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
|
|||
} else if session.Statement.UseCascade {
|
||||
table := session.Engine.autoMapType(*fieldValue)
|
||||
if table != nil {
|
||||
if len(table.PrimaryKeys) > 1 {
|
||||
panic("unsupported composited primary key cascade")
|
||||
}
|
||||
var pk = make(core.PK, len(table.PrimaryKeys))
|
||||
rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Int64:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
if x != 0 {
|
||||
pk[0] = x
|
||||
case reflect.Int:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = int(x)
|
||||
case reflect.Int32:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = int32(x)
|
||||
case reflect.Int16:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = int16(x)
|
||||
case reflect.Int8:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = int8(x)
|
||||
case reflect.Uint64:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = x
|
||||
case reflect.Uint:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = uint(x)
|
||||
case reflect.Uint32:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = uint32(x)
|
||||
case reflect.Uint16:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = uint16(x)
|
||||
case reflect.Uint8:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
pk[0] = uint8(x)
|
||||
case reflect.String:
|
||||
pk[0] = string(data)
|
||||
default:
|
||||
panic("unsupported primary key type cascade")
|
||||
}
|
||||
|
||||
if !isPKZero(pk) {
|
||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||
// property to be fetched lazily
|
||||
structInter := reflect.New(fieldValue.Type())
|
||||
newsession := session.Engine.NewSession()
|
||||
defer newsession.Close()
|
||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
||||
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2690,17 +2780,95 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
|
|||
structInter := reflect.New(fieldType.Elem())
|
||||
table := session.Engine.autoMapType(structInter.Elem())
|
||||
if table != nil {
|
||||
if len(table.PrimaryKeys) > 1 {
|
||||
panic("unsupported composited primary key cascade")
|
||||
}
|
||||
var pk = make(core.PK, len(table.PrimaryKeys))
|
||||
rawValueType := table.ColumnType(table.PKColumns()[0].FieldName)
|
||||
switch rawValueType.Kind() {
|
||||
case reflect.Int64:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
if x != 0 {
|
||||
|
||||
pk[0] = x
|
||||
case reflect.Int:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = int(x)
|
||||
case reflect.Int32:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = int32(x)
|
||||
case reflect.Int16:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = int16(x)
|
||||
case reflect.Int8:
|
||||
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = x
|
||||
case reflect.Uint64:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = x
|
||||
case reflect.Uint:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = uint(x)
|
||||
case reflect.Uint32:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = uint32(x)
|
||||
case reflect.Uint16:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = uint16(x)
|
||||
case reflect.Uint8:
|
||||
x, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
||||
}
|
||||
|
||||
pk[0] = uint8(x)
|
||||
case reflect.String:
|
||||
pk[0] = string(data)
|
||||
default:
|
||||
panic("unsupported primary key type cascade")
|
||||
}
|
||||
|
||||
if !isPKZero(pk) {
|
||||
// !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch
|
||||
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||
// property to be fetched lazily
|
||||
newsession := session.Engine.NewSession()
|
||||
defer newsession.Close()
|
||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
||||
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -589,6 +589,8 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
|||
continue
|
||||
}
|
||||
val = engine.FormatTime(col.SQLType.Name, t)
|
||||
} else if _, ok := reflect.New(fieldType).Interface().(core.Conversion); ok {
|
||||
continue
|
||||
} else {
|
||||
engine.autoMapType(fieldValue)
|
||||
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
||||
|
|
Loading…
Reference in New Issue