Skip to content

Commit decfbca

Browse files
Ja bist du narrischJa bist du narrisch
authored andcommitted
Added integrity violation tests.
1 parent df90f1c commit decfbca

File tree

3 files changed

+152
-21
lines changed

3 files changed

+152
-21
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#region License
2+
3+
//The contents of this file are subject to the Mozilla Public License
4+
//Version 1.1 (the "License"); you may not use this file except in
5+
//compliance with the License. You may obtain a copy of the License at
6+
//http://www.mozilla.org/MPL/
7+
//Software distributed under the License is distributed on an "AS IS"
8+
//basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
9+
//License for the specific language governing rights and limitations
10+
//under the License.
11+
12+
#endregion
13+
14+
using System.Linq;
15+
using DotNetProjects.Migrator.Framework;
16+
using DotNetProjects.Migrator.Providers.Impl.SQLite;
17+
using Migrator.Providers.SQLite;
18+
using Migrator.Tests.Settings;
19+
using NUnit.Framework;
20+
21+
namespace Migrator.Tests.Providers;
22+
23+
[TestFixture]
24+
[Category("SQLite")]
25+
public class SQLiteTransformationProviderAddForeignKeyTests : TransformationProviderBase
26+
{
27+
[SetUp]
28+
public void SetUp()
29+
{
30+
var configReader = new ConfigurationReader();
31+
var connectionString = configReader.GetDatabaseConnectionConfigById("SQLiteConnectionString")
32+
.ConnectionString;
33+
34+
_provider = new SQLiteTransformationProvider(new SQLiteDialect(), connectionString, "default", null);
35+
_provider.BeginTransaction();
36+
37+
AddDefaultTable();
38+
}
39+
40+
[Test]
41+
public void AddForeignKey()
42+
{
43+
// Arrange
44+
AddTableWithPrimaryKey();
45+
_provider.ExecuteNonQuery("INSERT INTO Test (Id, name) VALUES (1, 'my name')");
46+
_provider.ExecuteNonQuery("INSERT INTO TestTwo (TestId) VALUES (1)");
47+
48+
// Act
49+
_provider.AddForeignKey("FK name is not supported by SQLite", parentTable: "Test", parentColumn: "Id", childTable: "TestTwo", childColumn: "TestId", ForeignKeyConstraintType.Cascade);
50+
51+
// Assert
52+
var foreignKeyConstraints = ((SQLiteTransformationProvider)_provider).GetForeignKeyConstraints("TestTwo");
53+
var tableSQLCreateScript = ((SQLiteTransformationProvider)_provider).GetSqlCreateTableScript("TestTwo");
54+
55+
Assert.That(foreignKeyConstraints.Single().Name, Is.Null);
56+
Assert.That(foreignKeyConstraints.Single().ChildTable, Is.EqualTo("TestTwo"));
57+
Assert.That(foreignKeyConstraints.Single().ParentTable, Is.EqualTo("Test"));
58+
Assert.That(foreignKeyConstraints.Single().ChildColumns.Single(), Is.EqualTo("TestId"));
59+
Assert.That(foreignKeyConstraints.Single().ParentColumns.Single(), Is.EqualTo("Id"));
60+
// Cascade is not supported
61+
62+
Assert.That(tableSQLCreateScript, Does.Contain("CREATE TABLE \"TestTwo\""));
63+
Assert.That(tableSQLCreateScript, Does.Contain(", FOREIGN KEY (TestId) REFERENCES Test(Id))"));
64+
65+
var result = ((SQLiteTransformationProvider)_provider).CheckForeignKeyIntegrity();
66+
Assert.That(result, Is.True);
67+
}
68+
69+
[Test]
70+
public void AddForeignKey_RenameParentColumWithForeignKeyAndData_ForeignKeyPointsToRenamedColumn()
71+
{
72+
// Arrange
73+
AddTableWithPrimaryKey();
74+
_provider.ExecuteNonQuery("INSERT INTO Test (Id, name) VALUES (1, 'my name')");
75+
_provider.ExecuteNonQuery("INSERT INTO TestTwo (TestId) VALUES (1)");
76+
_provider.AddForeignKey("FK name is not supported by SQLite", parentTable: "Test", parentColumn: "Id", childTable: "TestTwo", childColumn: "TestId", ForeignKeyConstraintType.Cascade);
77+
78+
// Act
79+
_provider.RenameColumn("Test", "Id", "IdNew");
80+
81+
// Assert
82+
var foreignKeyConstraints = ((SQLiteTransformationProvider)_provider).GetForeignKeyConstraints("TestTwo");
83+
var tableSQLCreateScript = ((SQLiteTransformationProvider)_provider).GetSqlCreateTableScript("TestTwo");
84+
85+
Assert.That(tableSQLCreateScript, Does.Contain("CREATE TABLE \"TestTwo\""));
86+
Assert.That(tableSQLCreateScript, Does.Contain(", FOREIGN KEY (TestId) REFERENCES Test(Id))"));
87+
88+
var result = ((SQLiteTransformationProvider)_provider).CheckForeignKeyIntegrity();
89+
Assert.That(result, Is.True);
90+
}
91+
}

