Skip to content

Commit c044f4d

Browse files
Ja bist du narrischJa bist du narrisch
authored andcommitted
Foreign key adjustments
1 parent 6bf800f commit c044f4d

File tree

2 files changed

+78
-13
lines changed

2 files changed

+78
-13
lines changed

src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_RemoveColumnTests.cs

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,44 +63,44 @@ public void RemoveColumn_HavingNoCompositeIndexAndNoCompositeUniqueConstraint_Su
6363
public void RemoveColumn_HavingASingleForeignKeyPointingToTheTargetColumn_SingleColumnForeignKeyIsRemoved()
6464
{
6565
// Arrange
66-
const string testTableName = "Color";
66+
const string parentTableName = "Parent";
6767
const string propertyName1 = "Id";
6868
const string propertyName2 = "OtherProperty";
69-
const string childTestTableName = "ChildTable";
69+
const string childTestTableName = "Child";
7070
const string childTestTableName2 = "ChildTable2";
7171
const string propertyChildTableName1 = "ColorId";
7272

73-
Provider.AddTable(testTableName,
73+
Provider.AddTable(parentTableName,
7474
new Column(propertyName1, DbType.Int32, ColumnProperty.PrimaryKey),
7575
new Column(propertyName2, DbType.Int32, ColumnProperty.Unique)
7676
);
7777

7878
Provider.AddTable(childTestTableName, new Column(propertyChildTableName1, DbType.Int32));
79-
Provider.AddForeignKey("Not used in SQLite", childTestTableName, propertyChildTableName1, testTableName, propertyName1);
79+
Provider.AddForeignKey("Not used in SQLite", childTestTableName, propertyChildTableName1, parentTableName, propertyName1);
8080
var script = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(childTestTableName);
8181

8282
Provider.AddTable(childTestTableName2, new Column(propertyChildTableName1, DbType.Int32));
83-
Provider.AddForeignKey(name: "Not used in SQLite", childTable: childTestTableName2, childColumn: propertyChildTableName1, parentTable: testTableName, parentColumn: propertyName2);
83+
Provider.AddForeignKey(name: "Not used in SQLite", childTable: childTestTableName2, childColumn: propertyChildTableName1, parentTable: parentTableName, parentColumn: propertyName2);
8484

85-
var tableInfoBefore = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(testTableName);
85+
var tableInfoBefore = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(parentTableName);
8686
var tableInfoChildBefore = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(childTestTableName);
8787

88-
Provider.ExecuteNonQuery($"INSERT INTO {testTableName} ({propertyName1}, {propertyName2}) VALUES (1, 2)");
88+
Provider.ExecuteNonQuery($"INSERT INTO {parentTableName} ({propertyName1}, {propertyName2}) VALUES (1, 2)");
8989
Provider.ExecuteNonQuery($"INSERT INTO {childTestTableName} ({propertyChildTableName1}) VALUES (1)");
9090
Provider.ExecuteNonQuery($"INSERT INTO {childTestTableName2} ({propertyChildTableName1}) VALUES (2)");
9191

9292
// Act
93-
Provider.RemoveColumn(testTableName, propertyName1);
93+
Provider.RemoveColumn(parentTableName, propertyName1);
9494

9595
// Assert
96-
Provider.ExecuteNonQuery($"INSERT INTO {testTableName} ({propertyName2}) VALUES (3)");
96+
Provider.ExecuteNonQuery($"INSERT INTO {parentTableName} ({propertyName2}) VALUES (3)");
9797
using var command = Provider.GetCommand();
98-
using var reader = Provider.ExecuteQuery(command, $"SELECT COUNT(*) as Count from {testTableName}");
98+
using var reader = Provider.ExecuteQuery(command, $"SELECT COUNT(*) as Count from {parentTableName}");
9999
reader.Read();
100100
var count = reader.GetInt32(reader.GetOrdinal("Count"));
101101
Assert.That(count, Is.EqualTo(2));
102102

103-
var tableInfoAfter = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(testTableName);
103+
var tableInfoAfter = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(parentTableName);
104104

105105
Assert.That(tableInfoBefore.Columns.Single(x => x.Name == propertyName1).ColumnProperty.HasFlag(ColumnProperty.PrimaryKey), Is.True);
106106
Assert.That(tableInfoBefore.Columns.Single(x => x.Name == propertyName2).ColumnProperty.HasFlag(ColumnProperty.Unique), Is.True);
@@ -201,4 +201,68 @@ public void RemoveColumn_HavingMultipleSingleUniques_Succeeds()
201201
Assert.That(tableInfoBefore.Uniques.Count, Is.EqualTo(2));
202202
Assert.That(tableInfoAfter.Uniques.Count, Is.EqualTo(1));
203203
}
204+
205+
[Test]
206+
public void RemoveColumn_HavingAForeignKeyPointingFromTableToParentAndForeignKeyPointingToTable_SingleColumnForeignKeyIsRemoved()
207+
{
208+
// Arrange
209+
const string tableNameLevel1 = "Level1";
210+
const string tableNameLevel2 = "Level2";
211+
const string tableNameLevel3 = "Level3";
212+
const string propertyId = "Id";
213+
const string propertyLevel1Id = "Level1Id";
214+
const string propertyLevel2Id = "Level2Id";
215+
216+
Provider.AddTable(tableNameLevel1, new Column(propertyId, DbType.Int32, ColumnProperty.PrimaryKey));
217+
218+
Provider.AddTable(tableNameLevel2,
219+
new Column(propertyId, DbType.Int32, ColumnProperty.PrimaryKey),
220+
new Column(propertyLevel1Id, DbType.Int32, ColumnProperty.Unique)
221+
);
222+
223+
Provider.AddTable(tableNameLevel3,
224+
new Column(propertyId, DbType.Int32, ColumnProperty.PrimaryKey),
225+
new Column(propertyLevel2Id, DbType.Int32)
226+
);
227+
228+
Provider.AddForeignKey("Level2ToLevel1", tableNameLevel2, propertyLevel1Id, tableNameLevel1, propertyId);
229+
Provider.AddForeignKey("Level3ToLevel2", tableNameLevel3, propertyLevel2Id, tableNameLevel2, propertyId);
230+
231+
var script = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(tableNameLevel2);
232+
233+
var tableInfoLevel2Before = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel2);
234+
var tableInfoLevel3Before = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel3);
235+
236+
Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel1} ({propertyId}) VALUES (1)");
237+
Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel1} ({propertyId}) VALUES (2)");
238+
Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel2} ({propertyId}, {propertyLevel1Id}) VALUES (1, 1)");
239+
Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel3} ({propertyId}, {propertyLevel2Id}) VALUES (1, 1)");
240+
241+
// Act
242+
Provider.RemoveColumn(tableNameLevel2, propertyLevel1Id);
243+
244+
// Assert
245+
Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel2} ({propertyId}) VALUES (2)");
246+
using var command = Provider.GetCommand();
247+
248+
using var reader = Provider.ExecuteQuery(command, $"SELECT COUNT(*) as Count from {tableNameLevel2}");
249+
reader.Read();
250+
var count = reader.GetInt32(reader.GetOrdinal("Count"));
251+
Assert.That(count, Is.EqualTo(2));
252+
253+
var tableInfoLevel2After = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel2);
254+
255+
Assert.That(tableInfoLevel2Before.Columns.Single(x => x.Name == propertyId).ColumnProperty.HasFlag(ColumnProperty.PrimaryKey), Is.True);
256+
Assert.That(tableInfoLevel2Before.Columns.Single(x => x.Name == propertyLevel1Id).ColumnProperty.HasFlag(ColumnProperty.Unique), Is.True);
257+
Assert.That(tableInfoLevel2Before.ForeignKeys.Single().ChildColumns.Single(), Is.EqualTo(propertyLevel1Id));
258+
259+
Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyId), Is.Not.Null);
260+
Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyLevel1Id), Is.Null);
261+
Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyId), Is.Not.Null);
262+
Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyLevel1Id), Is.Null);
263+
Assert.That(tableInfoLevel2After.ForeignKeys, Is.Empty);
264+
265+
var valid = ((SQLiteTransformationProvider)Provider).CheckForeignKeyIntegrity();
266+
Assert.That(valid, Is.True);
267+
}
204268
}

