Skip to content

Commit 3c75c4e

Browse files
Ja bist du narrischJa bist du narrisch
authored andcommitted
Match FK constraint extract data with pragma FK data
1 parent ed2593c commit 3c75c4e

File tree

2 files changed

+55
-41
lines changed

2 files changed

+55
-41
lines changed

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

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System.Data;
22
using System.Linq;
3-
using DotNetProjects.Migrator.Framework;
4-
using DotNetProjects.Migrator.Providers.Impl.SQLite;
53
using Migrator.Framework;
64
using Migrator.Tests.Providers.SQLite.Base;
75
using NUnit.Framework;
@@ -48,40 +46,11 @@ public void RenameColumn_HavingASingleForeignKeyPointingToTheTargetColumn_Single
4846
// Act
4947
var foreignKeyConstraints = Provider.GetForeignKeyConstraints(child);
5048

51-
// var tableInfoLevel2Before = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel2);
52-
// var tableInfoLevel3Before = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel3);
49+
// Assert
50+
Assert.That(foreignKeyConstraints.Single(x => x.Name == foreignKeyStringA).ChildColumns, Is.EqualTo([childColumnFKToParentAProperty1]));
51+
Assert.That(foreignKeyConstraints.Single(x => x.Name == foreignKeyStringA).ParentColumns, Is.EqualTo([parentAProperty1]));
5352

54-
// Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel1} ({propertyId}) VALUES (1)");
55-
// Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel1} ({propertyId}) VALUES (2)");
56-
// Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel2} ({propertyId}, {propertyLevel1Id}) VALUES (1, 1)");
57-
// Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel3} ({propertyId}, {propertyLevel2Id}) VALUES (1, 1)");
58-
59-
// // Act
60-
// Provider.RenameColumn(tableNameLevel2, propertyId, propertyIdRenamed);
61-
// Provider.RenameColumn(tableNameLevel2, propertyLevel1Id, propertyLevel1IdRenamed);
62-
63-
// // Assert
64-
// Provider.ExecuteNonQuery($"INSERT INTO {tableNameLevel2} ({propertyIdRenamed}, {propertyLevel1IdRenamed}) VALUES (2,2)");
65-
// using var command = Provider.GetCommand();
66-
67-
// using var reader = Provider.ExecuteQuery(command, $"SELECT COUNT(*) as Count from {tableNameLevel2}");
68-
// reader.Read();
69-
// var count = reader.GetInt32(reader.GetOrdinal("Count"));
70-
// Assert.That(count, Is.EqualTo(2));
71-
72-
// var tableInfoLevel2After = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableNameLevel2);
73-
74-
// Assert.That(tableInfoLevel2Before.Columns.Single(x => x.Name == propertyId).ColumnProperty.HasFlag(ColumnProperty.PrimaryKey), Is.True);
75-
// Assert.That(tableInfoLevel2Before.Columns.Single(x => x.Name == propertyLevel1Id).ColumnProperty.HasFlag(ColumnProperty.Unique), Is.True);
76-
// Assert.That(tableInfoLevel2Before.ForeignKeys.Single().ChildColumns.Single(), Is.EqualTo(propertyLevel1Id));
77-
78-
// Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyId), Is.Null);
79-
// Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyLevel1Id), Is.Null);
80-
// Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyIdRenamed), Is.Not.Null);
81-
// Assert.That(tableInfoLevel2After.Columns.FirstOrDefault(x => x.Name == propertyLevel1IdRenamed), Is.Not.Null);
82-
// Assert.That(tableInfoLevel2After.ForeignKeys.Single().ChildColumns.Single(), Is.EqualTo(propertyLevel1IdRenamed));
83-
84-
// var valid = ((SQLiteTransformationProvider)Provider).CheckForeignKeyIntegrity();
85-
// Assert.That(valid, Is.True);
53+
Assert.That(foreignKeyConstraints.Single(x => x.Name == foreignKeyStringB).ChildColumns, Is.EqualTo([childColumnFKToParentBProperty1, childColumnFKToParentBProperty2]));
54+
Assert.That(foreignKeyConstraints.Single(x => x.Name == foreignKeyStringB).ParentColumns, Is.EqualTo([parentBProperty1, parentBProperty2]));
8655
}
8756
}

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

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,22 +118,65 @@ public override ForeignKeyConstraint[] GetForeignKeyConstraints(string tableName
118118
foreignKeyConstraints.Add(foreignKeyConstraint);
119119
}
120120

