@@ -308,15 +308,47 @@ func (m Migrator) DropColumn(value interface{}, name string) error {
308308func (m Migrator ) AlterColumn (value interface {}, field string ) error {
309309 return m .RunWithValue (value , func (stmt * gorm.Statement ) error {
310310 if stmt .Schema != nil {
311- if field := stmt .Schema .LookUpField (field ); field != nil {
312- fileType := m .FullDataTypeOf (field )
311+ if f := stmt .Schema .LookUpField (field ); f != nil {
312+ columnTypes , err := m .ColumnTypes (value )
313+ if err != nil {
314+ return err
315+ }
316+
317+ var currentNullable bool
318+ var currentType string
319+ for _ , col := range columnTypes {
320+ if strings .EqualFold (col .Name (), f .DBName ) {
321+ currentNullable , _ = col .Nullable ()
322+ currentType = strings .ToUpper (col .DatabaseTypeName ())
323+ break
324+ }
325+ }
326+
327+ desiredNullable := ! f .NotNull
328+ desiredType := strings .ToUpper (m .DataTypeOf (f ))
329+
330+ // nullable → non-nullable → skip
331+ if currentNullable && ! desiredNullable {
332+ return nil
333+ }
334+
335+ // same type + same nullability → skip
336+ if currentNullable == desiredNullable && strings .Contains (currentType , desiredType ) {
337+ return nil
338+ }
339+
340+ sql := "ALTER TABLE ? MODIFY ? " + m .DataTypeOf (f )
341+ if f .NotNull {
342+ sql += " NOT NULL"
343+ } else if ! currentNullable && desiredNullable {
344+ sql += " NULL"
345+ }
346+
313347 return m .DB .Exec (
314- "ALTER TABLE ? MODIFY ? ?" ,
348+ sql ,
315349 clause.Table {Name : stmt .Schema .Table },
316- clause.Column {Name : field .DBName },
317- fileType ,
350+ clause.Column {Name : f .DBName },
318351 ).Error
319-
320352 }
321353 }
322354 return fmt .Errorf ("failed to look up field with name: %s" , field )
0 commit comments