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  }