Add Migrator
This commit is contained in:
		
							parent
							
								
									43ce0b8af2
								
							
						
					
					
						commit
						62dcd7896a
					
				| @ -75,13 +75,10 @@ func (p *processor) Execute(db *DB) { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if stmt.Model != nil { | 		if stmt.Model != nil { | ||||||
| 			var err error | 			err := stmt.Parse(stmt.Model) | ||||||
| 			stmt.Schema, err = schema.Parse(stmt.Model, db.cacheStore, db.NamingStrategy) |  | ||||||
| 
 | 
 | ||||||
| 			if err != nil && (!errors.Is(err, schema.ErrUnsupportedDataType) || stmt.Table == "") { | 			if err != nil && (!errors.Is(err, schema.ErrUnsupportedDataType) || stmt.Table == "") { | ||||||
| 				db.AddError(err) | 				db.AddError(err) | ||||||
| 			} else if stmt.Table == "" && stmt.Schema != nil { |  | ||||||
| 				stmt.Table = stmt.Schema.Table |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -15,6 +15,8 @@ var ( | |||||||
| 	ErrInvalidTransaction = errors.New("no valid transaction") | 	ErrInvalidTransaction = errors.New("no valid transaction") | ||||||
| 	// ErrUnaddressable unaddressable value
 | 	// ErrUnaddressable unaddressable value
 | ||||||
| 	ErrUnaddressable = errors.New("using unaddressable value") | 	ErrUnaddressable = errors.New("using unaddressable value") | ||||||
|  | 	// ErrNotImplemented not implemented
 | ||||||
|  | 	ErrNotImplemented = errors.New("not implemented") | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt
 | // Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt
 | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								migrator.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								migrator.go
									
									
									
									
									
								
							| @ -4,6 +4,11 @@ import ( | |||||||
| 	"database/sql" | 	"database/sql" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // Migrator returns migrator
 | ||||||
|  | func (db *DB) Migrator() Migrator { | ||||||
|  | 	return db.Dialector.Migrator() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ViewOption view option
 | // ViewOption view option
 | ||||||
| type ViewOption struct { | type ViewOption struct { | ||||||
| 	Replace     bool | 	Replace     bool | ||||||
| @ -15,10 +20,13 @@ type Migrator interface { | |||||||
| 	// AutoMigrate
 | 	// AutoMigrate
 | ||||||
| 	AutoMigrate(dst ...interface{}) error | 	AutoMigrate(dst ...interface{}) error | ||||||
| 
 | 
 | ||||||
|  | 	// Database
 | ||||||
|  | 	CurrentDatabase() string | ||||||
|  | 
 | ||||||
| 	// Tables
 | 	// Tables
 | ||||||
| 	CreateTable(dst ...interface{}) error | 	CreateTable(dst ...interface{}) error | ||||||
| 	DropTable(dst ...interface{}) error | 	DropTable(dst ...interface{}) error | ||||||
| 	HasTable(dst ...interface{}) error | 	HasTable(dst ...interface{}) bool | ||||||
| 	RenameTable(oldName, newName string) error | 	RenameTable(oldName, newName string) error | ||||||
| 
 | 
 | ||||||
| 	// Columns
 | 	// Columns
 | ||||||
| @ -39,6 +47,6 @@ type Migrator interface { | |||||||
| 	// Indexes
 | 	// Indexes
 | ||||||
| 	CreateIndex(dst interface{}, name string) error | 	CreateIndex(dst interface{}, name string) error | ||||||
| 	DropIndex(dst interface{}, name string) error | 	DropIndex(dst interface{}, name string) error | ||||||
| 	HasIndex(dst interface{}, name string) error | 	HasIndex(dst interface{}, name string) bool | ||||||
| 	RenameIndex(dst interface{}, oldName, newName string) error | 	RenameIndex(dst interface{}, oldName, newName string) error | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,11 @@ | |||||||
| package migrator | package migrator | ||||||
| 
 | 
 | ||||||
| import "github.com/jinzhu/gorm" | import ( | ||||||
|  | 	"database/sql" | ||||||
|  | 	"fmt" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jinzhu/gorm" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // Migrator migrator struct
 | // Migrator migrator struct
 | ||||||
| type Migrator struct { | type Migrator struct { | ||||||
| @ -12,3 +17,149 @@ type Config struct { | |||||||
| 	CheckExistsBeforeDropping bool | 	CheckExistsBeforeDropping bool | ||||||
| 	DB                        *gorm.DB | 	DB                        *gorm.DB | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) RunWithValue(value interface{}, fc func(*gorm.Statement) error) error { | ||||||
|  | 	stmt := migrator.DB.Statement | ||||||
|  | 	if stmt == nil { | ||||||
|  | 		stmt = &gorm.Statement{DB: migrator.DB} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := stmt.Parse(value); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return fc(stmt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AutoMigrate
 | ||||||
|  | func (migrator Migrator) AutoMigrate(values ...interface{}) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) CreateTable(values ...interface{}) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) DropTable(values ...interface{}) error { | ||||||
|  | 	for _, value := range values { | ||||||
|  | 		if err := migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 			return migrator.DB.Exec("DROP TABLE " + stmt.Quote(stmt.Table)).Error | ||||||
|  | 		}); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) HasTable(values ...interface{}) bool { | ||||||
|  | 	var count int64 | ||||||
|  | 	for _, value := range values { | ||||||
|  | 		err := migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 			currentDatabase := migrator.DB.Migrator().CurrentDatabase() | ||||||
|  | 			return migrator.DB.Raw("SELECT count(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = ? AND table_type = ?", currentDatabase, stmt.Table, "BASE TABLE").Scan(&count).Error | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		if err != nil || count == 0 { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) RenameTable(oldName, newName string) error { | ||||||
|  | 	return migrator.DB.Exec("RENAME TABLE ? TO ?", oldName, newName).Error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) AddColumn(value interface{}, field string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if field := stmt.Schema.LookUpField(field); field != nil { | ||||||
|  | 			return migrator.DB.Exec(fmt.Sprintf("ALTER TABLE ? ADD ? %s", field.DBDataType), stmt.Table, field.DBName).Error | ||||||
|  | 		} | ||||||
|  | 		return fmt.Errorf("failed to look up field with name: %s", field) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) DropColumn(value interface{}, field string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if field := stmt.Schema.LookUpField(field); field != nil { | ||||||
|  | 			return migrator.DB.Exec("ALTER TABLE ? DROP COLUMN ?", stmt.Table, field.DBName).Error | ||||||
|  | 		} | ||||||
|  | 		return fmt.Errorf("failed to look up field with name: %s", field) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) AlterColumn(value interface{}, field string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if field := stmt.Schema.LookUpField(field); field != nil { | ||||||
|  | 			return migrator.DB.Exec(fmt.Sprintf("ALTER TABLE ? ALTER COLUMN ? TYPE %s", field.DBDataType), stmt.Table, field.DBName).Error | ||||||
|  | 		} | ||||||
|  | 		return fmt.Errorf("failed to look up field with name: %s", field) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) RenameColumn(value interface{}, oldName, field string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		if field := stmt.Schema.LookUpField(field); field != nil { | ||||||
|  | 			oldName = migrator.DB.NamingStrategy.ColumnName(stmt.Table, oldName) | ||||||
|  | 			return migrator.DB.Exec("ALTER TABLE ? RENAME COLUMN ? TO ?", stmt.Table, oldName, field.DBName).Error | ||||||
|  | 		} | ||||||
|  | 		return fmt.Errorf("failed to look up field with name: %s", field) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) ColumnTypes(value interface{}) ([]*sql.ColumnType, error) { | ||||||
|  | 	return nil, gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) CreateView(name string, option gorm.ViewOption) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) DropView(name string) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) CreateConstraint(value interface{}, name string) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) DropConstraint(value interface{}, name string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		return migrator.DB.Raw("ALTER TABLE ? DROP CONSTRAINT ?", stmt.Table, name).Error | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) CreateIndex(value interface{}, name string) error { | ||||||
|  | 	return gorm.ErrNotImplemented | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) DropIndex(value interface{}, name string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		return migrator.DB.Raw("DROP INDEX ? ON ?", name, stmt.Table).Error | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) HasIndex(value interface{}, name string) bool { | ||||||
|  | 	var count int64 | ||||||
|  | 	migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		currentDatabase := migrator.DB.Migrator().CurrentDatabase() | ||||||
|  | 		return migrator.DB.Raw("SELECT count(*) FROM information_schema.statistics WHERE table_schema = ? AND table_name = ? AND index_name = ?", currentDatabase, stmt.Table, name).Scan(&count).Error | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	if count != 0 { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) RenameIndex(value interface{}, oldName, newName string) error { | ||||||
|  | 	return migrator.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||||
|  | 		return migrator.DB.Exec("ALTER TABLE ? RENAME INDEX ? TO ?", stmt.Table, oldName, newName).Error | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (migrator Migrator) CurrentDatabase() (name string) { | ||||||
|  | 	migrator.DB.Raw("SELECT DATABASE()").Scan(&name) | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | |||||||
| @ -267,3 +267,10 @@ func (stmt *Statement) Build(clauses ...string) { | |||||||
| 	} | 	} | ||||||
| 	// TODO handle named vars
 | 	// TODO handle named vars
 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (stmt *Statement) Parse(value interface{}) (err error) { | ||||||
|  | 	if stmt.Schema, err = schema.Parse(value, stmt.DB.cacheStore, stmt.DB.NamingStrategy); err == nil && stmt.Table == "" { | ||||||
|  | 		stmt.Table = stmt.Schema.Table | ||||||
|  | 	} | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu