Explorar o código

添加数据映射

yjp hai 1 ano
pai
achega
01ca98f8e6
Modificáronse 4 ficheiros con 194 adicións e 0 borrados
  1. 1 0
      go.mod
  2. 2 0
      go.sum
  3. 134 0
      sdk/data_mapping/data_mapping.go
  4. 57 0
      test/sdk_test.go

+ 1 - 0
go.mod

@@ -7,6 +7,7 @@ require (
 	git.sxidc.com/go-tools/utils v1.5.1
 	github.com/fatih/structs v1.1.0
 	github.com/golang/protobuf v1.5.4
+	github.com/iancoleman/strcase v0.3.0
 	github.com/mwitkow/go-proto-validators v0.3.2
 	google.golang.org/grpc v1.63.2
 	google.golang.org/protobuf v1.33.0

+ 2 - 0
go.sum

@@ -54,6 +54,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
+github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=

+ 134 - 0
sdk/data_mapping/data_mapping.go

@@ -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
+}

+ 57 - 0
test/sdk_test.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"git.sxidc.com/service-supports/ds-sdk/sdk"
+	"git.sxidc.com/service-supports/ds-sdk/sdk/data_mapping"
 	"git.sxidc.com/service-supports/ds-sdk/sdk/raw_sql_tpl"
 	"math/rand"
 	"strconv"
@@ -12,6 +13,13 @@ import (
 	"time"
 )
 
+type Class struct {
+	ID         string `sqlmapping:"key;"`
+	Name       string `sqlmapping:"update:canClear;notQuery;"`
+	StudentNum int    `sqlmapping:"column:student_num;notUpdate;queryConditionCallback;"`
+	Ignored    string `sqlmapping:"-"`
+}
+
 const (
 	token          = "IpTTwAQweh/BP51fz5CzWKQFaXHvZe6ewvk6yOcAOkU="
 	address        = "localhost"
@@ -342,3 +350,52 @@ func TestRawSqlTemplate(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestDataMapping(t *testing.T) {
+	dataMapping, err := data_mapping.ParseDataMapping(&Class{})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if dataMapping.Name != "main.Class" {
+		t.Fatal("dataMapping名称不正确")
+	}
+
+	if dataMapping.SqlMapping == nil {
+		t.Fatal("没有解析除SqlMapping")
+	}
+
+	for columnName, sqlColumn := range dataMapping.SqlMapping.ColumnMap {
+		if columnName != "id" && columnName != "name" && columnName != "student_num" {
+			t.Fatal("列名不正确")
+		}
+
+		if sqlColumn.Name != "id" && sqlColumn.Name != "name" && sqlColumn.Name != "student_num" {
+			t.Fatal("列名不正确")
+		}
+
+		if sqlColumn.Name != columnName {
+			t.Fatal("列名不正确")
+		}
+
+		if sqlColumn.IsKey && columnName != "id" {
+			t.Fatal("键字段不正确")
+		}
+
+		if !sqlColumn.CanUpdate && (columnName != "id" && columnName != "student_num") {
+			t.Fatal("不可更新字段不正确")
+		}
+
+		if sqlColumn.CanUpdateClear && columnName != "name" {
+			t.Fatal("可清除字段不正确")
+		}
+
+		if !sqlColumn.CanQuery && columnName != "name" {
+			t.Fatal("可清除字段不正确")
+		}
+
+		if sqlColumn.NeedQueryConditionCallback && columnName != "student_num" {
+			t.Fatal("可清除字段不正确")
+		}
+	}
+}