utils.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package schema
  2. import (
  3. "context"
  4. "fmt"
  5. "reflect"
  6. "regexp"
  7. "strings"
  8. "gorm.io/gorm/clause"
  9. "gorm.io/gorm/utils"
  10. )
  11. var embeddedCacheKey = "embedded_cache_store"
  12. func ParseTagSetting(str string, sep string) map[string]string {
  13. settings := map[string]string{}
  14. names := strings.Split(str, sep)
  15. for i := 0; i < len(names); i++ {
  16. j := i
  17. if len(names[j]) > 0 {
  18. for {
  19. if names[j][len(names[j])-1] == '\\' {
  20. i++
  21. names[j] = names[j][0:len(names[j])-1] + sep + names[i]
  22. names[i] = ""
  23. } else {
  24. break
  25. }
  26. }
  27. }
  28. values := strings.Split(names[j], ":")
  29. k := strings.TrimSpace(strings.ToUpper(values[0]))
  30. if len(values) >= 2 {
  31. settings[k] = strings.Join(values[1:], ":")
  32. } else if k != "" {
  33. settings[k] = k
  34. }
  35. }
  36. return settings
  37. }
  38. func toColumns(val string) (results []string) {
  39. if val != "" {
  40. for _, v := range strings.Split(val, ",") {
  41. results = append(results, strings.TrimSpace(v))
  42. }
  43. }
  44. return
  45. }
  46. func removeSettingFromTag(tag reflect.StructTag, names ...string) reflect.StructTag {
  47. for _, name := range names {
  48. tag = reflect.StructTag(regexp.MustCompile(`(?i)(gorm:.*?)(`+name+`(:.*?)?)(;|("))`).ReplaceAllString(string(tag), "${1}${5}"))
  49. }
  50. return tag
  51. }
  52. func appendSettingFromTag(tag reflect.StructTag, value string) reflect.StructTag {
  53. t := tag.Get("gorm")
  54. if strings.Contains(t, value) {
  55. return tag
  56. }
  57. return reflect.StructTag(fmt.Sprintf(`gorm:"%s;%s"`, value, t))
  58. }
  59. // GetRelationsValues get relations's values from a reflect value
  60. func GetRelationsValues(ctx context.Context, reflectValue reflect.Value, rels []*Relationship) (reflectResults reflect.Value) {
  61. for _, rel := range rels {
  62. reflectResults = reflect.MakeSlice(reflect.SliceOf(reflect.PointerTo(rel.FieldSchema.ModelType)), 0, 1)
  63. appendToResults := func(value reflect.Value) {
  64. if _, isZero := rel.Field.ValueOf(ctx, value); !isZero {
  65. result := reflect.Indirect(rel.Field.ReflectValueOf(ctx, value))
  66. switch result.Kind() {
  67. case reflect.Struct:
  68. reflectResults = reflect.Append(reflectResults, result.Addr())
  69. case reflect.Slice, reflect.Array:
  70. for i := 0; i < result.Len(); i++ {
  71. if elem := result.Index(i); elem.Kind() == reflect.Ptr {
  72. reflectResults = reflect.Append(reflectResults, elem)
  73. } else {
  74. reflectResults = reflect.Append(reflectResults, elem.Addr())
  75. }
  76. }
  77. }
  78. }
  79. }
  80. switch reflectValue.Kind() {
  81. case reflect.Struct:
  82. appendToResults(reflectValue)
  83. case reflect.Slice:
  84. for i := 0; i < reflectValue.Len(); i++ {
  85. appendToResults(reflectValue.Index(i))
  86. }
  87. }
  88. reflectValue = reflectResults
  89. }
  90. return
  91. }
  92. // GetIdentityFieldValuesMap get identity map from fields
  93. func GetIdentityFieldValuesMap(ctx context.Context, reflectValue reflect.Value, fields []*Field) (map[string][]reflect.Value, [][]interface{}) {
  94. var (
  95. results = [][]interface{}{}
  96. dataResults = map[string][]reflect.Value{}
  97. loaded = map[interface{}]bool{}
  98. notZero, zero bool
  99. )
  100. if reflectValue.Kind() == reflect.Ptr ||
  101. reflectValue.Kind() == reflect.Interface {
  102. reflectValue = reflectValue.Elem()
  103. }
  104. switch reflectValue.Kind() {
  105. case reflect.Struct:
  106. results = [][]interface{}{make([]interface{}, len(fields))}
  107. for idx, field := range fields {
  108. results[0][idx], zero = field.ValueOf(ctx, reflectValue)
  109. notZero = notZero || !zero
  110. }
  111. if !notZero {
  112. return nil, nil
  113. }
  114. dataResults[utils.ToStringKey(results[0]...)] = []reflect.Value{reflectValue}
  115. case reflect.Slice, reflect.Array:
  116. for i := 0; i < reflectValue.Len(); i++ {
  117. elem := reflectValue.Index(i)
  118. elemKey := elem.Interface()
  119. if elem.Kind() != reflect.Ptr && elem.CanAddr() {
  120. elemKey = elem.Addr().Interface()
  121. }
  122. if _, ok := loaded[elemKey]; ok {
  123. continue
  124. }
  125. loaded[elemKey] = true
  126. fieldValues := make([]interface{}, len(fields))
  127. notZero = false
  128. for idx, field := range fields {
  129. fieldValues[idx], zero = field.ValueOf(ctx, elem)
  130. notZero = notZero || !zero
  131. }
  132. if notZero {
  133. dataKey := utils.ToStringKey(fieldValues...)
  134. if _, ok := dataResults[dataKey]; !ok {
  135. results = append(results, fieldValues)
  136. dataResults[dataKey] = []reflect.Value{elem}
  137. } else {
  138. dataResults[dataKey] = append(dataResults[dataKey], elem)
  139. }
  140. }
  141. }
  142. }
  143. return dataResults, results
  144. }
  145. // GetIdentityFieldValuesMapFromValues get identity map from fields
  146. func GetIdentityFieldValuesMapFromValues(ctx context.Context, values []interface{}, fields []*Field) (map[string][]reflect.Value, [][]interface{}) {
  147. resultsMap := map[string][]reflect.Value{}
  148. results := [][]interface{}{}
  149. for _, v := range values {
  150. rm, rs := GetIdentityFieldValuesMap(ctx, reflect.Indirect(reflect.ValueOf(v)), fields)
  151. for k, v := range rm {
  152. resultsMap[k] = append(resultsMap[k], v...)
  153. }
  154. results = append(results, rs...)
  155. }
  156. return resultsMap, results
  157. }
  158. // ToQueryValues to query values
  159. func ToQueryValues(table string, foreignKeys []string, foreignValues [][]interface{}) (interface{}, []interface{}) {
  160. queryValues := make([]interface{}, len(foreignValues))
  161. if len(foreignKeys) == 1 {
  162. for idx, r := range foreignValues {
  163. queryValues[idx] = r[0]
  164. }
  165. return clause.Column{Table: table, Name: foreignKeys[0]}, queryValues
  166. }
  167. columns := make([]clause.Column, len(foreignKeys))
  168. for idx, key := range foreignKeys {
  169. columns[idx] = clause.Column{Table: table, Name: key}
  170. }
  171. for idx, r := range foreignValues {
  172. queryValues[idx] = r
  173. }
  174. return columns, queryValues
  175. }
  176. type embeddedNamer struct {
  177. Table string
  178. Namer
  179. }