First try for the Preload feature
This commit is contained in:
		
							parent
							
								
									8aef600540
								
							
						
					
					
						commit
						3b784c37c4
					
				@ -1092,8 +1092,9 @@ db.Where("email = ?", "x@example.org").Attrs(User{RegisteredIp: "111.111.111.111
 | 
				
			|||||||
  db.Mode(&User{}).Do("EditForm").Get("edit_form_html")
 | 
					  db.Mode(&User{}).Do("EditForm").Get("edit_form_html")
 | 
				
			||||||
  DefaultTimeZone, R/W Splitting, Validation
 | 
					  DefaultTimeZone, R/W Splitting, Validation
 | 
				
			||||||
* Github Pages
 | 
					* Github Pages
 | 
				
			||||||
* Includes
 | 
					 | 
				
			||||||
* AlertColumn, DropColumn
 | 
					* AlertColumn, DropColumn
 | 
				
			||||||
 | 
					* db.Preload("Addresses.Map", "active = ?", true).Preload("Profile").Find(&users)
 | 
				
			||||||
 | 
					* db.Find(&users).Related(&users)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Author
 | 
					# Author
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,8 @@ package gorm
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/jinzhu/gorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Query(scope *Scope) {
 | 
					func Query(scope *Scope) {
 | 
				
			||||||
@ -13,6 +15,7 @@ func Query(scope *Scope) {
 | 
				
			|||||||
		isPtr          bool
 | 
							isPtr          bool
 | 
				
			||||||
		anyRecordFound bool
 | 
							anyRecordFound bool
 | 
				
			||||||
		destType       reflect.Type
 | 
							destType       reflect.Type
 | 
				
			||||||
 | 
							primaryKeys    []interface{}
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var dest = scope.IndirectValue()
 | 
						var dest = scope.IndirectValue()
 | 
				
			||||||
@ -47,8 +50,9 @@ func Query(scope *Scope) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		columns, _ := rows.Columns()
 | 
							preloadMap := map[string]map[string]*gorm.Field{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							columns, _ := rows.Columns()
 | 
				
			||||||
		defer rows.Close()
 | 
							defer rows.Close()
 | 
				
			||||||
		for rows.Next() {
 | 
							for rows.Next() {
 | 
				
			||||||
			scope.db.RowsAffected += 1
 | 
								scope.db.RowsAffected += 1
 | 
				
			||||||
@ -62,6 +66,7 @@ func Query(scope *Scope) {
 | 
				
			|||||||
			var values = make([]interface{}, len(columns))
 | 
								var values = make([]interface{}, len(columns))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fields := scope.New(elem.Addr().Interface()).Fields()
 | 
								fields := scope.New(elem.Addr().Interface()).Fields()
 | 
				
			||||||
 | 
								var primaryKey interface{}
 | 
				
			||||||
			for index, column := range columns {
 | 
								for index, column := range columns {
 | 
				
			||||||
				if field, ok := fields[column]; ok {
 | 
									if field, ok := fields[column]; ok {
 | 
				
			||||||
					if field.Field.Kind() == reflect.Ptr {
 | 
										if field.Field.Kind() == reflect.Ptr {
 | 
				
			||||||
@ -69,6 +74,10 @@ func Query(scope *Scope) {
 | 
				
			|||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						values[index] = reflect.New(reflect.PtrTo(field.Field.Type())).Interface()
 | 
											values[index] = reflect.New(reflect.PtrTo(field.Field.Type())).Interface()
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
										if field.IsPrimaryKey {
 | 
				
			||||||
 | 
											primaryKey = values[index]
 | 
				
			||||||
 | 
											primaryKeys = append(primaryKeys, primaryKey)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					var value interface{}
 | 
										var value interface{}
 | 
				
			||||||
					values[index] = &value
 | 
										values[index] = &value
 | 
				
			||||||
@ -95,6 +104,34 @@ func Query(scope *Scope) {
 | 
				
			|||||||
					dest.Set(reflect.Append(dest, elem))
 | 
										dest.Set(reflect.Append(dest, elem))
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if scope.Search.Preload != nil {
 | 
				
			||||||
 | 
									for key := range scope.Search.Preload {
 | 
				
			||||||
 | 
										if field := fields[key]; field != nil {
 | 
				
			||||||
 | 
											if preloadMap[key] == nil {
 | 
				
			||||||
 | 
												preloadMap[key] = map[string]reflect.Value{}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											preloadMap[key][fmt.Sprintf("%v", primaryKey)] = field
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, value := range preloadMap {
 | 
				
			||||||
 | 
								var typ reflect.Type
 | 
				
			||||||
 | 
								var relation *Relation
 | 
				
			||||||
 | 
								for _, v := range value {
 | 
				
			||||||
 | 
									typ = v.Field.Type()
 | 
				
			||||||
 | 
									relation = v.Relationship
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								sliceType := reflect.SliceOf(typ)
 | 
				
			||||||
 | 
								slice := reflect.MakeSlice(sliceType, 0, 0)
 | 
				
			||||||
 | 
								slicePtr := reflect.New(sliceType)
 | 
				
			||||||
 | 
								slicePtr.Elem().Set(slice)
 | 
				
			||||||
 | 
								if relation == "has_many" {
 | 
				
			||||||
 | 
									scope.NewDB().Find(slicePtr.Interface(), primaryKeys)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !anyRecordFound && !isSlice {
 | 
							if !anyRecordFound && !isSlice {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								main.go
									
									
									
									
									
								
							@ -156,10 +156,6 @@ func (s *DB) Joins(query string) *DB {
 | 
				
			|||||||
	return s.clone().search.joins(query).db
 | 
						return s.clone().search.joins(query).db
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *DB) Includes(value interface{}) *DB {
 | 
					 | 
				
			||||||
	return s.clone().search.includes(value).db
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB {
 | 
					func (s *DB) Scopes(funcs ...func(*DB) *DB) *DB {
 | 
				
			||||||
	c := s
 | 
						c := s
 | 
				
			||||||
	for _, f := range funcs {
 | 
						for _, f := range funcs {
 | 
				
			||||||
@ -432,6 +428,10 @@ func (s *DB) Association(column string) *Association {
 | 
				
			|||||||
	return &Association{Scope: scope, Column: column, Error: s.Error, PrimaryKey: primaryKey, PrimaryType: primaryType, Field: field}
 | 
						return &Association{Scope: scope, Column: column, Error: s.Error, PrimaryKey: primaryKey, PrimaryType: primaryType, Field: field}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *DB) Preload(column string, conditions ...interface{}) *DB {
 | 
				
			||||||
 | 
						return s.clone().search.preload(column, conditions...).db
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Set set value by name
 | 
					// Set set value by name
 | 
				
			||||||
func (s *DB) Set(name string, value interface{}) *DB {
 | 
					func (s *DB) Set(name string, value interface{}) *DB {
 | 
				
			||||||
	return s.clone().InstantSet(name, value)
 | 
						return s.clone().InstantSet(name, value)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								search.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								search.go
									
									
									
									
									
								
							@ -13,6 +13,7 @@ type search struct {
 | 
				
			|||||||
	Orders          []string
 | 
						Orders          []string
 | 
				
			||||||
	Joins           string
 | 
						Joins           string
 | 
				
			||||||
	Selects         []map[string]interface{}
 | 
						Selects         []map[string]interface{}
 | 
				
			||||||
 | 
						Preload         map[string][]interface{}
 | 
				
			||||||
	Offset          string
 | 
						Offset          string
 | 
				
			||||||
	Limit           string
 | 
						Limit           string
 | 
				
			||||||
	Group           string
 | 
						Group           string
 | 
				
			||||||
@ -23,6 +24,7 @@ type search struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (s *search) clone() *search {
 | 
					func (s *search) clone() *search {
 | 
				
			||||||
	return &search{
 | 
						return &search{
 | 
				
			||||||
 | 
							Preload:         s.Preload,
 | 
				
			||||||
		WhereConditions: s.WhereConditions,
 | 
							WhereConditions: s.WhereConditions,
 | 
				
			||||||
		OrConditions:    s.OrConditions,
 | 
							OrConditions:    s.OrConditions,
 | 
				
			||||||
		NotConditions:   s.NotConditions,
 | 
							NotConditions:   s.NotConditions,
 | 
				
			||||||
@ -100,12 +102,16 @@ func (s *search) having(query string, values ...interface{}) *search {
 | 
				
			|||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *search) includes(value interface{}) *search {
 | 
					func (s *search) joins(query string) *search {
 | 
				
			||||||
 | 
						s.Joins = query
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *search) joins(query string) *search {
 | 
					func (s *search) preload(column string, values ...interface{}) *search {
 | 
				
			||||||
	s.Joins = query
 | 
						if s.Preload == nil {
 | 
				
			||||||
 | 
							s.Preload = map[string][]interface{}{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s.Preload[column] = values
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user