Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持使用组合定义模型 #99

Merged
merged 3 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [eorm:修改 ErrNoRows 的语义,只有在 Get 才会返回](https://github.com/gotomicro/eorm/pull/80)
- [all: Field 取代 FieldByName](https://github.com/gotomicro/eorm/pull/90)
- [eorm: Delete的执行完成](https://github.com/gotomicro/eorm/pull/90)
- [eorm: 支持使用组合定义模型](https://github.com/gotomicro/eorm/pull/99)

### 文档, 代码质量以及文档
- [Add examples and docs for Aggregate and Assign](https://github.com/gotomicro/eorm/pull/50)
Expand Down
7 changes: 7 additions & 0 deletions internal/errs/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ var (
// ErrTooManyColumns 过多列
// 一般是查询的列多于结构体的列
ErrTooManyColumns = errors.New("eorm: 过多列")

// ErrCombinationIsNotStruct 不支持的组合类型,eorm 只支持结构体组合
ErrCombinationIsNotStruct = errors.New("eorm: 不支持的组合类型,eorm 只支持结构体组合")
)

func NewFieldConflictError(field string) error {
return fmt.Errorf("eorm: `%s`列冲突", field)
}

// NewInvalidFieldError 返回代表未知字段的错误。
// 通常来说,是字段名没写对
// 注意区分 NewInvalidColumnError
Expand Down
71 changes: 54 additions & 17 deletions internal/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"strings"
"sync"

"github.com/gotomicro/eorm/internal/errs"

// nolint
"unicode"
)
Expand Down Expand Up @@ -102,10 +104,38 @@ func (t *tagMetaRegistry) Get(table interface{}) (*TableMeta, error) {
func (t *tagMetaRegistry) Register(table interface{}, opts ...TableMetaOption) (*TableMeta, error) {
rtype := reflect.TypeOf(table)
v := rtype.Elem()
var columnMetas []*ColumnMeta
lens := v.NumField()
columnMetas := make([]*ColumnMeta, 0, lens)
fieldMap := make(map[string]*ColumnMeta, lens)
columnMap := make(map[string]*ColumnMeta, lens)
err := t.parseFields(v, []int{}, &columnMetas, fieldMap, 0)
if err != nil {
return nil, err
}

for _, columnMeta := range columnMetas {
columnMap[columnMeta.ColumnName] = columnMeta
}

tableMeta := &TableMeta{
Columns: columnMetas,
TableName: underscoreName(v.Name()),
Typ: rtype,
FieldMap: fieldMap,
ColumnMap: columnMap,
}
for _, o := range opts {
o(tableMeta)
}
t.metas.Store(rtype, tableMeta)
return tableMeta, nil

}

func (t *tagMetaRegistry) parseFields(v reflect.Type, fieldIndexes []int,
columnMetas *[]*ColumnMeta, fieldMap map[string]*ColumnMeta,
pOffset uintptr) error {
lens := v.NumField()
for i := 0; i < lens; i++ {
structField := v.Field(i)
tag := structField.Tag.Get("eorm")
Expand All @@ -124,32 +154,39 @@ func (t *tagMetaRegistry) Register(table interface{}, opts ...TableMetaOption) (
// skip the field.
continue
}
// 检查列有没有冲突
if fieldMap[structField.Name] != nil {
return errs.NewFieldConflictError(v.Name() + "." + structField.Name)
}
// 是组合
if structField.Anonymous {
// 不支持使用指针的组合
if structField.Type.Kind() != reflect.Struct {
return errs.ErrCombinationIsNotStruct
}
// 递归解析
o := structField.Offset + pOffset
err := t.parseFields(structField.Type, append(fieldIndexes, i), columnMetas, fieldMap, o)
if err != nil {
return err
}
continue
}

columnMeta := &ColumnMeta{
ColumnName: underscoreName(structField.Name),
FieldName: structField.Name,
Typ: structField.Type,
IsAutoIncrement: isAuto,
IsPrimaryKey: isKey,
Offset: structField.Offset,
Offset: structField.Offset + pOffset,
IsHolderType: structField.Type.AssignableTo(scannerType) && structField.Type.AssignableTo(driverValuerType),
FieldIndexes: []int{i},
FieldIndexes: append(fieldIndexes, i),
flyhigher139 marked this conversation as resolved.
Show resolved Hide resolved
flycash marked this conversation as resolved.
Show resolved Hide resolved
}
columnMetas = append(columnMetas, columnMeta)
*columnMetas = append(*columnMetas, columnMeta)
fieldMap[columnMeta.FieldName] = columnMeta
columnMap[columnMeta.ColumnName] = columnMeta
}
tableMeta := &TableMeta{
Columns: columnMetas,
TableName: underscoreName(v.Name()),
Typ: rtype,
FieldMap: fieldMap,
ColumnMap: columnMap,
}
for _, o := range opts {
o(tableMeta)
}
t.metas.Store(rtype, tableMeta)
return tableMeta, nil
return nil
}

// IgnoreFieldsOption function provide an option to ignore some fields when register table.
Expand Down
Loading