Added support of Find() to slices of structs with embedded interface fields
This commit is contained in:
parent
6c805b6a0e
commit
9d2c0adaa1
@ -1172,7 +1172,7 @@ db.Where("email = ?", "x@example.org").Attrs(User{RegisteredIp: "111.111.111.111
|
|||||||
//// INSERT INTO "users" (email,registered_ip) VALUES ("x@example.org", "111.111.111.111") // if record not found
|
//// INSERT INTO "users" (email,registered_ip) VALUES ("x@example.org", "111.111.111.111") // if record not found
|
||||||
```
|
```
|
||||||
|
|
||||||
## Tables with embedded iterface fields
|
## Embedded interface fields
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Delta struct {
|
type Delta struct {
|
||||||
@ -1207,7 +1207,12 @@ found := Delta {
|
|||||||
Became: &Login{},
|
Became: &Login{},
|
||||||
}
|
}
|
||||||
db.Where(&Delta{Was: &Login{Login: "Login1"}, Became: &Login{}}).First(&found);
|
db.Where(&Delta{Was: &Login{Login: "Login1"}, Became: &Login{}}).First(&found);
|
||||||
//// SELECT * FROM "delta__Login__Login" WHERE ("was__login" = 'Login1') ORDER BY "delta__Login__Login"."id" ASC LIMIT 1
|
//// SELECT * FROM "delta__Login__Login" WHERE ("was__login" = 'Login1') ORDER BY "delta__Login__Login"."id" ASC LIMIT 1
|
||||||
|
|
||||||
|
deltas := []Delta{{Was: &Login{}, Became: &Login{}}};
|
||||||
|
db.Find(&deltas)
|
||||||
|
//// SELECT * FROM "deltas__Login__Login"
|
||||||
|
deltas = append(deltas[:0], deltas[1:]...)
|
||||||
```
|
```
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
8
field.go
8
field.go
@ -76,8 +76,12 @@ func (scope *Scope) Fields() map[string]*Field {
|
|||||||
func getField(indirectValue reflect.Value, structField *StructField) *Field {
|
func getField(indirectValue reflect.Value, structField *StructField) *Field {
|
||||||
field := &Field{StructField: structField}
|
field := &Field{StructField: structField}
|
||||||
for _, name := range structField.Names {
|
for _, name := range structField.Names {
|
||||||
if (reflect.Indirect(indirectValue).Kind() == reflect.Interface) {
|
for ;reflect.Indirect(indirectValue).Kind() == reflect.Interface; {
|
||||||
indirectValue = indirectValue.Elem()
|
if (indirectValue.Elem().IsValid()) {
|
||||||
|
indirectValue = indirectValue.Elem()
|
||||||
|
} else {
|
||||||
|
indirectValue.Set(reflect.New(structField.Value.Type()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
indirectValue = reflect.Indirect(indirectValue).FieldByName(name)
|
indirectValue = reflect.Indirect(indirectValue).FieldByName(name)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
var modelStructs_byScopeType = map[reflect.Type]*ModelStruct{}
|
var modelStructs_byScopeType = map[reflect.Type]*ModelStruct{}
|
||||||
var modelStructs_byTableName = map[string ]*ModelStruct{}
|
var modelStructs_byTableName = map[string ]*ModelStruct{}
|
||||||
|
var modelStruct_last *ModelStruct
|
||||||
|
|
||||||
type ModelStruct struct {
|
type ModelStruct struct {
|
||||||
PrimaryFields []*StructField
|
PrimaryFields []*StructField
|
||||||
@ -94,18 +95,30 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
|||||||
|
|
||||||
modelStruct.ModelType = scopeType
|
modelStruct.ModelType = scopeType
|
||||||
if scopeType.Kind() != reflect.Struct {
|
if scopeType.Kind() != reflect.Struct {
|
||||||
|
modelStruct_last = &modelStruct
|
||||||
return &modelStruct
|
return &modelStruct
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set tablename
|
// Getting table name appendix
|
||||||
for i := 0; i < scopeType.NumField(); i++ {
|
for i := 0; i < scopeType.NumField(); i++ {
|
||||||
if fieldStruct := scopeType.Field(i); ast.IsExported(fieldStruct.Name) {
|
if fieldStruct := scopeType.Field(i); ast.IsExported(fieldStruct.Name) {
|
||||||
if (fieldStruct.Type.Kind() == reflect.Interface) {
|
if (fieldStruct.Type.Kind() == reflect.Interface) {
|
||||||
value := reflect.ValueOf(reflect.ValueOf(scope.Value).Elem().Field(i).Interface())
|
// Interface field
|
||||||
|
value := reflect.ValueOf(scope.Value).Elem()
|
||||||
|
if (value.Kind() == reflect.Slice) {
|
||||||
|
// A slice, using the first element
|
||||||
|
value = value.Index(0)
|
||||||
|
}
|
||||||
|
value = reflect.ValueOf(value.Field(i).Interface())
|
||||||
|
if (! value.IsValid()) {
|
||||||
|
// Invalid interfaces, using Model()'s result
|
||||||
|
return modelStruct_last
|
||||||
|
}
|
||||||
tableName = tableName + "__" + value.Elem().Type().Name()
|
tableName = tableName + "__" + value.Elem().Type().Name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Set tablename
|
||||||
if fm := reflect.New(scopeType).MethodByName("TableName"); fm.IsValid() {
|
if fm := reflect.New(scopeType).MethodByName("TableName"); fm.IsValid() {
|
||||||
if results := fm.Call([]reflect.Value{}); len(results) > 0 {
|
if results := fm.Call([]reflect.Value{}); len(results) > 0 {
|
||||||
if name, ok := results[0].Interface().(string); ok {
|
if name, ok := results[0].Interface().(string); ok {
|
||||||
@ -132,6 +145,7 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if value, ok := modelStructs_byTableName[tableName]; ok {
|
if value, ok := modelStructs_byTableName[tableName]; ok {
|
||||||
|
modelStruct_last = value
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +158,8 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
|||||||
if (fieldStruct.Type.Kind() == reflect.Interface) {
|
if (fieldStruct.Type.Kind() == reflect.Interface) {
|
||||||
value = reflect.ValueOf(reflect.ValueOf(scope.Value).Elem().Field(i).Interface())
|
value = reflect.ValueOf(reflect.ValueOf(scope.Value).Elem().Field(i).Interface())
|
||||||
cachable_byScopeType = false
|
cachable_byScopeType = false
|
||||||
|
} else {
|
||||||
|
value = reflect.Indirect(reflect.ValueOf(scope.Value))
|
||||||
}
|
}
|
||||||
field := &StructField{
|
field := &StructField{
|
||||||
Struct: fieldStruct,
|
Struct: fieldStruct,
|
||||||
@ -325,6 +341,7 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
|||||||
}
|
}
|
||||||
modelStruct.StructFields = append(modelStruct.StructFields, field)
|
modelStruct.StructFields = append(modelStruct.StructFields, field)
|
||||||
}
|
}
|
||||||
|
modelStruct_last = &modelStruct
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if (cachable_byScopeType) {
|
if (cachable_byScopeType) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user