sql_mapping.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. if !fieldValue.CanSet() {
  94. return nil, nil
  95. }
  96. fieldValue.Set(reflect.New(fieldValueTypeElem).Elem().Addr())
  97. }
  98. fieldValueElem = fieldValue.Elem()
  99. }
  100. if fieldValueTypeElem.Kind() == reflect.Struct && fieldValueTypeElem != reflect.TypeOf(time.Time{}) {
  101. return &MappingStruct{
  102. MappingTypesAndValues: MappingTypesAndValues{
  103. OriginFieldType: field.Type,
  104. OriginFieldValue: fieldValue,
  105. FieldTypeElem: fieldValueTypeElem,
  106. FieldValueElem: fieldValueElem,
  107. },
  108. }, nil
  109. }
  110. sqlColumn := &MappingColumn{
  111. Name: strcase.ToSnake(field.Name),
  112. IsKey: false,
  113. CanUpdate: true,
  114. CanUpdateClear: false,
  115. AESKey: "",
  116. JoinWith: sqlMappingDefaultJoinWith,
  117. MappingTypesAndValues: MappingTypesAndValues{
  118. OriginFieldType: field.Type,
  119. OriginFieldValue: fieldValue,
  120. FieldTypeElem: fieldValueTypeElem,
  121. FieldValueElem: fieldValueElem,
  122. },
  123. }
  124. if sqlColumn.Name == sqlMappingDefaultKeyColumnName {
  125. sqlColumn.IsKey = true
  126. sqlColumn.CanUpdate = false
  127. }
  128. if strutils.IsStringEmpty(sqlMappingTag) {
  129. return sqlColumn, nil
  130. }
  131. sqlMappingParts := strings.Split(sqlMappingTag, sqlMappingTagPartSeparator)
  132. if sqlMappingParts != nil || len(sqlMappingParts) != 0 {
  133. for _, sqlMappingPart := range sqlMappingParts {
  134. sqlPartKeyValue := strings.SplitN(strings.TrimSpace(sqlMappingPart), sqlMappingTagPartKeyValueSeparator, 2)
  135. if sqlPartKeyValue != nil && len(sqlPartKeyValue) == 2 && strutils.IsStringNotEmpty(sqlPartKeyValue[1]) {
  136. sqlPartKeyValue[1] = strings.Trim(sqlPartKeyValue[1], "'")
  137. }
  138. switch sqlPartKeyValue[0] {
  139. case sqlMappingColumn:
  140. if strutils.IsStringEmpty(sqlPartKeyValue[1]) {
  141. return nil, errors.New("column没有赋值列名")
  142. }
  143. sqlColumn.Name = sqlPartKeyValue[1]
  144. case sqlMappingKey:
  145. sqlColumn.IsKey = true
  146. sqlColumn.CanUpdate = false
  147. case sqlMappingNotUpdate:
  148. sqlColumn.CanUpdate = false
  149. case sqlMappingUpdateClear:
  150. sqlColumn.CanUpdateClear = true
  151. case sqlMappingAes:
  152. if len(sqlPartKeyValue[1]) != 32 {
  153. return nil, errors.New("AES密钥长度应该为32个字节")
  154. }
  155. sqlColumn.AESKey = sqlPartKeyValue[1]
  156. case sqlMappingJoinWith:
  157. if strutils.IsStringEmpty(sqlPartKeyValue[1]) {
  158. return nil, errors.New(sqlMappingJoinWith + "没有赋值分隔符")
  159. }
  160. if fieldValueTypeElem.Kind() != reflect.Slice || fieldValueTypeElem.Elem().Kind() != reflect.String {
  161. return nil, errors.New(sqlMappingJoinWith + "应该添加在[]string字段上")
  162. }
  163. sqlColumn.JoinWith = sqlPartKeyValue[1]
  164. default:
  165. continue
  166. }
  167. }
  168. }
  169. return sqlColumn, nil
  170. }