Skip to content

Commit ef00905

Browse files
committed
Fix some alter column logic
Fixes #524
1 parent 83af561 commit ef00905

2 files changed

Lines changed: 53 additions & 28 deletions

File tree

src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,17 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M
316316
var column = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name);
317317
var alterBase = $"ALTER TABLE {table} ALTER COLUMN {column} ";
318318

319+
// TYPE
320+
builder.Append(alterBase)
321+
.Append("TYPE ")
322+
.Append(type)
323+
.AppendLine(';');
324+
325+
// NOT NULL
326+
builder.Append(alterBase)
327+
.Append(operation.IsNullable ? "DROP NOT NULL" : "SET NOT NULL")
328+
.AppendLine(';');
329+
319330
CheckForOldValueGenerationAnnotation(operation);
320331

321332
var oldStrategy = operation.OldColumn[NpgsqlAnnotationNames.ValueGenerationStrategy] as NpgsqlValueGenerationStrategy?;
@@ -401,7 +412,10 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M
401412
Name = newSequenceName,
402413
ClrType = operation.ClrType
403414
}, model, builder);
404-
defaultValueSql = $@"nextval('{Dependencies.SqlGenerationHelper.DelimitIdentifier(newSequenceName)}')";
415+
416+
builder.Append(alterBase).Append("SET");
417+
DefaultValue(null, $@"nextval('{Dependencies.SqlGenerationHelper.DelimitIdentifier(newSequenceName)}')", builder);
418+
builder.AppendLine(';');
405419
// Note: we also need to set the sequence ownership, this is done below after the ALTER COLUMN
406420
break;
407421
}
@@ -412,22 +426,10 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M
412426
}
413427
}
414428

415-
// TYPE
416-
builder.Append(alterBase)
417-
.Append("TYPE ")
418-
.Append(type)
419-
.AppendLine(';');
420-
421-
// NOT NULL
422-
builder.Append(alterBase)
423-
.Append(operation.IsNullable ? "DROP NOT NULL" : "SET NOT NULL")
424-
.AppendLine(';');
425-
426429
// DEFAULT.
427-
// Note that identity columns don't have a regular default but trying
428-
// to drop the default triggers an error.
429-
if (newStrategy != NpgsqlValueGenerationStrategy.IdentityAlwaysColumn &&
430-
newStrategy != NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
430+
// Note that defaults values for value-generated columns (identity, serial) are managed above. This is
431+
// only for regular columns with user-specified default settings.
432+
if (newStrategy == null)
431433
{
432434
builder.Append(alterBase);
433435
if (operation.DefaultValue != null || defaultValueSql != null)

test/EFCore.PG.FunctionalTests/NpgsqlMigrationSqlGeneratorTest.cs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,9 @@ public void AlterColumnOperation_to_identity()
471471
});
472472

473473
Assert.Equal(
474-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" ADD GENERATED ALWAYS AS IDENTITY;" + EOL +
475474
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" TYPE integer;" + EOL +
476-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL,
475+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL +
476+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" ADD GENERATED ALWAYS AS IDENTITY;" + EOL,
477477
Sql);
478478
}
479479

@@ -491,10 +491,10 @@ public void AlterColumnOperation_int_to_serial()
491491
});
492492

493493
Assert.Equal(
494-
@"CREATE SEQUENCE ""People_IntKey_seq"" AS integer START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE NO CYCLE;" + EOL +
495-
@"GO" + EOL + EOL + // Note that GO here is just a delimiter introduced in the tests to indicate a batch boundary
496494
@"ALTER TABLE ""People"" ALTER COLUMN ""IntKey"" TYPE integer;" + EOL +
497495
@"ALTER TABLE ""People"" ALTER COLUMN ""IntKey"" SET NOT NULL;" + EOL +
496+
@"CREATE SEQUENCE ""People_IntKey_seq"" AS integer START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE NO CYCLE;" + EOL +
497+
@"GO" + EOL + EOL + // Note that GO here is just a delimiter introduced in the tests to indicate a batch boundary
498498
@"ALTER TABLE ""People"" ALTER COLUMN ""IntKey"" SET DEFAULT (nextval('""People_IntKey_seq""'));" + EOL +
499499
@"ALTER SEQUENCE ""People_IntKey_seq"" OWNED BY ""People"".""IntKey"";" + EOL,
500500
Sql);
@@ -514,10 +514,10 @@ public void AlterColumnOperation_long_to_bigserial()
514514
});
515515

