feat(schema) test self-reference belongs to
This commit is contained in:
		
							parent
							
								
									3c9dee889f
								
							
						
					
					
						commit
						6e6b40fb0d
					
				@ -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{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user