加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
migrator.go 6.94 KB
一键复制 编辑 原始数据 按行查看 历史
encircles 提交于 2021-11-26 17:02 . fix: hasIndex
package dm8
import (
"fmt"
"strings"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/migrator"
)
type Migrator struct {
migrator.Migrator
}
func (m Migrator) CurrentDatabase() (name string) {
m.DB.Raw(
fmt.Sprintf(`SELECT SYS_CONTEXT ('userenv', 'current_schema') "Current Database" FROM %s`, m.Dialector.(Dialector).DummyTableName()),
).Row().Scan(&name)
return
}
func (m Migrator) CreateTable(values ...interface{}) error {
m.TryQuotifyReservedWords(values)
m.TryRemoveOnUpdate(values)
return m.Migrator.CreateTable(values...)
}
func (m Migrator) DropTable(values ...interface{}) error {
values = m.ReorderModels(values, false)
for i := len(values) - 1; i >= 0; i-- {
value := values[i]
tx := m.DB.Session(&gorm.Session{})
if m.HasTable(value) {
if err := m.RunWithValue(value, func(stmt *gorm.Statement) error {
return tx.Exec("DROP TABLE ? CASCADE CONSTRAINTS", clause.Table{Name: stmt.Table}).Error
}); err != nil {
return err
}
}
}
return nil
}
func (m Migrator) HasTable(value interface{}) bool {
var count int64
m.RunWithValue(value, func(stmt *gorm.Statement) error {
// 判断 表空间内是否有表
// error: SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = '"TEST.WISDOM".jwt_blacklist'
// right: SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = 'DEMO' AND TABLESPACE_NAME = 'WISDOM_TEST'
sql := "SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = ?"
var tableSpaceName string
if n, ok := stmt.DB.NamingStrategy.(Namer); ok {
tableSpaceName = n.TableSpaceName
sql += " AND TABLESPACE_NAME = ?"
return m.DB.Raw(sql, stmt.Table, tableSpaceName).Row().Scan(&count)
} else {
return m.DB.Raw(sql, stmt.Table).Row().Scan(&count)
}
})
return count > 0
}
func (m Migrator) RenameTable(oldName, newName interface{}) (err error) {
resolveTable := func(name interface{}) (result string, err error) {
if v, ok := name.(string); ok {
result = v
} else {
stmt := &gorm.Statement{DB: m.DB}
if err = stmt.Parse(name); err == nil {
result = stmt.Table
}
}
return
}
var oldTable, newTable string
if oldTable, err = resolveTable(oldName); err != nil {
return
}
if newTable, err = resolveTable(newName); err != nil {
return
}
if !m.HasTable(oldTable) {
return
}
return m.DB.Exec("RENAME TABLE ? TO ?",
clause.Table{Name: oldTable},
clause.Table{Name: newTable},
).Error
}
func (m Migrator) AddColumn(value interface{}, field string) error {
if !m.HasColumn(value, field) {
return nil
}
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
if field := stmt.Schema.LookUpField(field); field != nil {
return m.DB.Exec(
"ALTER TABLE ? ADD ? ?",
clause.Table{Name: stmt.Table}, clause.Column{Name: field.DBName}, m.DB.Migrator().FullDataTypeOf(field),
).Error
}
return fmt.Errorf("failed to look up field with name: %s", field)
})
}
func (m Migrator) DropColumn(value interface{}, name string) error {
if !m.HasColumn(value, name) {
return nil
}
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
if field := stmt.Schema.LookUpField(name); field != nil {
name = field.DBName
}
return m.DB.Exec(
"ALTER TABLE ? DROP ?",
clause.Table{Name: stmt.Table},
clause.Column{Name: name},
).Error
})
}
func (m Migrator) AlterColumn(value interface{}, field string) error {
field = strings.ToUpper(field)
if !m.HasColumn(value, field) {
return nil
}
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
if field := stmt.Schema.LookUpField(field); field != nil {
return m.DB.Exec(
"ALTER TABLE ? MODIFY ? ?",
clause.Table{Name: stmt.Table},
clause.Column{Name: field.DBName},
m.FullDataTypeOf(field),
).Error
}
return fmt.Errorf("failed to look up field with name: %s", field)
})
}
func (m Migrator) HasColumn(value interface{}, field string) bool {
var count int64
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
return m.DB.Raw("SELECT COUNT(*) FROM USER_TAB_COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ?", stmt.Table, field).Row().Scan(&count)
}) == nil && count > 0
}
func (m Migrator) CreateConstraint(value interface{}, name string) error {
m.TryRemoveOnUpdate(value)
return m.Migrator.CreateConstraint(value, name)
}
func (m Migrator) DropConstraint(value interface{}, name string) error {
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
for _, chk := range stmt.Schema.ParseCheckConstraints() {
if chk.Name == name {
return m.DB.Exec(
"ALTER TABLE ? DROP CHECK ?",
clause.Table{Name: stmt.Table}, clause.Column{Name: name},
).Error
}
}
return m.DB.Exec(
"ALTER TABLE ? DROP CONSTRAINT ?",
clause.Table{Name: stmt.Table}, clause.Column{Name: name},
).Error
})
}
func (m Migrator) HasConstraint(value interface{}, name string) bool {
var count int64
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
return m.DB.Raw(
"SELECT COUNT(*) FROM USER_CONSTRAINTS WHERE TABLE_NAME = ? AND CONSTRAINT_NAME = ?", stmt.Table, name,
).Row().Scan(&count)
}) == nil && count > 0
}
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}, clause.Table{Name: stmt.Table}).Error
})
}
func (m Migrator) HasIndex(value interface{}, name string) bool {
var count int64
m.RunWithValue(value, func(stmt *gorm.Statement) error {
if idx := stmt.Schema.LookIndex(name); idx != nil {
name = idx.Name
}
return m.DB.Raw(
"SELECT COUNT(*) FROM USER_INDEXES WHERE TABLE_NAME = ? AND INDEX_NAME = ?",
stmt.Table,
name,
).Row().Scan(&count)
})
return count > 0
}
// https://docs.oracle.com/database/121/SPATL/alter-index-rename.htm
func (m Migrator) RenameIndex(value interface{}, oldName, newName string) error {
panic("TODO")
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
return m.DB.Exec(
"ALTER INDEX ?.? RENAME TO ?", // wat
clause.Table{Name: stmt.Table}, clause.Column{Name: oldName}, clause.Column{Name: newName},
).Error
})
}
func (m Migrator) TryRemoveOnUpdate(value interface{}) error {
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
for _, rel := range stmt.Schema.Relationships.Relations {
constraint := rel.ParseConstraint()
if constraint != nil {
rel.Field.TagSettings["CONSTRAINT"] = strings.ReplaceAll(rel.Field.TagSettings["CONSTRAINT"], fmt.Sprintf("ON UPDATE %s", constraint.OnUpdate), "")
}
}
return nil
})
}
func (m Migrator) TryQuotifyReservedWords(values []interface{}) error {
return m.RunWithValue(values, func(stmt *gorm.Statement) error {
for idx, v := range stmt.Schema.DBNames {
if IsReservedWord(v) {
stmt.Schema.DBNames[idx] = fmt.Sprintf(`"%s"`, v)
}
}
for _, v := range stmt.Schema.Fields {
if IsReservedWord(v.DBName) {
v.DBName = fmt.Sprintf(`"%s"`, v.DBName)
}
}
return nil
})
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化