From 74e7a9ca079ba44c4e9038088dace76726f2b69c Mon Sep 17 00:00:00 2001 From: heige Date: Wed, 14 Apr 2021 13:00:54 +0800 Subject: [PATCH] Optimize reflect value length and method (#4280) * Respect ignore migration when add column (#4276) continue https://github.com/go-gorm/gorm/pull/4028 * feat: Optimal value type acquisition for v (#4278) * feat: optimize relect value length and value * feat: optimize ConvertSliceOfMapToValuesForCreate method Co-authored-by: yrong1997 --- callbacks/associations.go | 5 +++-- callbacks/helper.go | 11 ++++++++--- schema/utils.go | 6 +++--- statement.go | 12 ++++++++---- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/callbacks/associations.go b/callbacks/associations.go index 2a4efbe1..6d74f20d 100644 --- a/callbacks/associations.go +++ b/callbacks/associations.go @@ -288,12 +288,13 @@ func SaveAfterAssociations(create bool) func(db *gorm.DB) { appendToElems(db.Statement.ReflectValue) } - if elems.Len() > 0 { + // optimize elems of reflect value length + if elemLen := elems.Len(); elemLen > 0 { if v, ok := selectColumns[rel.Name+".*"]; !ok || v { saveAssociations(db, rel, elems.Interface(), selectColumns, restricted, nil) } - for i := 0; i < elems.Len(); i++ { + for i := 0; i < elemLen; i++ { appendToJoins(objs[i], elems.Index(i)) } } diff --git a/callbacks/helper.go b/callbacks/helper.go index 3ac63fa1..ad85a1c6 100644 --- a/callbacks/helper.go +++ b/callbacks/helper.go @@ -41,16 +41,21 @@ func ConvertMapToValuesForCreate(stmt *gorm.Statement, mapValue map[string]inter // ConvertSliceOfMapToValuesForCreate convert slice of map to values func ConvertSliceOfMapToValuesForCreate(stmt *gorm.Statement, mapValues []map[string]interface{}) (values clause.Values) { var ( - columns = make([]string, 0, len(mapValues)) - result = map[string][]interface{}{} - selectColumns, restricted = stmt.SelectAndOmitColumns(true, false) + columns = make([]string, 0, len(mapValues)) ) + // when the length of mapValues,return directly here + // no need to call stmt.SelectAndOmitColumns method if len(mapValues) == 0 { stmt.AddError(gorm.ErrEmptySlice) return } + var ( + result = make(map[string][]interface{}, len(mapValues)) + selectColumns, restricted = stmt.SelectAndOmitColumns(true, false) + ) + for idx, mapValue := range mapValues { for k, v := range mapValue { if stmt.Schema != nil { diff --git a/schema/utils.go b/schema/utils.go index d311c61b..add22047 100644 --- a/schema/utils.go +++ b/schema/utils.go @@ -71,10 +71,10 @@ func GetRelationsValues(reflectValue reflect.Value, rels []*Relationship) (refle reflectResults = reflect.Append(reflectResults, result.Addr()) case reflect.Slice, reflect.Array: for i := 0; i < result.Len(); i++ { - if result.Index(i).Kind() == reflect.Ptr { - reflectResults = reflect.Append(reflectResults, result.Index(i)) + if elem := result.Index(i); elem.Kind() == reflect.Ptr { + reflectResults = reflect.Append(reflectResults, elem) } else { - reflectResults = reflect.Append(reflectResults, result.Index(i).Addr()) + reflectResults = reflect.Append(reflectResults, elem.Addr()) } } } diff --git a/statement.go b/statement.go index 7a827ca8..099c66d2 100644 --- a/statement.go +++ b/statement.go @@ -328,8 +328,10 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) [] } else if _, ok := v[key].(Valuer); ok { conds = append(conds, clause.Eq{Column: key, Value: v[key]}) } else { - values := make([]interface{}, reflectValue.Len()) - for i := 0; i < reflectValue.Len(); i++ { + // optimize relect value length + valueLen := reflectValue.Len() + values := make([]interface{}, valueLen) + for i := 0; i < valueLen; i++ { values[i] = reflectValue.Index(i).Interface() } @@ -396,8 +398,10 @@ func (stmt *Statement) BuildCondition(query interface{}, args ...interface{}) [] if len(args) == 1 { switch reflectValue.Kind() { case reflect.Slice, reflect.Array: - values := make([]interface{}, reflectValue.Len()) - for i := 0; i < reflectValue.Len(); i++ { + // optimize relect value length + valueLen := reflectValue.Len() + values := make([]interface{}, valueLen) + for i := 0; i < valueLen; i++ { values[i] = reflectValue.Index(i).Interface() }