From e2e802b837a234ede6dc122dbb26de965e35e55f Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Mon, 28 Feb 2022 09:28:19 +0800 Subject: [PATCH] Refactor Scan --- callbacks/create.go | 6 ++++-- scan.go | 29 ++++++++++++++++------------- tests/go.mod | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/callbacks/create.go b/callbacks/create.go index b0964e2b..6e2883f7 100644 --- a/callbacks/create.go +++ b/callbacks/create.go @@ -201,13 +201,15 @@ func ConvertToCreateValues(stmt *gorm.Statement) (values clause.Values) { switch stmt.ReflectValue.Kind() { case reflect.Slice, reflect.Array: rValLen := stmt.ReflectValue.Len() - stmt.SQL.Grow(rValLen * 18) - values.Values = make([][]interface{}, rValLen) if rValLen == 0 { stmt.AddError(gorm.ErrEmptySlice) return } + stmt.SQL.Grow(rValLen * 18) + stmt.Vars = make([]interface{}, 0, rValLen*len(values.Columns)) + values.Values = make([][]interface{}, rValLen) + defaultValueFieldsHavingValue := map[*schema.Field][]interface{}{} for i := 0; i < rValLen; i++ { rv := reflect.Indirect(stmt.ReflectValue.Index(i)) diff --git a/scan.go b/scan.go index d7b58e03..a4243d12 100644 --- a/scan.go +++ b/scan.go @@ -54,10 +54,6 @@ func (db *DB) scanIntoStruct(rows *sql.Rows, reflectValue reflect.Value, values for idx, field := range fields { if field != nil { values[idx] = field.NewValuePool.Get() - defer field.NewValuePool.Put(values[idx]) - if len(joinFields) == 0 || joinFields[idx][0] == nil { - defer field.Set(db.Statement.Context, reflectValue, values[idx]) - } } else if len(fields) == 1 { if reflectValue.CanAddr() { values[idx] = reflectValue.Addr().Interface() @@ -70,17 +66,24 @@ func (db *DB) scanIntoStruct(rows *sql.Rows, reflectValue reflect.Value, values db.RowsAffected++ db.AddError(rows.Scan(values...)) - for idx, joinField := range joinFields { - if joinField[0] != nil { - relValue := joinField[0].ReflectValueOf(db.Statement.Context, reflectValue) - if relValue.Kind() == reflect.Ptr && relValue.IsNil() { - if value := reflect.ValueOf(values[idx]).Elem(); value.Kind() == reflect.Ptr && value.IsNil() { - return - } + for idx, field := range fields { + if field != nil { + if len(joinFields) == 0 || joinFields[idx][0] == nil { + field.Set(db.Statement.Context, reflectValue, values[idx]) + } else { + relValue := joinFields[idx][0].ReflectValueOf(db.Statement.Context, reflectValue) + if relValue.Kind() == reflect.Ptr && relValue.IsNil() { + if value := reflect.ValueOf(values[idx]).Elem(); value.Kind() == reflect.Ptr && value.IsNil() { + return + } - relValue.Set(reflect.New(relValue.Type().Elem())) + relValue.Set(reflect.New(relValue.Type().Elem())) + } + joinFields[idx][1].Set(db.Statement.Context, relValue, values[idx]) } - joinField[1].Set(db.Statement.Context, relValue, values[idx]) + + // release data to pool + field.NewValuePool.Put(values[idx]) } } } diff --git a/tests/go.mod b/tests/go.mod index 9e3453b7..c65ea953 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -8,7 +8,7 @@ require ( github.com/jackc/pgx/v4 v4.15.0 // indirect github.com/jinzhu/now v1.1.4 github.com/lib/pq v1.10.4 - github.com/mattn/go-sqlite3 v1.14.11 // indirect + github.com/mattn/go-sqlite3 v1.14.12 // indirect golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect gorm.io/driver/mysql v1.3.2 gorm.io/driver/postgres v1.3.1