src/Migrator.Tests/Providers/SQLiteTransformationProviderTest.cs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#endregion
1313

14-
using System.Linq;
1514
using DotNetProjects.Migrator.Framework;
1615
using DotNetProjects.Migrator.Providers.Impl.SQLite;
1716
using Migrator.Providers.SQLite;
@@ -38,29 +37,37 @@ public void SetUp()
3837
}
3938

4039
[Test]
41-
public void AddForeignKey()
40+
public void CheckForeignKeyIntegrity_IntegrityViolated_ReturnsFalse()
4241
{
4342
// Arrange
4443
AddTableWithPrimaryKey();
44+
_provider.ExecuteNonQuery("INSERT INTO Test (Id, name) VALUES (1, 'my name')");
45+
_provider.ExecuteNonQuery("INSERT INTO TestTwo (TestId) VALUES (44444)");
46+
_provider.AddForeignKey("FK name is not supported by SQLite", parentTable: "Test", parentColumn: "Id", childTable: "TestTwo", childColumn: "TestId", ForeignKeyConstraintType.Cascade);
4547

4648
// Act
47-
_provider.AddForeignKey("FK name is not supported by SQLite", parentTable: "Test", parentColumn: "Id", childTable: "TestTwo", childColumn: "TestId", ForeignKeyConstraintType.Cascade);
49+
var result = ((SQLiteTransformationProvider)_provider).CheckForeignKeyIntegrity();
4850

4951
// Assert
50-
var foreignKeyConstraints = ((SQLiteTransformationProvider)_provider).GetForeignKeyConstraints("TestTwo");
51-
var tableSQLCreateScript = ((SQLiteTransformationProvider)_provider).GetSqlCreateTableScript("TestTwo");
52+
Assert.That(result, Is.False);
53+
}
54+
55+
[Test]
56+
public void CheckForeignKeyIntegrity_IntegrityOk_ReturnsTrue()
57+
{
58+
// Arrange
59+
AddTableWithPrimaryKey();
60+
_provider.ExecuteNonQuery("INSERT INTO Test (Id, name) VALUES (1, 'my name')");
61+
_provider.ExecuteNonQuery("INSERT INTO TestTwo (TestId) VALUES (1)");
62+
_provider.AddForeignKey("FK name is not supported by SQLite", parentTable: "Test", parentColumn: "Id", childTable: "TestTwo", childColumn: "TestId", ForeignKeyConstraintType.Cascade);
5263

53-
Assert.That(foreignKeyConstraints.Single().Name, Is.Null);
54-
Assert.That(foreignKeyConstraints.Single().ChildTable, Is.EqualTo("TestTwo"));
55-
Assert.That(foreignKeyConstraints.Single().ParentTable, Is.EqualTo("Test"));
56-
Assert.That(foreignKeyConstraints.Single().ChildColumns.Single(), Is.EqualTo("TestId"));
57-
Assert.That(foreignKeyConstraints.Single().ParentColumns.Single(), Is.EqualTo("Id"));
64+
// Act
65+
var result = ((SQLiteTransformationProvider)_provider).CheckForeignKeyIntegrity();
5866

59-
Assert.That(tableSQLCreateScript, Does.Contain("CREATE TABLE \"TestTwo\""));
60-
Assert.That(tableSQLCreateScript, Does.Contain(", FOREIGN KEY (TestId) REFERENCES Test(Id))"));
67+
// Assert
68+
Assert.That(result, Is.True);
6169
}
6270

