diff --git a/main.go b/main.go index cd445555..9844b584 100644 --- a/main.go +++ b/main.go @@ -567,6 +567,15 @@ func (s *DB) AddForeignKey(field string, dest string, onDelete string, onUpdate return scope.db } +// AddLongForeignKey can be used when the identifier of foreign key is exceeds 64 characters +// It uses sha1 to shorten it +// db.Model(&User{}).AddLongForeignKey("city_id", "cities(id)", "RESTRICT", "RESTRICT") +func (s *DB) AddLongForeignKey(field string, dest string, onDelete string, onUpdate string) *DB { + scope := s.clone().NewScope(s.Value) + scope.addLongForeignKey(field, dest, onDelete, onUpdate) + return scope.db +} + // Association start `Association Mode` to handler relations things easir in that mode, refer: https://jinzhu.github.io/gorm/associations.html#association-mode func (s *DB) Association(column string) *Association { var err error diff --git a/scope.go b/scope.go index 844df85c..6debb9e3 100644 --- a/scope.go +++ b/scope.go @@ -1,6 +1,7 @@ package gorm import ( + "crypto/sha1" "database/sql" "database/sql/driver" "errors" @@ -1114,6 +1115,24 @@ func (scope *Scope) addIndex(unique bool, indexName string, column ...string) { scope.Raw(fmt.Sprintf("%s %v ON %v(%v) %v", sqlCreate, indexName, scope.QuotedTableName(), strings.Join(columns, ", "), scope.whereSQL())).Exec() } +func (scope *Scope) addLongForeignKey(field string, dest string, onDelete string, onUpdate string) { + getHash := func(rawKey string) string { + h := sha1.New() + h.Write([]byte(rawKey)) + bs := h.Sum(nil) + return fmt.Sprintf("%x", bs) + } + keyName := scope.TableName() + field + dest + hash := getHash(keyName) + query := `ALTER TABLE ` + scope.QuotedTableName() + + ` ADD CONSTRAINT ` + "`" + hash + "`" + + ` FOREIGN KEY (` + scope.quoteIfPossible(field) + `)` + + ` REFERENCES ` + dest + + ` ON DELETE ` + onDelete + + ` ON UPDATE ` + onUpdate + `;` + scope.Raw(query).Exec() +} + func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) { var keyName = fmt.Sprintf("%s_%s_%s_foreign", scope.TableName(), field, dest) keyName = regexp.MustCompile("(_*[^a-zA-Z]+_*|_+)").ReplaceAllString(keyName, "_")