mirror of
https://gitee.com/johng/gf
synced 2026-07-06 13:42:46 +08:00
fix(database/gdb): fix iTableName interface detection when using WithAll with .Scan on reflect.Value objects (#4606)
fix(gdb/getTableNameFromOrmTag): 修复在使用WithAll, 并且使用.Scan传入对象的情况下,
无法识别该对象字段是否实现了iTableName的接口. 因为该情况下, 传入的object是reflect.Value.
示例如下:
type MaterialDetail struct {
*entity.Material
SourceFile MaterialSourceFileDetail json:"source_file"
orm:"with:id=source_file_id"
}
type MaterialSourceFileDetail struct {
*entity.MaterialSourceFile
}
func (MaterialSourceFileDetail) TableName() string {
return dao.MaterialSourceFile.Table()
}
func foo(ctx context.Context) {
err = dao.Material.Ctx(ctx).WithAll().
Where(dao.Material.Columns().MaterialId, materialId).
Scan(&material)
}
这种情况下, 传入getTableNameFromOrmTag的object是reflect.Value, 而不是对象本身.
这会导致识别出MaterialSourceFileDetail已经实现了iTableName接口, 无法获取到正确的表名.
---------
Co-authored-by: hailaz <739476267@qq.com>
This commit is contained in:
@ -151,13 +151,26 @@ func isDoStruct(object any) bool {
|
||||
// getTableNameFromOrmTag retrieves and returns the table name from struct object.
|
||||
func getTableNameFromOrmTag(object any) string {
|
||||
var tableName string
|
||||
// Use the interface value.
|
||||
if r, ok := object.(iTableName); ok {
|
||||
tableName = r.TableName()
|
||||
var actualObj = object
|
||||
|
||||
if rv, ok := object.(reflect.Value); ok {
|
||||
// Check if reflect.Value is valid
|
||||
if rv.IsValid() && rv.CanInterface() {
|
||||
actualObj = rv.Interface()
|
||||
} else {
|
||||
// If reflect.Value is invalid, we cannot proceed with interface checks
|
||||
return ""
|
||||
}
|
||||
}
|
||||
// User meta data tag "orm".
|
||||
if tableName == "" {
|
||||
if ormTag := gmeta.Get(object, OrmTagForStruct); !ormTag.IsEmpty() {
|
||||
|
||||
// Check iTableName interface
|
||||
if actualObj != nil {
|
||||
if r, ok := actualObj.(iTableName); ok {
|
||||
return r.TableName()
|
||||
}
|
||||
|
||||
// User meta data tag "orm".
|
||||
if ormTag := gmeta.Get(actualObj, OrmTagForStruct); !ormTag.IsEmpty() {
|
||||
match, _ := gregex.MatchString(
|
||||
fmt.Sprintf(`%s\s*:\s*([^,]+)`, OrmTagForTable),
|
||||
ormTag.String(),
|
||||
@ -166,17 +179,19 @@ func getTableNameFromOrmTag(object any) string {
|
||||
tableName = match[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use the struct name of snake case.
|
||||
if tableName == "" {
|
||||
if t, err := gstructs.StructType(object); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
tableName = gstr.CaseSnakeFirstUpper(
|
||||
gstr.StrEx(t.String(), "."),
|
||||
)
|
||||
|
||||
// Use the struct name of snake case.
|
||||
if tableName == "" {
|
||||
if t, err := gstructs.StructType(actualObj); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
tableName = gstr.CaseSnakeFirstUpper(
|
||||
gstr.StrEx(t.String(), "."),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tableName
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user