2 Commits

Author SHA1 Message Date
ca03e37c18 fix(scan): 修复对struct存在重复属性导致的崩溃
新增了在递归scan对象属性的时候发现嵌套属性名称和当前属性名称一致的时候做了友好错误提示
2025-02-05 13:26:41 +08:00
dde9b6f74e feat: 去掉了批量查询时,结果为空的报错 2024-09-19 14:11:17 +08:00
4 changed files with 12 additions and 12 deletions

View File

@@ -73,6 +73,7 @@ INSERT INTO
### 查询映射 -- 示例 ### 查询映射 -- 示例
```go ```go
// 如果没有结果,会返回 sql.ErrNoRows
func QueryOne(db *sql.DB) (*User,error){ func QueryOne(db *sql.DB) (*User,error){
tdMapper := NewMapper() tdMapper := NewMapper()
@@ -89,8 +90,7 @@ func QueryOne(db *sql.DB) (*User,error){
return &user, nil return &user, nil
} }
// 如果查询结果数量为0则返回 sql.ErrNoRows // 如果查询结果数量为0不会返回错误
// var ErrNoRows = errors.New("sql: no rows in result set")
func QueryAll(db *sql.DB)([]*User, error) { func QueryAll(db *sql.DB)([]*User, error) {
tdMapper := NewMapper() tdMapper := NewMapper()

View File

@@ -65,7 +65,7 @@ func (b *Mapper) extractStructData(data ...any) (map[string][]*TableRowMateria,
} }
if tableName == "" { if tableName == "" {
return nil, fmt.Errorf("not import TableName() string func for struct type: %s", uniqueTypeName) return nil, fmt.Errorf("not func TableName() string func for struct type: %s", uniqueTypeName)
} }
} }
@@ -247,10 +247,6 @@ func (b *Mapper) ScanRowsWithContext(ctx context.Context, target any, rows *sql.
// 将新实例添加到slice中 // 将新实例添加到slice中
vf.Set(reflect.Append(vf, newStruct)) vf.Set(reflect.Append(vf, newStruct))
} }
if vf.Len() == 0 { // 如果slice为空返回 sql.ErrNoRows
return sql.ErrNoRows
}
return nil return nil
default: default:
return errors.New("target must be a pointer to a struct or a slice of structs") return errors.New("target must be a pointer to a struct or a slice of structs")
@@ -277,11 +273,11 @@ func (b *Mapper) scanRow(target reflect.Value, rows *sql.Rows) error {
dest := make([]interface{}, len(columns)) dest := make([]interface{}, len(columns))
for i, colName := range columns { for i, colName := range columns {
// 拿到缓存的字段索引 // 拿到缓存的字段索引
if idx, ok := mate.DBName2IndexCache[colName]; ok { idx, ok := mate.DBName2IndexCache[colName]
dest[i] = target.FieldByIndex(idx).Addr().Interface() if !ok {
} else {
return fmt.Errorf("no corresponding field found for column %s", colName) return fmt.Errorf("no corresponding field found for column %s", colName)
} }
dest[i] = target.FieldByIndex(idx).Addr().Interface()
} }
// 扫描数据 // 扫描数据

View File

@@ -58,7 +58,7 @@ func TestBuilderInsert(t *testing.T) {
Ts: time.Now(), LoadUnitId: "负载单体ID", PInt: &p, NullInt32: sql.NullInt32{Int32: 32, Valid: true}, Ts: time.Now(), LoadUnitId: "负载单体ID", PInt: &p, NullInt32: sql.NullInt32{Int32: 32, Valid: true},
}, },
&TaosUser{ &TaosUser{
TaosTAG: &TaosTAG{DevId: "User001", DevType: "User类型", DataType: "User数据类型001"}, TaosTAG: &TaosTAG{DevId: "User001", DevType: "User类型", DataType: "User数据类型001", Alias: "三儿"},
Ts: time.Now(), Name: "张三", Ts: time.Now(), Name: "张三",
}, &TaosUser{ }, &TaosUser{
TaosTAG: &TaosTAG{DevId: "User002", DevType: "User类型", DataType: "User数据类型002"}, TaosTAG: &TaosTAG{DevId: "User002", DevType: "User类型", DataType: "User数据类型002"},

View File

@@ -81,7 +81,11 @@ func scan(data interface{}) (*StructMate, error) {
continue continue
} }
sr.Field2IndexCache[field.Name] = append(sr.Field2IndexCache[field.Name], i) if len(sr.Field2IndexCache[field.Name]) > 0 {
return nil, fmt.Errorf("duplicate field [%s %s `db:%s`]", field.Name, field.Type.Name(), columnName)
}
sr.Field2IndexCache[field.Name] = append([]int{}, i)
sr.DBName2IndexCache[columnName] = append(sr.DBName2IndexCache[columnName], i) sr.DBName2IndexCache[columnName] = append(sr.DBName2IndexCache[columnName], i)
sr.Filed2DBNameCache[field.Name] = columnName sr.Filed2DBNameCache[field.Name] = columnName