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 {
|
func (engine *Engine) IdOf(bean interface{}) core.PK {
|
||||||
table := engine.TableInfo(bean)
|
return engine.IdOfV(reflect.ValueOf(bean))
|
||||||
v := reflect.Indirect(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))
|
pk := make([]interface{}, len(table.PrimaryKeys))
|
||||||
for i, col := range table.PKColumns() {
|
for i, col := range table.PKColumns() {
|
||||||
pkField := v.FieldByName(col.FieldName)
|
pkField := v.FieldByName(col.FieldName)
|
||||||
|
|
37
helpers.go
37
helpers.go
|
@ -11,6 +11,43 @@ import (
|
||||||
"github.com/go-xorm/core"
|
"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 {
|
func indexNoCase(s, sep string) int {
|
||||||
return strings.Index(strings.ToLower(s), strings.ToLower(sep))
|
return strings.Index(strings.ToLower(s), strings.ToLower(sep))
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,6 +218,9 @@ func (db *mysql) SqlType(c *core.Column) string {
|
||||||
res += ")"
|
res += ")"
|
||||||
case core.NVarchar:
|
case core.NVarchar:
|
||||||
res = core.Varchar
|
res = core.Varchar
|
||||||
|
case core.Uuid:
|
||||||
|
res = core.Varchar
|
||||||
|
c.Length = 40
|
||||||
default:
|
default:
|
||||||
res = t
|
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
|
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() {
|
for _, filter := range session.Engine.dialect.Filters() {
|
||||||
sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
|
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 {
|
} else if session.Statement.UseCascade {
|
||||||
table := session.Engine.autoMapType(*fieldValue)
|
table := session.Engine.autoMapType(*fieldValue)
|
||||||
if table != nil {
|
if table != nil {
|
||||||
var x int64
|
if len(table.PrimaryKeys) > 1 {
|
||||||
if rawValueType.Kind() == reflect.Int64 {
|
panic("unsupported composited primary key cascade")
|
||||||
x = vv.Int()
|
|
||||||
}
|
}
|
||||||
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
|
// !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
|
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||||
// property to be fetched lazily
|
// property to be fetched lazily
|
||||||
structInter := reflect.New(fieldValue.Type())
|
structInter := reflect.New(fieldValue.Type())
|
||||||
newsession := session.Engine.NewSession()
|
newsession := session.Engine.NewSession()
|
||||||
defer newsession.Close()
|
defer newsession.Close()
|
||||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2415,18 +2437,86 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
|
||||||
} else if session.Statement.UseCascade {
|
} else if session.Statement.UseCascade {
|
||||||
table := session.Engine.autoMapType(*fieldValue)
|
table := session.Engine.autoMapType(*fieldValue)
|
||||||
if table != nil {
|
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)
|
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
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
|
// !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
|
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||||
// property to be fetched lazily
|
// property to be fetched lazily
|
||||||
structInter := reflect.New(fieldValue.Type())
|
structInter := reflect.New(fieldValue.Type())
|
||||||
newsession := session.Engine.NewSession()
|
newsession := session.Engine.NewSession()
|
||||||
defer newsession.Close()
|
defer newsession.Close()
|
||||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -2690,17 +2780,95 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
|
||||||
structInter := reflect.New(fieldType.Elem())
|
structInter := reflect.New(fieldType.Elem())
|
||||||
table := session.Engine.autoMapType(structInter.Elem())
|
table := session.Engine.autoMapType(structInter.Elem())
|
||||||
if table != nil {
|
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)
|
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("arg %v as int: %s", key, err.Error())
|
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
|
// !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
|
// however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne
|
||||||
// property to be fetched lazily
|
// property to be fetched lazily
|
||||||
newsession := session.Engine.NewSession()
|
newsession := session.Engine.NewSession()
|
||||||
defer newsession.Close()
|
defer newsession.Close()
|
||||||
has, err := newsession.Id(x).Get(structInter.Interface())
|
has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,6 +589,8 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val = engine.FormatTime(col.SQLType.Name, t)
|
val = engine.FormatTime(col.SQLType.Name, t)
|
||||||
|
} else if _, ok := reflect.New(fieldType).Interface().(core.Conversion); ok {
|
||||||
|
continue
|
||||||
} else {
|
} else {
|
||||||
engine.autoMapType(fieldValue)
|
engine.autoMapType(fieldValue)
|
||||||
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
|
Loading…
Reference in New Issue