|
|
@@ -0,0 +1,134 @@
|
|
|
+package data_mapping
|
|
|
+
|
|
|
+import (
|
|
|
+ "errors"
|
|
|
+ "github.com/iancoleman/strcase"
|
|
|
+ "reflect"
|
|
|
+ "strings"
|
|
|
+)
|
|
|
+
|
|
|
+type DataMapping struct {
|
|
|
+ Name string
|
|
|
+ SqlMapping *SqlMapping
|
|
|
+}
|
|
|
+
|
|
|
+func ParseDataMapping(e any) (*DataMapping, error) {
|
|
|
+ if e == nil {
|
|
|
+ return nil, errors.New("没有传递实体")
|
|
|
+ }
|
|
|
+
|
|
|
+ entityType := reflect.TypeOf(e)
|
|
|
+ if entityType.Kind() == reflect.Ptr {
|
|
|
+ entityType = entityType.Elem()
|
|
|
+ }
|
|
|
+
|
|
|
+ if entityType.Kind() != reflect.Struct {
|
|
|
+ return nil, errors.New("传递的不是实体结构")
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlMapping, err := parseSqlMapping(entityType)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return &DataMapping{
|
|
|
+ Name: entityType.String(),
|
|
|
+ SqlMapping: sqlMapping,
|
|
|
+ }, nil
|
|
|
+}
|
|
|
+
|
|
|
+const (
|
|
|
+ sqlMappingTagPartSeparator = ";"
|
|
|
+ sqlMappingTagPartKeyValueSeparator = ":"
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
+ sqlMappingTagKey = "sqlmapping"
|
|
|
+ sqlMappingIgnore = "-"
|
|
|
+ sqlMappingColumn = "column"
|
|
|
+ sqlMappingKey = "key"
|
|
|
+ sqlMappingNotUpdate = "notUpdate"
|
|
|
+ sqlMappingUpdateClear = "updateClear"
|
|
|
+ sqlMappingNotQuery = "notQuery"
|
|
|
+ sqlMappingQueryConditionCallback = "queryConditionCallback"
|
|
|
+)
|
|
|
+
|
|
|
+type SqlMapping struct {
|
|
|
+ ColumnMap map[string]SqlColumn
|
|
|
+}
|
|
|
+
|
|
|
+func parseSqlMapping(entityType reflect.Type) (*SqlMapping, error) {
|
|
|
+ sqlMapping := new(SqlMapping)
|
|
|
+ sqlMapping.ColumnMap = make(map[string]SqlColumn)
|
|
|
+
|
|
|
+ fieldNum := entityType.NumField()
|
|
|
+ for i := 0; i < fieldNum; i++ {
|
|
|
+ sqlColumn, err := parseSqlColumn(entityType.Field(i))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if sqlColumn == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlMapping.ColumnMap[sqlColumn.Name] = *sqlColumn
|
|
|
+ }
|
|
|
+
|
|
|
+ return sqlMapping, nil
|
|
|
+}
|
|
|
+
|
|
|
+type SqlColumn struct {
|
|
|
+ Name string
|
|
|
+ IsKey bool
|
|
|
+ CanUpdate bool
|
|
|
+ CanUpdateClear bool
|
|
|
+ CanQuery bool
|
|
|
+ NeedQueryConditionCallback bool
|
|
|
+}
|
|
|
+
|
|
|
+func parseSqlColumn(field reflect.StructField) (*SqlColumn, error) {
|
|
|
+ sqlColumn := &SqlColumn{
|
|
|
+ Name: strcase.ToSnake(field.Name),
|
|
|
+ IsKey: false,
|
|
|
+ CanUpdate: true,
|
|
|
+ CanUpdateClear: false,
|
|
|
+ CanQuery: true,
|
|
|
+ NeedQueryConditionCallback: false,
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlMappingTag, ok := field.Tag.Lookup(sqlMappingTagKey)
|
|
|
+ if !ok {
|
|
|
+ return sqlColumn, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ if sqlMappingTag == sqlMappingIgnore {
|
|
|
+ return nil, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlMappingParts := strings.Split(sqlMappingTag, sqlMappingTagPartSeparator)
|
|
|
+ if sqlMappingParts != nil || len(sqlMappingParts) != 0 {
|
|
|
+ for _, sqlMappingPart := range sqlMappingParts {
|
|
|
+ sqlPartKeyValue := strings.Split(strings.TrimSpace(sqlMappingPart), sqlMappingTagPartKeyValueSeparator)
|
|
|
+ switch sqlPartKeyValue[0] {
|
|
|
+ case sqlMappingColumn:
|
|
|
+ sqlColumn.Name = strings.TrimSpace(sqlPartKeyValue[1])
|
|
|
+ case sqlMappingKey:
|
|
|
+ sqlColumn.IsKey = true
|
|
|
+ sqlColumn.CanUpdate = false
|
|
|
+ case sqlMappingNotUpdate:
|
|
|
+ sqlColumn.CanUpdate = false
|
|
|
+ case sqlMappingUpdateClear:
|
|
|
+ sqlColumn.CanUpdateClear = true
|
|
|
+ case sqlMappingNotQuery:
|
|
|
+ sqlColumn.CanQuery = false
|
|
|
+ case sqlMappingQueryConditionCallback:
|
|
|
+ sqlColumn.NeedQueryConditionCallback = true
|
|
|
+ default:
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return sqlColumn, nil
|
|
|
+}
|