From 45ef1da7e4853441e59af06800ed7c672f15bc7c Mon Sep 17 00:00:00 2001 From: Michael Nussbaum Date: Wed, 23 Feb 2022 21:10:20 -0500 Subject: [PATCH] Fix naming longer then 64 chars with dots in table (#5045) Ensures that foreign key relationships and indexes are given syntactically valid names when their name length exceeds 64 characters and they contained dot characters within the name. This is most often relevant when a Postgres table name is fully qualified by including its schema as part of its name --- schema/naming.go | 3 +-- schema/naming_test.go | 2 +- schema/relationship_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/schema/naming.go b/schema/naming.go index 125094bc..47a2b363 100644 --- a/schema/naming.go +++ b/schema/naming.go @@ -3,7 +3,6 @@ package schema import ( "crypto/sha1" "encoding/hex" - "fmt" "regexp" "strings" "unicode/utf8" @@ -95,7 +94,7 @@ func (ns NamingStrategy) formatName(prefix, table, name string) string { h.Write([]byte(formattedName)) bs := h.Sum(nil) - formattedName = fmt.Sprintf("%v%v%v", prefix, table, name)[0:56] + hex.EncodeToString(bs)[:8] + formattedName = formattedName[0:56] + hex.EncodeToString(bs)[:8] } return formattedName } diff --git a/schema/naming_test.go b/schema/naming_test.go index 1fdab9a0..3f598c33 100644 --- a/schema/naming_test.go +++ b/schema/naming_test.go @@ -193,7 +193,7 @@ func TestFormatNameWithStringLongerThan64Characters(t *testing.T) { ns := NamingStrategy{} formattedName := ns.formatName("prefix", "table", "thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString") - if formattedName != "prefixtablethisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLo180f2c67" { + if formattedName != "prefix_table_thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVery180f2c67" { t.Errorf("invalid formatted name generated, got %v", formattedName) } } diff --git a/schema/relationship_test.go b/schema/relationship_test.go index e2cf11a9..40ffc324 100644 --- a/schema/relationship_test.go +++ b/schema/relationship_test.go @@ -576,3 +576,39 @@ func TestHasManySameForeignKey(t *testing.T) { References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}}, }) } + +type Author struct { + gorm.Model +} + +type Book struct { + gorm.Model + Author Author + AuthorID uint +} + +func (Book) TableName() string { + return "my_schema.a_very_very_very_very_very_very_very_very_long_table_name" +} + +func TestParseConstraintNameWithSchemaQualifiedLongTableName(t *testing.T) { + s, err := schema.Parse( + &Book{}, + &sync.Map{}, + schema.NamingStrategy{}, + ) + if err != nil { + t.Fatalf("Failed to parse schema") + } + + expectedConstraintName := "fk_my_schema_a_very_very_very_very_very_very_very_very_l4db13eec" + constraint := s.Relationships.Relations["Author"].ParseConstraint() + + if constraint.Name != expectedConstraintName { + t.Fatalf( + "expected constraint name %s, got %s", + expectedConstraintName, + constraint.Name, + ) + } +}