From 28b50cbb2066d5d6f30899c323d1457117c50719 Mon Sep 17 00:00:00 2001 From: black Date: Thu, 15 Jun 2023 16:52:48 +0800 Subject: [PATCH 1/3] refactor: distinguish between Unique and UniqueIndex --- migrator.go | 16 ---------------- mysql.go | 5 +++-- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/migrator.go b/migrator.go index d35a86e..a92f6a4 100644 --- a/migrator.go +++ b/migrator.go @@ -184,22 +184,6 @@ func (m Migrator) DropTable(values ...interface{}) error { }) } -func (m Migrator) DropConstraint(value interface{}, name string) error { - return m.RunWithValue(value, func(stmt *gorm.Statement) error { - constraint, chk, table := m.GuessConstraintAndTable(stmt, name) - if chk != nil { - return m.DB.Exec("ALTER TABLE ? DROP CHECK ?", clause.Table{Name: stmt.Table}, clause.Column{Name: chk.Name}).Error - } - if constraint != nil { - name = constraint.Name - } - - return m.DB.Exec( - "ALTER TABLE ? DROP FOREIGN KEY ?", clause.Table{Name: table}, clause.Column{Name: name}, - ).Error - }) -} - // ColumnTypes column types return columnTypes,error func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) { columnTypes := make([]gorm.ColumnType, 0) diff --git a/mysql.go b/mysql.go index 68d02e8..e9dd6e7 100644 --- a/mysql.go +++ b/mysql.go @@ -268,8 +268,9 @@ func (dialector Dialector) Migrator(db *gorm.DB) gorm.Migrator { return Migrator{ Migrator: migrator.Migrator{ Config: migrator.Config{ - DB: db, - Dialector: dialector, + UniqueAffectedByUniqueIndex: true, + DB: db, + Dialector: dialector, }, }, Dialector: dialector, From 36889990e7e62d7f55c46967cab4a058f38efcde Mon Sep 17 00:00:00 2001 From: black Date: Mon, 19 Jun 2023 19:37:52 +0800 Subject: [PATCH 2/3] rewrite MigrateColumnUnique --- migrator.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mysql.go | 5 ++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/migrator.go b/migrator.go index a92f6a4..bce776d 100644 --- a/migrator.go +++ b/migrator.go @@ -47,6 +47,78 @@ func (m Migrator) FullDataTypeOf(field *schema.Field) clause.Expr { return expr } +// MigrateColumnUnique migrate column's UNIQUE constraint. +// In MySQL, ColumnType's Unique is affected by UniqueIndex, so we have to take care of the UniqueIndex. +func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, columnType gorm.ColumnType) error { + unique, ok := columnType.Unique() + if !ok || field.PrimaryKey { + return nil // skip primary key + } + + queryTx, execTx := m.GetQueryAndExecTx() + return m.RunWithValue(value, func(stmt *gorm.Statement) error { + // We're currently only receiving boolean values on `Unique` tag, + // so the UniqueConstraint name is fixed + constraint := m.DB.NamingStrategy.UniqueName(stmt.Table, field.DBName) + if unique { + // Clean up redundant unique indexes + indexes, _ := queryTx.Migrator().GetIndexes(value) + for _, index := range indexes { + if uni, ok := index.Unique(); !ok || !uni { + continue + } + if columns := index.Columns(); len(columns) != 1 || columns[0] != field.DBName { + continue + } + if name := index.Name(); name == constraint || name == field.UniqueIndex { + continue + } + if err := execTx.Migrator().DropIndex(value, index.Name()); err != nil { + return err + } + } + + hasConstraint := queryTx.Migrator().HasConstraint(value, constraint) + switch { + case field.Unique && !hasConstraint: + if field.Unique { + if err := execTx.Migrator().CreateConstraint(value, constraint); err != nil { + return err + } + } + // field isn't Unique but ColumnType's Unique is reported by UniqueConstraint. + case !field.Unique && hasConstraint: + if err := execTx.Migrator().DropConstraint(value, constraint); err != nil { + return err + } + if field.UniqueIndex != "" { + if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil { + return err + } + } + } + + if field.UniqueIndex != "" && !queryTx.Migrator().HasIndex(value, field.UniqueIndex) { + if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil { + return err + } + } + } else { + if field.Unique { + if err := execTx.Migrator().CreateConstraint(value, constraint); err != nil { + return err + } + } + if field.UniqueIndex != "" { + if err := execTx.Migrator().CreateIndex(value, field.UniqueIndex); err != nil { + return err + } + } + } + return nil + }) +} + func (m Migrator) AlterColumn(value interface{}, field string) error { return m.RunWithValue(value, func(stmt *gorm.Statement) error { if stmt.Schema != nil { diff --git a/mysql.go b/mysql.go index e9dd6e7..68d02e8 100644 --- a/mysql.go +++ b/mysql.go @@ -268,9 +268,8 @@ func (dialector Dialector) Migrator(db *gorm.DB) gorm.Migrator { return Migrator{ Migrator: migrator.Migrator{ Config: migrator.Config{ - UniqueAffectedByUniqueIndex: true, - DB: db, - Dialector: dialector, + DB: db, + Dialector: dialector, }, }, Dialector: dialector, From 9f265619d04ed32499c71e409119c9c3de460a0f Mon Sep 17 00:00:00 2001 From: black Date: Sun, 4 Feb 2024 17:26:36 +0800 Subject: [PATCH 3/3] update gorm to master latest (for https://github.com/go-gorm/gorm/pull/6386) --- go.mod | 2 +- go.sum | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index fc63353..6ee0e28 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,5 @@ go 1.14 require ( github.com/go-sql-driver/mysql v1.7.0 - gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 + gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde ) diff --git a/go.sum b/go.sum index 5db00fb..8165163 100644 --- a/go.sum +++ b/go.sum @@ -7,4 +7,8 @@ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ= -gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= \ No newline at end of file +gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.6-0.20231115133256-3207ad6033aa h1:cGDODlWbAjO6jreDwDD34SsdQVhuFE5KjXO1LmpKZYQ= +gorm.io/gorm v1.25.6-0.20231115133256-3207ad6033aa/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde h1:9DShaph9qhkIYw7QF91I/ynrr4cOO2PZra2PFD7Mfeg= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=