Test Migrate Indexes
This commit is contained in:
		
							parent
							
								
									c291c2f42c
								
							
						
					
					
						commit
						7c0de9199c
					
				| @ -23,6 +23,10 @@ func (m Migrator) HasTable(value interface{}) bool { | |||||||
| func (m Migrator) HasIndex(value interface{}, name string) bool { | func (m Migrator) HasIndex(value interface{}, name string) bool { | ||||||
| 	var count int | 	var count int | ||||||
| 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return m.DB.Raw( | 		return m.DB.Raw( | ||||||
| 			"SELECT count(*) FROM sys.indexes WHERE name=? AND object_id=OBJECT_ID(?)", | 			"SELECT count(*) FROM sys.indexes WHERE name=? AND object_id=OBJECT_ID(?)", | ||||||
| 			name, stmt.Table, | 			name, stmt.Table, | ||||||
|  | |||||||
| @ -37,11 +37,15 @@ func (m Migrator) BuildIndexOptions(opts []schema.IndexOption, stmt *gorm.Statem | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m Migrator) HasIndex(value interface{}, indexName string) bool { | func (m Migrator) HasIndex(value interface{}, name string) bool { | ||||||
| 	var count int64 | 	var count int64 | ||||||
| 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return m.DB.Raw( | 		return m.DB.Raw( | ||||||
| 			"SELECT count(*) FROM pg_indexes WHERE tablename = ? AND indexname = ? AND schemaname = CURRENT_SCHEMA()", stmt.Table, indexName, | 			"SELECT count(*) FROM pg_indexes WHERE tablename = ? AND indexname = ? AND schemaname = CURRENT_SCHEMA()", stmt.Table, name, | ||||||
| 		).Row().Scan(&count) | 		).Row().Scan(&count) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| @ -50,10 +54,7 @@ func (m Migrator) HasIndex(value interface{}, indexName string) bool { | |||||||
| 
 | 
 | ||||||
| func (m Migrator) CreateIndex(value interface{}, name string) error { | func (m Migrator) CreateIndex(value interface{}, name string) error { | ||||||
| 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
| 		err := fmt.Errorf("failed to create index with name %v", name) | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
| 		indexes := stmt.Schema.ParseIndexes() |  | ||||||
| 
 |  | ||||||
| 		if idx, ok := indexes[name]; ok { |  | ||||||
| 			opts := m.BuildIndexOptions(idx.Fields, stmt) | 			opts := m.BuildIndexOptions(idx.Fields, stmt) | ||||||
| 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | ||||||
| 
 | 
 | ||||||
| @ -73,18 +74,9 @@ func (m Migrator) CreateIndex(value interface{}, name string) error { | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return m.DB.Exec(createIndexSQL, values...).Error | 			return m.DB.Exec(createIndexSQL, values...).Error | ||||||
| 		} else if field := stmt.Schema.LookUpField(name); field != nil { |  | ||||||
| 			for _, idx := range indexes { |  | ||||||
| 				for _, idxOpt := range idx.Fields { |  | ||||||
| 					if idxOpt.Field == field { |  | ||||||
| 						if err = m.CreateIndex(value, idx.Name); err != nil { |  | ||||||
| 							return err |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		return err | 
 | ||||||
|  | 		return fmt.Errorf("failed to create index with name %v", name) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package sqlite | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/jinzhu/gorm" | 	"github.com/jinzhu/gorm" | ||||||
| 	"github.com/jinzhu/gorm/clause" | 	"github.com/jinzhu/gorm/clause" | ||||||
| @ -37,17 +38,6 @@ func (m Migrator) HasColumn(value interface{}, field string) bool { | |||||||
| 	return count > 0 | 	return count > 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m Migrator) HasIndex(value interface{}, name string) bool { |  | ||||||
| 	var count int |  | ||||||
| 	m.RunWithValue(value, func(stmt *gorm.Statement) error { |  | ||||||
| 		return m.DB.Raw( |  | ||||||
| 			"SELECT count(*) FROM sqlite_master WHERE type = ? AND tbl_name = ? AND sql LIKE ?", |  | ||||||
| 			"index", stmt.Table, "%INDEX "+name+" ON%", |  | ||||||
| 		).Row().Scan(&count) |  | ||||||
| 	}) |  | ||||||
| 	return count > 0 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (m Migrator) CreateConstraint(interface{}, string) error { | func (m Migrator) CreateConstraint(interface{}, string) error { | ||||||
| 	return gorm.ErrNotImplemented | 	return gorm.ErrNotImplemented | ||||||
| } | } | ||||||
| @ -83,10 +73,7 @@ func (m Migrator) BuildIndexOptions(opts []schema.IndexOption, stmt *gorm.Statem | |||||||
| 
 | 
 | ||||||
| func (m Migrator) CreateIndex(value interface{}, name string) error { | func (m Migrator) CreateIndex(value interface{}, name string) error { | ||||||
| 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
| 		err := fmt.Errorf("failed to create index with name %v", name) | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
| 		indexes := stmt.Schema.ParseIndexes() |  | ||||||
| 
 |  | ||||||
| 		if idx, ok := indexes[name]; ok { |  | ||||||
| 			opts := m.BuildIndexOptions(idx.Fields, stmt) | 			opts := m.BuildIndexOptions(idx.Fields, stmt) | ||||||
| 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | ||||||
| 
 | 
 | ||||||
| @ -106,17 +93,44 @@ func (m Migrator) CreateIndex(value interface{}, name string) error { | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return m.DB.Exec(createIndexSQL, values...).Error | 			return m.DB.Exec(createIndexSQL, values...).Error | ||||||
| 		} else if field := stmt.Schema.LookUpField(name); field != nil { |  | ||||||
| 			for _, idx := range indexes { |  | ||||||
| 				for _, idxOpt := range idx.Fields { |  | ||||||
| 					if idxOpt.Field == field { |  | ||||||
| 						if err = m.CreateIndex(value, idx.Name); err != nil { |  | ||||||
| 							return err |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		return err | 
 | ||||||
|  | 		return fmt.Errorf("failed to create index with name %v", name) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m Migrator) HasIndex(value interface{}, name string) bool { | ||||||
|  | 	var count int | ||||||
|  | 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		m.DB.Raw( | ||||||
|  | 			"SELECT count(*) FROM sqlite_master WHERE type = ? AND tbl_name = ? AND name = ?", "index", stmt.Table, name, | ||||||
|  | 		).Row().Scan(&count) | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 	return count > 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m Migrator) RenameIndex(value interface{}, oldName, newName string) error { | ||||||
|  | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		var sql string | ||||||
|  | 		m.DB.Raw("SELECT sql FROM sqlite_master WHERE type = ? AND tbl_name = ? AND name = ?", "index", stmt.Table, oldName).Row().Scan(&sql) | ||||||
|  | 		if sql != "" { | ||||||
|  | 			return m.DB.Exec(strings.Replace(sql, oldName, newName, 1)).Error | ||||||
|  | 		} | ||||||
|  | 		return fmt.Errorf("failed to find index with name %v", oldName) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m Migrator) DropIndex(value interface{}, name string) error { | ||||||
|  | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return m.DB.Exec("DROP INDEX ?", clause.Column{Name: name}).Error | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -418,10 +418,7 @@ type BuildIndexOptionsInterface interface { | |||||||
| 
 | 
 | ||||||
| func (m Migrator) CreateIndex(value interface{}, name string) error { | func (m Migrator) CreateIndex(value interface{}, name string) error { | ||||||
| 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
| 		err := fmt.Errorf("failed to create index with name %v", name) | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
| 		indexes := stmt.Schema.ParseIndexes() |  | ||||||
| 
 |  | ||||||
| 		if idx, ok := indexes[name]; ok { |  | ||||||
| 			opts := m.DB.Migrator().(BuildIndexOptionsInterface).BuildIndexOptions(idx.Fields, stmt) | 			opts := m.DB.Migrator().(BuildIndexOptionsInterface).BuildIndexOptions(idx.Fields, stmt) | ||||||
| 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | 			values := []interface{}{clause.Column{Name: idx.Name}, clause.Table{Name: stmt.Table}, opts} | ||||||
| 
 | 
 | ||||||
| @ -441,23 +438,18 @@ func (m Migrator) CreateIndex(value interface{}, name string) error { | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			return m.DB.Exec(createIndexSQL, values...).Error | 			return m.DB.Exec(createIndexSQL, values...).Error | ||||||
| 		} else if field := stmt.Schema.LookUpField(name); field != nil { |  | ||||||
| 			for _, idx := range indexes { |  | ||||||
| 				for _, idxOpt := range idx.Fields { |  | ||||||
| 					if idxOpt.Field == field { |  | ||||||
| 						if err = m.CreateIndex(value, idx.Name); err != nil { |  | ||||||
| 							return err |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		return err | 
 | ||||||
|  | 		return fmt.Errorf("failed to create index with name %v", name) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m Migrator) DropIndex(value interface{}, name string) error { | func (m Migrator) DropIndex(value interface{}, name string) error { | ||||||
| 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	return m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return m.DB.Exec("DROP INDEX ? ON ?", clause.Column{Name: name}, clause.Table{Name: stmt.Table}).Error | 		return m.DB.Exec("DROP INDEX ? ON ?", clause.Column{Name: name}, clause.Table{Name: stmt.Table}).Error | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| @ -466,6 +458,10 @@ func (m Migrator) HasIndex(value interface{}, name string) bool { | |||||||
| 	var count int64 | 	var count int64 | ||||||
| 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | 	m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
| 		currentDatabase := m.DB.Migrator().CurrentDatabase() | 		currentDatabase := m.DB.Migrator().CurrentDatabase() | ||||||
|  | 		if idx := stmt.Schema.LookIndex(name); idx != nil { | ||||||
|  | 			name = idx.Name | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return m.DB.Raw( | 		return m.DB.Raw( | ||||||
| 			"SELECT count(*) FROM information_schema.statistics WHERE table_schema = ? AND table_name = ? AND index_name = ?", | 			"SELECT count(*) FROM information_schema.statistics WHERE table_schema = ? AND table_name = ? AND index_name = ?", | ||||||
| 			currentDatabase, stmt.Table, name, | 			currentDatabase, stmt.Table, name, | ||||||
|  | |||||||
| @ -52,6 +52,23 @@ func (schema *Schema) ParseIndexes() map[string]Index { | |||||||
| 	return indexes | 	return indexes | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (schema *Schema) LookIndex(name string) *Index { | ||||||
|  | 	indexes := schema.ParseIndexes() | ||||||
|  | 	for _, index := range indexes { | ||||||
|  | 		if index.Name == name { | ||||||
|  | 			return &index | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for _, field := range index.Fields { | ||||||
|  | 			if field.Name == name { | ||||||
|  | 				return &index | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func parseFieldIndexes(field *Field) (indexes []Index) { | func parseFieldIndexes(field *Field) (indexes []Index) { | ||||||
| 	for _, value := range strings.Split(field.Tag.Get("gorm"), ";") { | 	for _, value := range strings.Split(field.Tag.Get("gorm"), ";") { | ||||||
| 		if value != "" { | 		if value != "" { | ||||||
|  | |||||||
| @ -46,3 +46,21 @@ func TestDelete(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestInlineCondDelete(t *testing.T) { | ||||||
|  | 	user1 := *GetUser("inline_delete_1", Config{}) | ||||||
|  | 	user2 := *GetUser("inline_delete_2", Config{}) | ||||||
|  | 	DB.Save(&user1).Save(&user2) | ||||||
|  | 
 | ||||||
|  | 	if DB.Delete(&User{}, user1.ID).Error != nil { | ||||||
|  | 		t.Errorf("No error should happen when delete a record") | ||||||
|  | 	} else if !DB.Where("name = ?", user1.Name).First(&User{}).RecordNotFound() { | ||||||
|  | 		t.Errorf("User can't be found after delete") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Delete(&User{}, "name = ?", user2.Name).Error; err != nil { | ||||||
|  | 		t.Errorf("No error should happen when delete a record, err=%s", err) | ||||||
|  | 	} else if !DB.Where("name = ?", user2.Name).First(&User{}).RecordNotFound() { | ||||||
|  | 		t.Errorf("User can't be found after delete") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/jinzhu/gorm" | ||||||
| 	. "github.com/jinzhu/gorm/tests" | 	. "github.com/jinzhu/gorm/tests" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -27,3 +28,46 @@ func TestMigrate(t *testing.T) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestIndexes(t *testing.T) { | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name string `gorm:"index"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Migrator().CreateIndex(&User{}, "Name"); err != nil { | ||||||
|  | 		t.Errorf("Got error when tried to create index: %+v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !DB.Migrator().HasIndex(&User{}, "Name") { | ||||||
|  | 		t.Errorf("Failed to find index for user's name") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Migrator().DropIndex(&User{}, "Name"); err != nil { | ||||||
|  | 		t.Errorf("Failed to drop index for user's name, got err %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if DB.Migrator().HasIndex(&User{}, "Name") { | ||||||
|  | 		t.Errorf("Should not find index for user's name after delete") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Migrator().CreateIndex(&User{}, "Name"); err != nil { | ||||||
|  | 		t.Errorf("Got error when tried to create index: %+v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Migrator().RenameIndex(&User{}, "idx_users_name", "idx_users_name_1"); err != nil { | ||||||
|  | 		t.Errorf("no error should happen when rename index, but got %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !DB.Migrator().HasIndex(&User{}, "idx_users_name_1") { | ||||||
|  | 		t.Errorf("Should find index for user's name after rename") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := DB.Migrator().DropIndex(&User{}, "idx_users_name_1"); err != nil { | ||||||
|  | 		t.Errorf("Failed to drop index for user's name, got err %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if DB.Migrator().HasIndex(&User{}, "idx_users_name_1") { | ||||||
|  | 		t.Errorf("Should not find index for user's name after delete") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -7,6 +7,8 @@ fi | |||||||
| for dialect in "${dialects[@]}" ; do | for dialect in "${dialects[@]}" ; do | ||||||
|   if [ "$GORM_DIALECT" = "" ] || [ "$GORM_DIALECT" = "${dialect}" ] |   if [ "$GORM_DIALECT" = "" ] || [ "$GORM_DIALECT" = "${dialect}" ] | ||||||
|   then |   then | ||||||
|  |     echo "testing ${dialect}..." | ||||||
|  | 
 | ||||||
|     if [ "$GORM_VERBOSE" = "" ] |     if [ "$GORM_VERBOSE" = "" ] | ||||||
|     then |     then | ||||||
|       DEBUG=false GORM_DIALECT=${dialect} go test -race ./... |       DEBUG=false GORM_DIALECT=${dialect} go test -race ./... | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu