This commit is contained in:
mohammad ali ashraf 2023-03-28 18:57:50 +05:00
parent cc2d46e5be
commit f3503275da
6 changed files with 54 additions and 13 deletions

15
gorm.go
View File

@ -144,7 +144,20 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
}
if config.NamingStrategy == nil {
config.NamingStrategy = schema.NamingStrategy{}
// Set default value of IdentifierMaxLength according to the database type
identifierMaxLength := 64
switch dialector.Name() {
case "mysql":
identifierMaxLength = 64
case "postgres":
identifierMaxLength = 63
case "sqlite":
identifierMaxLength = 64
case "sqlserver":
identifierMaxLength = 128
}
config.NamingStrategy = schema.NamingStrategy{NamingStrategyConfig: schema.NamingStrategyConfig{IdentifierMaxLength: identifierMaxLength}}
}
if config.Logger == nil {

View File

@ -15,7 +15,7 @@ type UserCheck struct {
}
func TestParseCheck(t *testing.T) {
user, err := schema.Parse(&UserCheck{}, &sync.Map{}, schema.NamingStrategy{})
user, err := schema.Parse(&UserCheck{}, &sync.Map{}, schema.NamingStrategy{NamingStrategyConfig: schema.NamingStrategyConfig{IdentifierMaxLength: 64}})
if err != nil {
t.Fatalf("failed to parse user check, got error %v", err)
}

View File

@ -52,7 +52,7 @@ type CompIdxLevel2B struct {
}
func TestParseIndex(t *testing.T) {
user, err := schema.Parse(&UserIndex{}, &sync.Map{}, schema.NamingStrategy{})
user, err := schema.Parse(&UserIndex{}, &sync.Map{}, schema.NamingStrategy{NamingStrategyConfig: schema.NamingStrategyConfig{IdentifierMaxLength: 64}})
if err != nil {
t.Fatalf("failed to parse user index, got error %v", err)
}

View File

@ -32,6 +32,17 @@ type NamingStrategy struct {
SingularTable bool
NameReplacer Replacer
NoLowerCase bool
NamingStrategyConfig
}
// This struct is used to configure the behavior NamingStrategy, according to DB.
// For example, in MySQL, the maximum length of an identifier is 64 characters.
// In PostgreSQL, the maximum length of an identifier is 63 characters.
// In SQL Server, the maximum length of an identifier is 128 characters.
// In SQLite, the maximum length of an identifier is unlimited.
// In future, we may add more options to NamingStrategyConfig.
type NamingStrategyConfig struct {
IdentifierMaxLength int
}
// TableName convert string to table name
@ -89,12 +100,12 @@ func (ns NamingStrategy) formatName(prefix, table, name string) string {
prefix, table, name,
}, "_"), ".", "_")
if utf8.RuneCountInString(formattedName) > 64 {
if utf8.RuneCountInString(formattedName) > ns.IdentifierMaxLength {
h := sha1.New()
h.Write([]byte(formattedName))
bs := h.Sum(nil)
formattedName = formattedName[0:56] + hex.EncodeToString(bs)[:8]
formattedName = formattedName[0:ns.IdentifierMaxLength-8] + hex.EncodeToString(bs)[:8]
}
return formattedName
}

View File

@ -57,9 +57,10 @@ func TestToDBName(t *testing.T) {
func TestNamingStrategy(t *testing.T) {
ns := NamingStrategy{
TablePrefix: "public.",
SingularTable: true,
NameReplacer: strings.NewReplacer("CID", "Cid"),
TablePrefix: "public.",
SingularTable: true,
NameReplacer: strings.NewReplacer("CID", "Cid"),
NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 64},
}
idxName := ns.IndexName("public.table", "name")
@ -111,7 +112,8 @@ func TestCustomReplacer(t *testing.T) {
return strings.NewReplacer("CID", "_Cid").Replace(replaced)
},
},
NoLowerCase: false,
NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 64},
NoLowerCase: false,
}
idxName := ns.IndexName("public.table", "name")
@ -155,7 +157,8 @@ func TestCustomReplacerWithNoLowerCase(t *testing.T) {
return strings.NewReplacer("CID", "_Cid").Replace(replaced)
},
},
NoLowerCase: true,
NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 64},
NoLowerCase: true,
}
idxName := ns.IndexName("public.table", "name")
@ -189,13 +192,27 @@ func TestCustomReplacerWithNoLowerCase(t *testing.T) {
}
}
func TestFormatNameWithStringLongerThan64Characters(t *testing.T) {
ns := NamingStrategy{}
func TestFormatNameWithStringLongerThanMaxIdentifierLength(t *testing.T) {
ns := NamingStrategy{NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 63}}
formattedName := ns.formatName("prefix", "table", "thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString")
if formattedName != "prefix_table_thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVer180f2c67" {
t.Errorf("invalid formatted name generated, got %v", formattedName)
}
ns = NamingStrategy{NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 64}}
formattedName = ns.formatName("prefix", "table", "thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString")
if formattedName != "prefix_table_thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVery180f2c67" {
t.Errorf("invalid formatted name generated, got %v", formattedName)
}
ns = NamingStrategy{NamingStrategyConfig: NamingStrategyConfig{IdentifierMaxLength: 128}}
formattedName = ns.formatName("prefix", "table", "thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongString")
if formattedName != "prefix_table_thisIsAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery81f06061" {
t.Errorf("invalid formatted name generated, got %v", formattedName)
}
}
func TestReplaceEmptyTableName(t *testing.T) {

View File

@ -642,7 +642,7 @@ func TestParseConstraintNameWithSchemaQualifiedLongTableName(t *testing.T) {
s, err := schema.Parse(
&Book{},
&sync.Map{},
schema.NamingStrategy{},
schema.NamingStrategy{NamingStrategyConfig: schema.NamingStrategyConfig{IdentifierMaxLength: 64}},
)
if err != nil {
t.Fatalf("Failed to parse schema")