entc/gen: ensure foreign-key constraints are unique in codegen (#3066)

This commit is contained in:
Ariel Mashraki
2022-11-05 07:28:50 +02:00
committed by GitHub
parent 5d4f02620d
commit a91aabe3ef
3 changed files with 62 additions and 2 deletions

View File

@@ -681,6 +681,9 @@ func (g *Graph) Tables() (all []*schema.Table, err error) {
index.Annotation = entsqlIndexAnnotate(idx.Annotations)
}
}
if err := ensureUniqueFKs(tables); err != nil {
return nil, err
}
return
}
@@ -733,6 +736,29 @@ func fkSymbols(e *Edge, c1, c2 *schema.Column) (string, string) {
return s1, s2
}
// ensureUniqueNames ensures constraint names are unique.
func ensureUniqueFKs(tables map[string]*schema.Table) error {
fks := make(map[string]*schema.Table)
for _, t := range tables {
for _, fk := range t.ForeignKeys {
switch other, ok := fks[fk.Symbol]; {
case !ok:
fks[fk.Symbol] = t
case ok && other.Name != t.Name:
a, b := t.Name, other.Name
// Keep reporting order consistent.
if a > b {
a, b = b, a
}
return fmt.Errorf("duplicate foreign-key symbol %q found in tables %q and %q", fk.Symbol, a, b)
case ok:
return fmt.Errorf("duplicate foreign-key symbol %q found in table %q", fk.Symbol, t.Name)
}
}
}
return nil
}
// deleteAction returns the referential action for DELETE operations of the given edge.
func deleteAction(e *Edge, c *schema.Column) schema.ReferenceOption {
action := schema.NoAction

View File

@@ -344,6 +344,40 @@ func TestFKColumns(t *testing.T) {
}
}
func TestAbortDuplicateFK(t *testing.T) {
var (
user = &load.Schema{
Name: "User",
Edges: []*load.Edge{
{Name: "pets", Type: "Pet", StorageKey: &edge.StorageKey{Symbols: []string{"owner_id"}}},
{Name: "cars", Type: "Car", StorageKey: &edge.StorageKey{Symbols: []string{"owner_id"}}},
},
}
pet = &load.Schema{
Name: "Pet",
Fields: []*load.Field{
{Name: "owner_id", Info: &field.TypeInfo{Type: field.TypeInt}, Nillable: true, Optional: true},
},
Edges: []*load.Edge{
{Name: "owner", Type: "User", RefName: "pets", Inverse: true, Unique: true},
},
}
car = &load.Schema{
Name: "Car",
Fields: []*load.Field{
{Name: "owner_id", Info: &field.TypeInfo{Type: field.TypeInt}, Nillable: true, Optional: true},
},
Edges: []*load.Edge{
{Name: "owner", Type: "User", RefName: "cars", Inverse: true, Unique: true},
},
}
)
g, err := NewGraph(&Config{Package: "entc/gen", Storage: drivers[0]}, user, pet, car)
require.NoError(t, err)
_, err = g.Tables()
require.EqualError(t, err, `duplicate foreign-key symbol "owner_id" found in tables "cars" and "pets"`)
}
func TestEnsureCorrectFK(t *testing.T) {
var (
user = &load.Schema{