From 92bc52270eef31212791eea77454eeb5bba71f74 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 13:45:11 -0400 Subject: [PATCH 1/7] use IF EXISTS --- migrator/migrator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 189a141f..1c15d1ff 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -762,7 +762,8 @@ func (m Migrator) DropConstraint(value interface{}, name string) error { if constraint != nil { name = constraint.GetName() } - return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error + // using IF EXISTS here as we are "guessing" the constraint name + return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT IF EXISTS ?", clause.Table{Name: table}, clause.Column{Name: name}).Error }) } From e55b2ba3120b7bdc797d007e73455ab68207c2d4 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 14:32:27 -0400 Subject: [PATCH 2/7] if exists doesn't work for mysql, so have to verify constraint exists. --- migrator/migrator.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 1c15d1ff..d9218ede 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -762,8 +762,11 @@ func (m Migrator) DropConstraint(value interface{}, name string) error { if constraint != nil { name = constraint.GetName() } - // using IF EXISTS here as we are "guessing" the constraint name - return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT IF EXISTS ?", clause.Table{Name: table}, clause.Column{Name: name}).Error + // ensure the constraint exists first as we are "guessing" the constraint name + if m.HasConstraint(value, name) { + return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error + } + return nil }) } From 79e73f0d7d9cb1123b10b3e527463449a0e4e9d1 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 16:17:38 -0400 Subject: [PATCH 3/7] move to the caller --- migrator/migrator.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index d9218ede..c763c8a9 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -587,7 +587,7 @@ func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, co // 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 && !field.Unique { + if unique && !field.Unique && m.HasConstraint(value, constraint) { return m.DB.Migrator().DropConstraint(value, constraint) } if !unique && field.Unique { @@ -762,11 +762,8 @@ func (m Migrator) DropConstraint(value interface{}, name string) error { if constraint != nil { name = constraint.GetName() } - // ensure the constraint exists first as we are "guessing" the constraint name - if m.HasConstraint(value, name) { - return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error - } - return nil + + return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error }) } From e483cd9993199dafb4e3ceb9065a81a2dc039144 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 16:31:37 -0400 Subject: [PATCH 4/7] put check back in drop --- migrator/migrator.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index c763c8a9..7d923851 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -587,7 +587,7 @@ func (m Migrator) MigrateColumnUnique(value interface{}, field *schema.Field, co // 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 && !field.Unique && m.HasConstraint(value, constraint) { + if unique && !field.Unique { return m.DB.Migrator().DropConstraint(value, constraint) } if !unique && field.Unique { @@ -758,11 +758,13 @@ func (m Migrator) CreateConstraint(value interface{}, name string) error { // DropConstraint drop constraint func (m Migrator) DropConstraint(value interface{}, name string) error { return m.RunWithValue(value, func(stmt *gorm.Statement) error { + if !m.HasConstraint(value, name) { + return nil + } constraint, table := m.GuessConstraintInterfaceAndTable(stmt, name) if constraint != nil { name = constraint.GetName() } - return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error }) } From 38fb45fea80ecd091e72396d5cdc0218ee3725c7 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 17:01:58 -0400 Subject: [PATCH 5/7] debug --- migrator/migrator.go | 3 ++- tests/migrate_test.go | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 7d923851..678cf566 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -759,7 +759,8 @@ func (m Migrator) CreateConstraint(value interface{}, name string) error { func (m Migrator) DropConstraint(value interface{}, name string) error { return m.RunWithValue(value, func(stmt *gorm.Statement) error { if !m.HasConstraint(value, name) { - return nil + constraint, _ := m.GuessConstraintInterfaceAndTable(stmt, name) + return errors.New(fmt.Sprintf("Can't find constraint for %q, with guessed name %q", name, constraint)) } constraint, table := m.GuessConstraintInterfaceAndTable(stmt, name) if constraint != nil { diff --git a/tests/migrate_test.go b/tests/migrate_test.go index d955c8d7..079dde0f 100644 --- a/tests/migrate_test.go +++ b/tests/migrate_test.go @@ -681,6 +681,10 @@ func TestMigrateConstraint(t *testing.T) { DB.Migrator().CreateConstraint(&User{}, name) } + if !DB.Migrator().HasConstraint(&User{}, name) { + t.Fatalf("failed to create constraint %v", name) + } + if err := DB.Migrator().DropConstraint(&User{}, name); err != nil { t.Fatalf("failed to drop constraint %v, got error %v", name, err) } From 3198b7c2192cc14c42ec3ea705cbedd3a5410ea6 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 17:23:39 -0400 Subject: [PATCH 6/7] more tracing --- migrator/migrator.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 678cf566..079754e1 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -710,6 +710,7 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for _, rel := range stmt.Schema.Relationships.Relations { if constraint := rel.ParseConstraint(); constraint != nil && constraint.Name == name { + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation 0 %q", constraint)) return constraint, getTable(rel) } } @@ -718,6 +719,7 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for k := range checkConstraints { if checkConstraints[k].Field == field { v := checkConstraints[k] + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for check %q", &v)) return &v, stmt.Table } } @@ -725,12 +727,14 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for k := range uniqueConstraints { if uniqueConstraints[k].Field == field { v := uniqueConstraints[k] + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for unique %q", &v)) return &v, stmt.Table } } for _, rel := range stmt.Schema.Relationships.Relations { if constraint := rel.ParseConstraint(); constraint != nil && rel.Field == field { + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation %q", constraint)) return constraint, getTable(rel) } } @@ -757,10 +761,10 @@ func (m Migrator) CreateConstraint(value interface{}, name string) error { // DropConstraint drop constraint func (m Migrator) DropConstraint(value interface{}, name string) error { + fmt.Println(fmt.Sprintf("SHREWS --In Drop %q", name)) return m.RunWithValue(value, func(stmt *gorm.Statement) error { if !m.HasConstraint(value, name) { - constraint, _ := m.GuessConstraintInterfaceAndTable(stmt, name) - return errors.New(fmt.Sprintf("Can't find constraint for %q, with guessed name %q", name, constraint)) + return nil } constraint, table := m.GuessConstraintInterfaceAndTable(stmt, name) if constraint != nil { From 003bcc3a3556cd2891b62bdede1fdebf67d0f883 Mon Sep 17 00:00:00 2001 From: Dave Shrewsberry Date: Thu, 1 Aug 2024 17:26:20 -0400 Subject: [PATCH 7/7] more tracing --- migrator/migrator.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index 079754e1..56fe3872 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -710,7 +710,7 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for _, rel := range stmt.Schema.Relationships.Relations { if constraint := rel.ParseConstraint(); constraint != nil && constraint.Name == name { - fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation 0 %q", constraint)) + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation 0 %v", constraint)) return constraint, getTable(rel) } } @@ -719,7 +719,7 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for k := range checkConstraints { if checkConstraints[k].Field == field { v := checkConstraints[k] - fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for check %q", &v)) + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for check %v", &v)) return &v, stmt.Table } } @@ -727,14 +727,14 @@ func (m Migrator) GuessConstraintInterfaceAndTable(stmt *gorm.Statement, name st for k := range uniqueConstraints { if uniqueConstraints[k].Field == field { v := uniqueConstraints[k] - fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for unique %q", &v)) + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for unique %v", &v)) return &v, stmt.Table } } for _, rel := range stmt.Schema.Relationships.Relations { if constraint := rel.ParseConstraint(); constraint != nil && rel.Field == field { - fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation %q", constraint)) + fmt.Println(fmt.Sprintf("SHREWS --Out of Guess for relation %v", constraint)) return constraint, getTable(rel) } }