feat(schema) test self-reference belongs to

This commit is contained in:
Jinzhu 2018-02-26 00:45:09 +08:00
parent 3c9dee889f
commit 6e6b40fb0d
3 changed files with 145 additions and 14 deletions

View File

@ -2,11 +2,6 @@ package schema
import "testing"
type BelongsTo struct {
ID int
Name string
}
type HasOne struct {
ID int
MyStructID uint
@ -24,13 +19,94 @@ type Many2Many struct {
}
func TestBelongsToRel(t *testing.T) {
type MyStruct struct {
ID int
Name string
BelongsTo BelongsTo
type BelongsTo struct {
ID int
Name string
}
Parse(&MyStruct{})
type MyStruct struct {
ID int
Name string
BelongsToID uint
BelongsTo BelongsTo
}
schema := Parse(&MyStruct{})
compareFields(schema.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_id", Name: "BelongsToID", BindNames: []string{"BelongsToID"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_id"}, AssociationForeignKey: []string{"id"}}},
}, t)
type MyStruct2 struct {
ID int `gorm:"column:my_id"`
Name string
BelongsToKey uint
BelongsTo BelongsTo `gorm:"foreignkey:BelongsToKey"`
}
schema2 := Parse(&MyStruct2{})
compareFields(schema2.Fields, []*Field{
{DBName: "my_id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true, TagSettings: map[string]string{"COLUMN": "my_id"}},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_key", Name: "BelongsToKey", BindNames: []string{"BelongsToKey"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_key"}, AssociationForeignKey: []string{"id"}}, TagSettings: map[string]string{"FOREIGNKEY": "BelongsToKey"}},
}, t)
type BelongsTo3 struct {
ID int `gorm:"column:my_id"`
Name string
}
type MyStruct3 struct {
ID int
Name string
BelongsToKey uint
BelongsTo BelongsTo3 `gorm:"foreignkey:BelongsToKey"`
}
schema3 := Parse(&MyStruct3{})
compareFields(schema3.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_key", Name: "BelongsToKey", BindNames: []string{"BelongsToKey"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_key"}, AssociationForeignKey: []string{"my_id"}}, TagSettings: map[string]string{"FOREIGNKEY": "BelongsToKey"}},
}, t)
}
func TestSelfReferenceBelongsToRel(t *testing.T) {
type MyStruct struct {
ID int
Name string
BelongsToID int
BelongsTo *MyStruct
}
// user1 belongs to user2, when creating, will create user2 first
schema := Parse(&MyStruct{})
compareFields(schema.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_id", Name: "BelongsToID", BindNames: []string{"BelongsToID"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_id"}, AssociationForeignKey: []string{"id"}}},
}, t)
type MyStruct2 struct {
ID int
Name string
BelongsToKey int
BelongsTo *MyStruct2 `gorm:"rel:belongs_to;foreignkey:BelongsToKey"`
}
// user1 belongs to user2, when creating, will create user2 first
schema2 := Parse(&MyStruct2{})
compareFields(schema2.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_key", Name: "BelongsToKey", BindNames: []string{"BelongsToKey"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_key"}, AssociationForeignKey: []string{"id"}}, TagSettings: map[string]string{"FOREIGNKEY": "BelongsToKey"}},
}, t)
}
func TestHasOneRel(t *testing.T) {
@ -43,6 +119,46 @@ func TestHasOneRel(t *testing.T) {
Parse(&MyStruct{})
}
func TestSelfReferenceHasOneRel(t *testing.T) {
type MyStruct struct {
ID int
Name string
BelongsToID int
BelongsTo *MyStruct
}
// user1 belongs to user2, when creating, will create user2 first
schema := Parse(&MyStruct{})
compareFields(schema.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "belongs_to_id", Name: "BelongsToID", BindNames: []string{"BelongsToID"}, IsNormal: true, IsForeignKey: true},
{DBName: "belongs_to", Name: "BelongsTo", BindNames: []string{"BelongsTo"}, Relationship: &Relationship{Kind: "belongs_to", ForeignKey: []string{"belongs_to_id"}, AssociationForeignKey: []string{"id"}}},
}, t)
}
func TestPolymorphicHasOneRel(t *testing.T) {
type HasOne struct {
ID int
Name string
OwnerType string
OwnerID string
}
type MyStruct struct {
ID int
Name string
HasOne HasOne `gorm:"polymorphic:Owner"`
}
schema := Parse(&MyStruct{})
compareFields(schema.Fields, []*Field{
{DBName: "id", Name: "ID", BindNames: []string{"ID"}, IsNormal: true, IsPrimaryKey: true},
{DBName: "name", Name: "Name", BindNames: []string{"Name"}, IsNormal: true},
{DBName: "has_one", Name: "HasOne", BindNames: []string{"HasOne"}, Relationship: &Relationship{Kind: "has_one", PolymorphicType: "OwnerType", PolymorphicDBName: "owner_type", PolymorphicValue: "my_struct", ForeignKey: []string{"owner_id"}, AssociationForeignKey: []string{"id"}}, TagSettings: map[string]string{"POLYMORPHIC": "Owner"}},
}, t)
}
func TestHasManyRel(t *testing.T) {
type MyStruct struct {
ID int
@ -62,4 +178,3 @@ func TestManyToManyRel(t *testing.T) {
Parse(&MyStruct{})
}

View File

@ -5,9 +5,13 @@ import (
"go/ast"
"reflect"
"sort"
"strings"
"sync"
"time"
)
var schemaMap = sync.Map{}
// Schema model schema definition
type Schema struct {
ModelType reflect.Type
@ -48,6 +52,10 @@ func Parse(dest interface{}) *Schema {
return nil
}
if m, ok := schemaMap.Load(reflectType); ok {
return m.(*Schema)
}
schema.ModelType = reflectType
onConflictFields := map[string]int{}
@ -221,12 +229,16 @@ func Parse(dest interface{}) *Schema {
}
if len(schema.PrimaryFields) == 0 {
if field := getSchemaField("id", schema.Fields); field != nil {
field.IsPrimaryKey = true
schema.PrimaryFields = append(schema.PrimaryFields, field)
for _, field := range schema.Fields {
if strings.ToUpper(field.Name) == "ID" || field.DBName == "id" {
field.IsPrimaryKey = true
schema.PrimaryFields = append(schema.PrimaryFields, field)
break
}
}
}
schemaMap.Store(reflectType, &schema)
return &schema
}

View File

@ -293,5 +293,9 @@ func fieldEqual(got, expected *Field) error {
if expected.HasDefaultValue != got.HasDefaultValue {
return fmt.Errorf("field HasDefaultValue should be %v, got %v", expected.HasDefaultValue, got.HasDefaultValue)
}
if !reflect.DeepEqual(expected.Relationship, got.Relationship) {
return fmt.Errorf("field Relationship should be %#v, got %#v", expected.Relationship, got.Relationship)
}
return nil
}