sql_mapping.go 4.9 KB

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