121+
if (foreignKeyConstraints.Count == 0)
122+
{
123+
return [];
124+
}
125+
121126
var createTableScript = GetSqlCreateTableScript(tableName);
122127
var regEx = ForeignKeyRegex();
123128
var matchesCollection = regEx.Matches(createTableScript);
124-
var matches = matchesCollection.Cast<Match>().ToList().Where(x => x.Success).Select(x => x.Value).ToList();
129+
var fkParts = matchesCollection.Cast<Match>().ToList().Where(x => x.Success).Select(x => x.Value).ToList();
125130

126-
if (matches.Count != foreignKeyConstraints.Count)
131+
if (fkParts.Count != foreignKeyConstraints.Count)
127132
{
128-
throw new Exception($"Cannot extract all foreign keys out of the create table script in SQLite. Did you use a name as foreign key constraint for all constraints in table {tableName}?");
133+
throw new Exception($"Cannot extract all foreign keys out of the create table script in SQLite. Did you use a name as foreign key constraint for all constraints in table '{tableName}' in this or older migrations?");
129134
}
130135

131-
foreach (var foreignKeyConstraint in foreignKeyConstraints)
136+
List<ForeignKeyExtract> foreignKeyExtracts = [];
137+
138+
foreach (var fkPart in fkParts)
132139
{
133140
var regexParenthesis = ForeignKeyParenthesisRegex();
134-
regexParenthesis.Matches()
141+
var parenthesisContents = regexParenthesis.Matches(fkPart).Cast<Match>().Select(x => x.Groups[1].Value).ToList();
142+
143+
if (parenthesisContents.Count != 2)
144+
{
145+
throw new Exception("Cannot extract parenthesis of foreign key constraint");
146+
}
147+
148+
var foreignKeyExtract = new ForeignKeyExtract()
149+
{
150+
ChildColumnNames = parenthesisContents[0].Split(",").Select(x => x.Trim()).ToList(),
151+
ParentColumnNames = parenthesisContents[1].Split(",").Select(x => x.Trim()).ToList(),
152+
};
153+
154+
var foreignKeyConstraintNameRegex = ForeignKeyConstraintNameRegex();
155+
var foreignKeyNameMatch = foreignKeyConstraintNameRegex.Match(fkPart);
156+
157+
if (!foreignKeyNameMatch.Success)
158+
{
159+
throw new Exception("Could not extract the foreign key constraint name");
160+
}
161+
162+
foreignKeyExtract.ForeignKeyName = foreignKeyNameMatch.Groups[1].Value;
163+
164+
foreignKeyExtracts.Add(foreignKeyExtract);
135165
}
136166

167+
foreach (var foreignKeyConstraint in foreignKeyConstraints)
168+
{
169+
foreach (var foreignKeyExtract in foreignKeyExtracts)
170+
{
171+
if (
172+
foreignKeyExtract.ChildColumnNames.SequenceEqual(foreignKeyConstraint.ChildColumns) &&
173+
foreignKeyExtract.ParentColumnNames.SequenceEqual(foreignKeyConstraint.ParentColumns)
174+
)
175+
{
176+
foreignKeyConstraint.Name = foreignKeyExtract.ForeignKeyName;
177+
}
178+
}
179+
}
137180

138181
return foreignKeyConstraints.ToArray();
139182
}
@@ -1259,5 +1302,7 @@ protected override void ConfigureParameterWithValue(IDbDataParameter parameter,
12591302
private static partial Regex ForeignKeyRegex();
12601303
[GeneratedRegex(@"\(([^)]+)\)")]
12611304
private static partial Regex ForeignKeyParenthesisRegex();
1305+
[GeneratedRegex(@"CONSTRAINT\s+(\w+)\s+FOREIGN\s+KEY")]
1306+
private static partial Regex ForeignKeyConstraintNameRegex();
12621307
}
12631308
}

0 commit comments

Comments
 (0)