utils.go 5.0 KB

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