From e7f00bd2cd9f3ee4463a6f69917c9ba59cd6bf58 Mon Sep 17 00:00:00 2001
From: Michael Goff <Michael.Goff@Quantum.com>
Date: Wed, 15 Jun 2016 16:06:22 -0700
Subject: [PATCH] Add support for multiple indexes seperated by commas for
 issue #884

---
 migration_test.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++
 scope.go          | 20 ++++++++++-----
 2 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/migration_test.go b/migration_test.go
index 3e385466..b344514a 100644
--- a/migration_test.go
+++ b/migration_test.go
@@ -367,3 +367,68 @@ func TestAutoMigration(t *testing.T) {
 		t.Error("Big Emails should be saved and fetched correctly")
 	}
 }
+
+type MultipleIndexes struct {
+	ID     int64
+	UserID int64  `sql:"unique_index:uix_multipleindexes_user_name,uix_multipleindexes_user_email;index:idx_multipleindexes_user_other"`
+	Name   string `sql:"unique_index:uix_multipleindexes_user_name"`
+	Email  string `sql:"unique_index:,uix_multipleindexes_user_email"`
+	Other  string `sql:"index:,idx_multipleindexes_user_other"`
+}
+
+func TestMultipleIndexes(t *testing.T) {
+	if err := DB.DropTableIfExists(&MultipleIndexes{}).Error; err != nil {
+		fmt.Printf("Got error when try to delete table multiple_indexes, %+v\n", err)
+	}
+
+	DB.Debug().AutoMigrate(&MultipleIndexes{})
+	if err := DB.AutoMigrate(&BigEmail{}).Error; err != nil {
+		t.Errorf("Auto Migrate should not raise any error")
+	}
+
+	DB.Save(&MultipleIndexes{UserID: 1, Name: "jinzhu", Email: "jinzhu@example.org", Other: "foo"})
+
+	scope := DB.NewScope(&MultipleIndexes{})
+	if !scope.Dialect().HasIndex(scope.TableName(), "uix_multipleindexes_user_name") {
+		t.Errorf("Failed to create index")
+	}
+
+	if !scope.Dialect().HasIndex(scope.TableName(), "uix_multipleindexes_user_email") {
+		t.Errorf("Failed to create index")
+	}
+
+	if !scope.Dialect().HasIndex(scope.TableName(), "uix_multiple_indexes_email") {
+		t.Errorf("Failed to create index")
+	}
+
+	if !scope.Dialect().HasIndex(scope.TableName(), "idx_multipleindexes_user_other") {
+		t.Errorf("Failed to create index")
+	}
+
+	if !scope.Dialect().HasIndex(scope.TableName(), "idx_multiple_indexes_other") {
+		t.Errorf("Failed to create index")
+	}
+
+	var mutipleIndexes MultipleIndexes
+	DB.First(&mutipleIndexes, "name = ?", "jinzhu")
+	if mutipleIndexes.Email != "jinzhu@example.org" || mutipleIndexes.Name != "jinzhu" {
+		t.Error("MutipleIndexes should be saved and fetched correctly")
+	}
+
+	// Check unique constraints
+	if err := DB.Save(&MultipleIndexes{UserID: 1, Name: "name1", Email: "jinzhu@example.org", Other: "foo"}).Error; err == nil {
+		t.Error("MultipleIndexes unique index failed")
+	}
+
+	if err := DB.Save(&MultipleIndexes{UserID: 1, Name: "name1", Email: "foo@example.org", Other: "foo"}).Error; err != nil {
+		t.Error("MultipleIndexes unique index failed")
+	}
+
+	if err := DB.Save(&MultipleIndexes{UserID: 2, Name: "name1", Email: "jinzhu@example.org", Other: "foo"}).Error; err == nil {
+		t.Error("MultipleIndexes unique index failed")
+	}
+
+	if err := DB.Save(&MultipleIndexes{UserID: 2, Name: "name1", Email: "foo2@example.org", Other: "foo"}).Error; err != nil {
+		t.Error("MultipleIndexes unique index failed")
+	}
+}
diff --git a/scope.go b/scope.go
index 1e755626..f4a21548 100644
--- a/scope.go
+++ b/scope.go
@@ -1157,17 +1157,25 @@ func (scope *Scope) autoIndex() *Scope {
 
 	for _, field := range scope.GetStructFields() {
 		if name, ok := field.TagSettings["INDEX"]; ok {
-			if name == "INDEX" {
-				name = fmt.Sprintf("idx_%v_%v", scope.TableName(), field.DBName)
+			names := strings.Split(name, ",")
+
+			for _, name := range names {
+				if name == "INDEX" || name == "" {
+					name = fmt.Sprintf("idx_%v_%v", scope.TableName(), field.DBName)
+				}
+				indexes[name] = append(indexes[name], field.DBName)
 			}
-			indexes[name] = append(indexes[name], field.DBName)
 		}
 
 		if name, ok := field.TagSettings["UNIQUE_INDEX"]; ok {
-			if name == "UNIQUE_INDEX" {
-				name = fmt.Sprintf("uix_%v_%v", scope.TableName(), field.DBName)
+			names := strings.Split(name, ",")
+
+			for _, name := range names {
+				if name == "UNIQUE_INDEX" || name == "" {
+					name = fmt.Sprintf("uix_%v_%v", scope.TableName(), field.DBName)
+				}
+				uniqueIndexes[name] = append(uniqueIndexes[name], field.DBName)
 			}
-			uniqueIndexes[name] = append(uniqueIndexes[name], field.DBName)
 		}
 	}