forked from mirror/gorm
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…
Reference in New Issue