sql_mapping.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package sql
  2. import (
  3. "errors"
  4. "git.sxidc.com/go-tools/utils/strutils"
  5. "github.com/iancoleman/strcase"
  6. "reflect"
  7. "strings"
  8. "time"
  9. )
  10. const (
  11. sqlMappingDefaultKeyColumnName = "id"
  12. sqlMappingDefaultJoinWith = "::"
  13. sqlMappingTagPartSeparator = ";"
  14. sqlMappingTagPartKeyValueSeparator = ":"
  15. )
  16. const (
  17. sqlMappingTagKey = "sqlmapping"
  18. sqlMappingIgnore = "-"
  19. sqlMappingColumn = "column"
  20. sqlMappingKey = "key"
  21. sqlMappingNotUpdate = "notUpdate"
  22. sqlMappingUpdateClear = "updateClear"
  23. sqlMappingAes = "aes"
  24. sqlMappingJoinWith = "joinWith"
  25. )
  26. type Mapping struct {
  27. MappingElement map[string]any
  28. }
  29. type MappingColumn struct {
  30. Name string
  31. IsKey bool
  32. CanUpdate bool
  33. CanUpdateClear bool
  34. AESKey string
  35. JoinWith string
  36. // 原字段的反射结构
  37. OriginFieldType reflect.Type
  38. OriginFieldValue reflect.Value
  39. // 值类型的反射结构
  40. FieldTypeElem reflect.Type
  41. FieldValueElem reflect.Value
  42. }
  43. func ParseSqlMappingTag(e any) (*Mapping, error) {
  44. if e == nil {
  45. return nil, errors.New("没有传递实体")
  46. }
  47. entityType := reflect.TypeOf(e)
  48. if entityType.Kind() == reflect.Ptr {
  49. entityType = entityType.Elem()
  50. }
  51. if entityType.Kind() != reflect.Struct {
  52. return nil, errors.New("传递的实体不是结构类型")
  53. }
  54. entityValue := reflect.ValueOf(e)
  55. if entityValue.Kind() == reflect.Ptr {
  56. entityValue = entityValue.Elem()
  57. }
  58. sqlMapping := new(Mapping)
  59. sqlMapping.MappingElement = make(map[string]any)
  60. fieldNum := entityType.NumField()
  61. for i := 0; i < fieldNum; i++ {
  62. field := entityType.Field(i)
  63. fieldValue := entityValue.Field(i)
  64. element, err := parseSqlMappingElement(field, fieldValue)
  65. if err != nil {
  66. return nil, err
  67. }
  68. if element == nil {
  69. continue
  70. }
  71. sqlMapping.MappingElement[field.Name] = element
  72. }
  73. return sqlMapping, nil
  74. }
  75. func parseSqlMappingElement(field reflect.StructField, fieldValue reflect.Value) (any, error) {
  76. sqlMappingTag := field.Tag.Get(sqlMappingTagKey)
  77. if sqlMappingTag == sqlMappingIgnore {
  78. return nil, nil
  79. }
  80. fieldValueTypeElem := field.Type
  81. if field.Type.Kind() == reflect.Ptr {
  82. fieldValueTypeElem = field.Type.Elem()
  83. }
  84. fieldValueElem := fieldValue
  85. if fieldValue.Kind() == reflect.Ptr {
  86. if !fieldValue.IsValid() || fieldValue.IsNil() {
  87. fieldValueElem = reflect.New(fieldValueTypeElem).Elem()
  88. } else {
  89. fieldValueElem = fieldValue.Elem()
  90. }
  91. }
  92. if fieldValueTypeElem.Kind() == reflect.Struct && fieldValueTypeElem != reflect.TypeOf(time.Time{}) {
  93. return ParseSqlMappingTag(fieldValueElem.Interface())
  94. }
  95. sqlColumn := &MappingColumn{
  96. Name: strcase.ToSnake(field.Name),
  97. IsKey: false,
  98. CanUpdate: true,
  99. CanUpdateClear: false,
  100. AESKey: "",
  101. JoinWith: sqlMappingDefaultJoinWith,
  102. OriginFieldType: field.Type,
  103. OriginFieldValue: fieldValue,
  104. FieldTypeElem: fieldValueTypeElem,
  105. FieldValueElem: fieldValueElem,
  106. }
  107. if sqlColumn.Name == sqlMappingDefaultKeyColumnName {
  108. sqlColumn.IsKey = true
  109. sqlColumn.CanUpdate = false
  110. }
  111. if strutils.IsStringEmpty(sqlMappingTag) {
  112. return sqlColumn, nil
  113. }
  114. sqlMappingParts := strings.Split(sqlMappingTag, sqlMappingTagPartSeparator)
  115. if sqlMappingParts != nil || len(sqlMappingParts) != 0 {
  116. for _, sqlMappingPart := range sqlMappingParts {
  117. sqlPartKeyValue := strings.SplitN(strings.TrimSpace(sqlMappingPart), sqlMappingTagPartKeyValueSeparator, 2)
  118. if sqlPartKeyValue != nil && len(sqlPartKeyValue) == 2 && strutils.IsStringNotEmpty(sqlPartKeyValue[1]) {
  119. sqlPartKeyValue[1] = strings.Trim(sqlPartKeyValue[1], "'")
  120. }
  121. switch sqlPartKeyValue[0] {
  122. case sqlMappingColumn:
  123. if strutils.IsStringEmpty(sqlPartKeyValue[1]) {
  124. return nil, errors.New("column没有赋值列名")
  125. }
  126. sqlColumn.Name = sqlPartKeyValue[1]
  127. case sqlMappingKey:
  128. sqlColumn.IsKey = true
  129. sqlColumn.CanUpdate = false
  130. case sqlMappingNotUpdate:
  131. sqlColumn.CanUpdate = false
  132. sqlColumn.CanUpdateClear = false
  133. case sqlMappingUpdateClear:
  134. if !sqlColumn.CanUpdate {
  135. sqlColumn.CanUpdateClear = false
  136. } else {
  137. sqlColumn.CanUpdateClear = true
  138. }
  139. case sqlMappingAes:
  140. if len(sqlPartKeyValue[1]) != 32 {
  141. return nil, errors.New("AES密钥长度应该为32个字节")
  142. }
  143. sqlColumn.AESKey = sqlPartKeyValue[1]
  144. case sqlMappingJoinWith:
  145. if strutils.IsStringEmpty(sqlPartKeyValue[1]) {
  146. return nil, errors.New(sqlMappingJoinWith + "没有赋值分隔符")
  147. }
  148. if fieldValueTypeElem.Kind() != reflect.Slice || fieldValueTypeElem.Elem().Kind() != reflect.String {
  149. return nil, errors.New(sqlMappingJoinWith + "应该添加在[]string字段上")
  150. }
  151. sqlColumn.JoinWith = sqlPartKeyValue[1]
  152. default:
  153. continue
  154. }
  155. }
  156. }
  157. return sqlColumn, nil
  158. }