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