516516
Assert.Equal(
517-
@"CREATE SEQUENCE ""People_LongKey_seq"" START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE NO CYCLE;" + EOL +
518-
@"GO" + EOL + EOL + // Note that GO here is just a delimiter introduced in the tests to indicate a batch boundary
519517
@"ALTER TABLE ""People"" ALTER COLUMN ""LongKey"" TYPE bigint;" + EOL +
520518
@"ALTER TABLE ""People"" ALTER COLUMN ""LongKey"" SET NOT NULL;" + EOL +
519+
@"CREATE SEQUENCE ""People_LongKey_seq"" START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE NO CYCLE;" + EOL +
520+
@"GO" + EOL + EOL + // Note that GO here is just a delimiter introduced in the tests to indicate a batch boundary
521521
@"ALTER TABLE ""People"" ALTER COLUMN ""LongKey"" SET DEFAULT (nextval('""People_LongKey_seq""'));" + EOL +
522522
@"ALTER SEQUENCE ""People_LongKey_seq"" OWNED BY ""People"".""LongKey"";" + EOL,
523523
Sql);
@@ -540,9 +540,9 @@ public void AlterColumnOperation_identity_to_identity()
540540
});
541541

542542
Assert.Equal(
543-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET GENERATED ALWAYS;" + EOL +
544543
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" TYPE integer;" + EOL +
545-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL,
544+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL +
545+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET GENERATED ALWAYS;" + EOL,
546546
Sql);
547547
}
548548

@@ -562,13 +562,36 @@ public void AlterColumnOperation_serial_to_identity()
562562
[NpgsqlAnnotationNames.ValueGenerationStrategy] = NpgsqlValueGenerationStrategy.IdentityAlwaysColumn
563563
});
564564

565-
Assert.Equal(@"ALTER SEQUENCE ""People_Id_seq"" RENAME TO ""People_Id_old_seq"";" + EOL +
565+
Assert.Equal(
566+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" TYPE integer;" + EOL +
567+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL +
568+
@"ALTER SEQUENCE ""People_Id_seq"" RENAME TO ""People_Id_old_seq"";" + EOL +
566569
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" DROP DEFAULT;" + EOL +
567570
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" ADD GENERATED ALWAYS AS IDENTITY;" + EOL +
568571
@"SELECT * FROM setval('""People_Id_seq""', nextval('""People_Id_old_seq""'), false);" + EOL +
569-
@"DROP SEQUENCE ""People_Id_old_seq"";" + EOL +
570-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" TYPE integer;" + EOL +
571-
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL,
572+
@"DROP SEQUENCE ""People_Id_old_seq"";" + EOL,
573+
Sql);
574+
}
575+
576+
[Fact]
577+
public void AlterColumnOperation_serial_change_type()
578+
{
579+
Generate(
580+
new AlterColumnOperation
581+
{
582+
Table = "People",
583+
Name = "Id",
584+
ClrType = typeof(long),
585+
OldColumn = new ColumnOperation
586+
{
587+
ClrType = typeof(int),
588+
[NpgsqlAnnotationNames.ValueGenerationStrategy] = NpgsqlValueGenerationStrategy.SerialColumn
589+
},
590+
[NpgsqlAnnotationNames.ValueGenerationStrategy] = NpgsqlValueGenerationStrategy.SerialColumn
591+
});
592+
593+
Assert.Equal(@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" TYPE bigint;" + EOL +
594+
@"ALTER TABLE ""People"" ALTER COLUMN ""Id"" SET NOT NULL;" + EOL,
572595
Sql);
573596
}
574597

0 commit comments

Comments
 (0)