63-
6471
[Test]
6572
public void CanParseColumnDefForName()
6673
{

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

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,17 +310,34 @@ public override void RemoveColumn(string table, string column)
310310

311311
public override void RenameColumn(string tableName, string oldColumnName, string newColumnName)
312312
{
313+
// Due to old .Net versions we cannot use ThrowIfNullOrWhitespace
314+
if (string.IsNullOrWhiteSpace(newColumnName))
315+
{
316+
throw new Exception("New column name is null or empty");
317+
}
318+
313319
if (ColumnExists(tableName, newColumnName))
314320
{
315321
throw new MigrationException(string.Format("Table '{0}' has column named '{1}' already", tableName, newColumnName));
316322
}
317323

318324
if (ColumnExists(tableName, oldColumnName))
319325
{
320-
var columnDef = GetColumns(tableName).First(x => x.Name == oldColumnName);
326+
var sqliteTableInfo = GetTableData(tableName);
327+
var columnMapping = sqliteTableInfo.ColumnMappings.First(x => x.OldName == oldColumnName);
328+
columnMapping.NewName = newColumnName;
329+
330+
var column = sqliteTableInfo.Columns.First(x => x.Name == newColumnName);
331+
column.Name = newColumnName;
332+
333+
var affectedForeignKeys = sqliteTableInfo.ForeignKeys.Where(x => x.ChildColumns.Contains(oldColumnName)).ToList();
321334

322-
columnDef.Name = newColumnName;
323-
ChangeColumnInternal(tableName, [oldColumnName], [columnDef]);
335+
foreach (var foreignKey in affectedForeignKeys)
336+
{
337+
foreignKey.ChildColumns = foreignKey.ChildColumns.Select(x => x == oldColumnName ? newColumnName : x).ToArray();
338+
}
339+
340+
RecreateTable(sqliteTableInfo);
324341
}
325342
else
326343
{
@@ -379,18 +396,34 @@ public SQLiteTableInfo GetTableData(string tableName)
379396
return sqliteTable;
380397
}
381398

399+
public bool CheckForeignKeyIntegrity()
400+
{
401+
ExecuteNonQuery("PRAGMA foreign_keys = ON");
402+
403+
using (var cmd = CreateCommand())
404+
using (var reader = ExecuteQuery(cmd, "PRAGMA foreign_key_check"))
405+
{
406+
if (reader.Read())
407+
{
408+
return false;
409+
}
410+
411+
return true;
412+
}
413+
}
414+
382415
private void RecreateTable(SQLiteTableInfo sqliteTableInfo)
383416
{
384417
var sourceTableQuoted = QuoteTableNameIfRequired(sqliteTableInfo.TableNameMapping.OldName);
385418
var targetIntermediateTableQuoted = QuoteTableNameIfRequired($"{sqliteTableInfo.TableNameMapping.NewName}{IntermediateTableSuffix}");
386419
var targetTableQuoted = QuoteTableNameIfRequired($"{sqliteTableInfo.TableNameMapping.NewName}");
387420

388-
var columns = sqliteTableInfo.Columns.Cast<IDbField>();
389-
var foreignKeys = sqliteTableInfo.ForeignKeys.Cast<IDbField>();
390-
var indexes = sqliteTableInfo.Indexes.Cast<IDbField>();
421+
var columnDbFields = sqliteTableInfo.Columns.Cast<IDbField>();
422+
var foreignKeyDbFields = sqliteTableInfo.ForeignKeys.Cast<IDbField>();
423+
var indexDbFields = sqliteTableInfo.Indexes.Cast<IDbField>();
391424

392-
var dbFields = columns.Concat(foreignKeys)
393-
.Concat(indexes)
425+
var dbFields = columnDbFields.Concat(foreignKeyDbFields)
426+
.Concat(indexDbFields)
394427
.ToArray();
395428

396429
AddTable(targetIntermediateTableQuoted, null, dbFields);

0 commit comments

Comments
 (0)