From 2cc229eeb22c10e75b9f9453b063f99a8b88711b Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Tue, 10 Sep 2019 05:59:04 -0700 Subject: [PATCH] entc/gen: reject edge with mismatch type for back-ref Reviewed By: alexsn Differential Revision: D17260642 fbshipit-source-id: ef25dc77d9e4a7986e86d859f4f776fcf34336c9 --- entc/gen/graph.go | 13 ++++++++----- entc/gen/graph_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/entc/gen/graph.go b/entc/gen/graph.go index 06a8f84de..f47bf9bfa 100644 --- a/entc/gen/graph.go +++ b/entc/gen/graph.go @@ -59,7 +59,7 @@ func NewGraph(c Config, schemas ...*load.Schema) (g *Graph, err error) { g.addEdges(schema) } for _, t := range g.Nodes { - check(g.resolve(t), "resolve %q relations/references", t.Name) + check(g.resolve(t), "resolve %q relations", t.Name) } for _, schema := range schemas { g.addIndexes(schema) @@ -136,7 +136,7 @@ func (g *Graph) addEdges(schema *load.Schema) { }) // inverse only. case e.Inverse && e.Ref == nil: - expect(e.RefName != "", `missing reference name for inverse edge: %s.%s`, t.Name, e.Name) + expect(e.RefName != "", "missing reference name for inverse edge: %s.%s", t.Name, e.Name) t.Edges = append(t.Edges, &Edge{ Type: typ, Name: e.Name, @@ -148,7 +148,7 @@ func (g *Graph) addEdges(schema *load.Schema) { // inverse and assoc. case e.Inverse: ref := e.Ref - expect(e.RefName == "", `reference name is derived from the assoc name: %s.%s <-> %s.%s`, t.Name, ref.Name, t.Name, e.Name) + expect(e.RefName == "", "reference name is derived from the assoc name: %s.%s <-> %s.%s", t.Name, ref.Name, t.Name, e.Name) expect(ref.Type == t.Name, "assoc-inverse edge allowed only as o2o relation of the same type") t.Edges = append(t.Edges, &Edge{ Type: typ, @@ -198,10 +198,13 @@ func (g *Graph) resolve(t *Type) error { case e.IsInverse(): ref, ok := e.Type.HasAssoc(e.Inverse) if !ok { - return fmt.Errorf(`edge is missing for inverse edge: %s.%s`, e.Type.Name, e.Name) + return fmt.Errorf("edge is missing for inverse edge: %s.%s", e.Type.Name, e.Name) } if !e.Optional && !ref.Optional { - return fmt.Errorf(`edges cannot be required in both directions: %s.%s <-> %s.%s`, t.Name, e.Name, ref.Type.Name, ref.Name) + return fmt.Errorf("edges cannot be required in both directions: %s.%s <-> %s.%s", t.Name, e.Name, e.Type.Name, ref.Name) + } + if ref.Type != t { + return fmt.Errorf("mismatch type for back-ref %q of %s.%s <-> %s.%s", e.Inverse, t.Name, e.Name, e.Type.Name, ref.Name) } table := t.Table() // The name of the column is how we identify the other side. For example "A Parent has Children" diff --git a/entc/gen/graph_test.go b/entc/gen/graph_test.go index 1d65777f6..74fe09cec 100644 --- a/entc/gen/graph_test.go +++ b/entc/gen/graph_test.go @@ -145,6 +145,30 @@ func TestNewGraphRequiredLoop(t *testing.T) { require.Error(t, err, "require loop") } +func TestNewGraphBadInverse(t *testing.T) { + _, err := NewGraph(Config{Package: "entc/gen", Storage: drivers}, + &load.Schema{ + Name: "User", + Edges: []*load.Edge{ + {Name: "pets", Type: "Pet"}, + {Name: "groups", Type: "Group"}, + }, + }, + &load.Schema{ + Name: "Pet", + Edges: []*load.Edge{ + {Name: "owner", Type: "User", Unique: true, Required: true, RefName: "pets", Inverse: true}, + }, + }, + &load.Schema{ + Name: "Group", + Edges: []*load.Edge{ + {Name: "users", Type: "User", RefName: "pets", Inverse: true}, + }, + }) + require.Errorf(t, err, "mismatch type for back-reference") +} + func TestRelation(t *testing.T) { require := require.New(t) _, err := NewGraph(Config{Package: "entc/gen", Storage: drivers}, T1)