Skip to content

Commit

Permalink
Don't generate DEFAULT 0 clause for AUTO_INCREMENT columns. (#1980)
Browse files Browse the repository at this point in the history
  • Loading branch information
lauxjpn authored Mar 3, 2025
1 parent b61cbbd commit 23db204
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/EFCore.MySql/Migrations/MySqlMigrationsSqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,8 @@ protected override void ColumnDefinition(

if (operation.ComputedColumnSql == null)
{
ColumnDefinitionWithCharSet(schema, table, name, operation, model, builder);
// AUTO_INCREMENT columns don't support DEFAULT values.
ColumnDefinitionWithCharSet(schema, table, name, operation, model, builder, withDefaultValue: !autoIncrement);

GenerateComment(operation.Comment, builder);

Expand Down Expand Up @@ -1305,7 +1306,14 @@ private void GenerateComment(string comment, MigrationCommandListBuilder builder
.Append(MySqlStringTypeMapping.EscapeSqlLiteralWithLineBreaks(comment, !_options.NoBackslashEscapes, false));
}

private void ColumnDefinitionWithCharSet(string schema, string table, string name, ColumnOperation operation, IModel model, MigrationCommandListBuilder builder)
private void ColumnDefinitionWithCharSet(
string schema,
string table,
string name,
ColumnOperation operation,
IModel model,
MigrationCommandListBuilder builder,
bool withDefaultValue)
{
if (operation.ComputedColumnSql != null)
{
Expand All @@ -1322,7 +1330,10 @@ private void ColumnDefinitionWithCharSet(string schema, string table, string nam

builder.Append(operation.IsNullable ? " NULL" : " NOT NULL");

DefaultValue(operation.DefaultValue, operation.DefaultValueSql, columnType, builder);
if (withDefaultValue)
{
DefaultValue(operation.DefaultValue, operation.DefaultValueSql, columnType, builder);
}

var srid = operation[MySqlAnnotationNames.SpatialReferenceSystemId];
if (srid is int &&
Expand Down
205 changes: 205 additions & 0 deletions test/EFCore.MySql.FunctionalTests/FullMigrationsMySqlTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -362,6 +363,133 @@ IF NOT EXISTS(SELECT 1 FROM `__EFMigrationsHistory` WHERE `MigrationId` = '00000
DROP PROCEDURE `POMELO_AFTER_ADD_PRIMARY_KEY`;
""",
Sql,
ignoreLineEndingDifferences: true);
}

[ConditionalFact]
public virtual void Alter_column_change_primary_key_will_not_try_to_declare_default_value_in_sql()
{
using var db = Fixture.CreateContext<FullInfrastructureMigrationsFixture.MigrationPrimaryKeyChangeFromStringToIntContext>(
new ServiceCollection()
.AddScoped<IMigrator, MySqlTestMigrator>());

db.Database.EnsureDeleted();
db.Database.EnsureCreated();

var migrator = (MySqlTestMigrator)db.GetService<IMigrator>();
migrator.MigrationsSqlGenerationOptionsOverrider = options => options & ~MigrationsSqlGenerationOptions.Script;

SetSql(migrator.GenerateScript());

Assert.False(Sql.Contains("DEFAULT 0"));
Assert.Equal(
"""
CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
`MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
`ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
) CHARACTER SET=utf8mb4;
START TRANSACTION;
CREATE TABLE `IceCreams` (
`Name` varchar(32) NOT NULL,
CONSTRAINT `PK_IceCreams` PRIMARY KEY (`Name`)
);
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
VALUES ('00000000000001_Migration1', '7.0.0-test');
DROP PROCEDURE IF EXISTS `POMELO_BEFORE_DROP_PRIMARY_KEY`;
CREATE PROCEDURE `POMELO_BEFORE_DROP_PRIMARY_KEY`(IN `SCHEMA_NAME_ARGUMENT` VARCHAR(255), IN `TABLE_NAME_ARGUMENT` VARCHAR(255))
BEGIN
DECLARE HAS_AUTO_INCREMENT_ID TINYINT(1);
DECLARE PRIMARY_KEY_COLUMN_NAME VARCHAR(255);
DECLARE PRIMARY_KEY_TYPE VARCHAR(255);
DECLARE SQL_EXP VARCHAR(1000);
SELECT COUNT(*)
INTO HAS_AUTO_INCREMENT_ID
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `Extra` = 'auto_increment'
AND `COLUMN_KEY` = 'PRI'
LIMIT 1;
IF HAS_AUTO_INCREMENT_ID THEN
SELECT `COLUMN_TYPE`
INTO PRIMARY_KEY_TYPE
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `COLUMN_KEY` = 'PRI'
LIMIT 1;
SELECT `COLUMN_NAME`
INTO PRIMARY_KEY_COLUMN_NAME
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `COLUMN_KEY` = 'PRI'
LIMIT 1;
SET SQL_EXP = CONCAT('ALTER TABLE `', (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA())), '`.`', TABLE_NAME_ARGUMENT, '` MODIFY COLUMN `', PRIMARY_KEY_COLUMN_NAME, '` ', PRIMARY_KEY_TYPE, ' NOT NULL;');
SET @SQL_EXP = SQL_EXP;
PREPARE SQL_EXP_EXECUTE FROM @SQL_EXP;
EXECUTE SQL_EXP_EXECUTE;
DEALLOCATE PREPARE SQL_EXP_EXECUTE;
END IF;
END;
DROP PROCEDURE IF EXISTS `POMELO_AFTER_ADD_PRIMARY_KEY`;
CREATE PROCEDURE `POMELO_AFTER_ADD_PRIMARY_KEY`(IN `SCHEMA_NAME_ARGUMENT` VARCHAR(255), IN `TABLE_NAME_ARGUMENT` VARCHAR(255), IN `COLUMN_NAME_ARGUMENT` VARCHAR(255))
BEGIN
DECLARE HAS_AUTO_INCREMENT_ID INT(11);
DECLARE PRIMARY_KEY_COLUMN_NAME VARCHAR(255);
DECLARE PRIMARY_KEY_TYPE VARCHAR(255);
DECLARE SQL_EXP VARCHAR(1000);
SELECT COUNT(*)
INTO HAS_AUTO_INCREMENT_ID
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `COLUMN_NAME` = COLUMN_NAME_ARGUMENT
AND `COLUMN_TYPE` LIKE '%int%'
AND `COLUMN_KEY` = 'PRI';
IF HAS_AUTO_INCREMENT_ID THEN
SELECT `COLUMN_TYPE`
INTO PRIMARY_KEY_TYPE
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `COLUMN_NAME` = COLUMN_NAME_ARGUMENT
AND `COLUMN_TYPE` LIKE '%int%'
AND `COLUMN_KEY` = 'PRI';
SELECT `COLUMN_NAME`
INTO PRIMARY_KEY_COLUMN_NAME
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA()))
AND `TABLE_NAME` = TABLE_NAME_ARGUMENT
AND `COLUMN_NAME` = COLUMN_NAME_ARGUMENT
AND `COLUMN_TYPE` LIKE '%int%'
AND `COLUMN_KEY` = 'PRI';
SET SQL_EXP = CONCAT('ALTER TABLE `', (SELECT IFNULL(SCHEMA_NAME_ARGUMENT, SCHEMA())), '`.`', TABLE_NAME_ARGUMENT, '` MODIFY COLUMN `', PRIMARY_KEY_COLUMN_NAME, '` ', PRIMARY_KEY_TYPE, ' NOT NULL AUTO_INCREMENT;');
SET @SQL_EXP = SQL_EXP;
PREPARE SQL_EXP_EXECUTE FROM @SQL_EXP;
EXECUTE SQL_EXP_EXECUTE;
DEALLOCATE PREPARE SQL_EXP_EXECUTE;
END IF;
END;
CALL POMELO_BEFORE_DROP_PRIMARY_KEY(NULL, 'IceCreams');
ALTER TABLE `IceCreams` DROP PRIMARY KEY;
ALTER TABLE `IceCreams` ADD `IceCreamId` int NOT NULL AUTO_INCREMENT;
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
VALUES ('00000000000002_Migration2', '7.0.0-test');
DROP PROCEDURE `POMELO_BEFORE_DROP_PRIMARY_KEY`;
DROP PROCEDURE `POMELO_AFTER_ADD_PRIMARY_KEY`;
COMMIT;
""",
Sql,
ignoreLineEndingDifferences: true);
Expand Down Expand Up @@ -649,6 +777,83 @@ protected override void Down(MigrationBuilder migrationBuilder)

#endregion MigrationPrimaryKeyChange

public class MigrationPrimaryKeyChangeFromStringToIntContext : DbContext
{
public MigrationPrimaryKeyChangeFromStringToIntContext(DbContextOptions options)
: base(options)
{
}

public static class Migrations
{
[DbContext(typeof(MigrationPrimaryKeyChangeFromStringToIntContext))]
[Migration("00000000000001_Migration1")]
private class Migration1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
MigrationsInfrastructureFixtureBase.ActiveProvider = migrationBuilder.ActiveProvider;

migrationBuilder
.CreateTable(
name: "IceCreams",
columns: table => new
{
Name = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IceCreams", x => x.Name);
});
}

protected override void Down(MigrationBuilder migrationBuilder)
=> migrationBuilder.DropTable("IceCreams");
}

[DbContext(typeof(MigrationPrimaryKeyChangeFromStringToIntContext))]
[Migration("00000000000002_Migration2")]
private class Migration2 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_IceCreams",
table: "IceCreams");

migrationBuilder.AddColumn<int>(
name: "IceCreamId",
table: "IceCreams",
type: "int",
nullable: false,
defaultValue: 0)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);

migrationBuilder.AddPrimaryKey(
name: "PK_IceCreams",
table: "IceCreams",
column: "IceCreamId");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_IceCreams",
table: "IceCreams");

migrationBuilder.DropColumn(
name: "IceCreamId",
table: "IceCreams");

migrationBuilder.AddPrimaryKey(
name: "PK_IceCreams",
table: "IceCreams",
column: "Name");
}
}
}
}

#region MigrationDropPrimaryKeyWithRecreatingForeignKeys

public class MigrationDropPrimaryKeyWithRecreatingForeignKeysContext : PoolableDbContext
Expand Down

0 comments on commit 23db204

Please sign in to comment.