issue #6098
This commit is contained in:
parent
cc2d46e5be
commit
f3503275da
15
gorm.go
15
gorm.go
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user