src/Migrator/Providers/Impl/SQLite/SQLiteTransformationProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,11 @@ public override void RemoveColumn(string tableName, string column)
414414
}
415415
}
416416

417-
sqliteInfoMainTable.Uniques.RemoveAll(x => x.KeyColumns.Length == 1 && x.KeyColumns[0] == column);
417+
sqliteInfoMainTable.Uniques.RemoveAll(x => x.KeyColumns.Length == 1 && x.KeyColumns[0].Equals(column, StringComparison.OrdinalIgnoreCase));
418418
sqliteInfoMainTable.ColumnMappings.RemoveAll(x => x.OldName.Equals(column, StringComparison.OrdinalIgnoreCase));
419419
sqliteInfoMainTable.Columns.RemoveAll(x => x.Name.Equals(column, StringComparison.OrdinalIgnoreCase));
420-
sqliteInfoMainTable.Indexes.RemoveAll(x => x.KeyColumns.Length == 1 && x.KeyColumns[0] == column);
420+
sqliteInfoMainTable.Indexes.RemoveAll(x => x.KeyColumns.Length == 1 && x.KeyColumns[0].Equals(column, StringComparison.OrdinalIgnoreCase));
421+
sqliteInfoMainTable.ForeignKeys.RemoveAll(x => x.ChildColumns.Length == 1 && x.ChildColumns[0].Equals(column, StringComparison.OrdinalIgnoreCase));
421422

422423
RecreateTable(sqliteInfoMainTable);
423424
}

0 commit comments

Comments
 (0)