88using System . Globalization ;
99using System . Linq ;
1010using System . Text ;
11+ using System . Text . RegularExpressions ;
1112using ForeignKeyConstraint = DotNetProjects . Migrator . Framework . ForeignKeyConstraint ;
1213using Index = Migrator . Framework . Index ;
1314
@@ -16,7 +17,7 @@ namespace DotNetProjects.Migrator.Providers.Impl.SQLite
1617 /// <summary>
1718 /// Summary description for SQLiteTransformationProvider.
1819 /// </summary>
19- public class SQLiteTransformationProvider : TransformationProvider
20+ public partial class SQLiteTransformationProvider : TransformationProvider
2021 {
2122 private const string IntermediateTableSuffix = "Temp" ;
2223
@@ -59,7 +60,7 @@ public override void AddForeignKey(
5960 // SQLite does not support FK names
6061 ChildColumns = childColumns ,
6162 ChildTable = childTable ,
62- Name = null ,
63+ Name = name ,
6364 ParentColumns = parentColumns ,
6465 ParentTable = parentTable ,
6566 } ;
@@ -117,6 +118,23 @@ public override ForeignKeyConstraint[] GetForeignKeyConstraints(string tableName
117118 foreignKeyConstraints . Add ( foreignKeyConstraint ) ;
118119 }
119120
121+ var createTableScript = GetSqlCreateTableScript ( tableName ) ;
122+ var regEx = ForeignKeyRegex ( ) ;
123+ var matchesCollection = regEx . Matches ( createTableScript ) ;
124+ var matches = matchesCollection . Cast < Match > ( ) . ToList ( ) . Where ( x => x . Success ) . Select ( x => x . Value ) . ToList ( ) ;
125+
126+ if ( matches . Count != foreignKeyConstraints . Count )
127+ {
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 } ?") ;
129+ }
130+
131+ foreach ( var foreignKeyConstraint in foreignKeyConstraints )
132+ {
133+ var regexParenthesis = ForeignKeyParenthesisRegex ( ) ;
134+ regexParenthesis . Matches ( )
135+ }
136+
137+
120138 return foreignKeyConstraints . ToArray ( ) ;
121139 }
122140
@@ -749,7 +767,7 @@ public override bool ViewExists(string view)
749767
750768 public override List < string > GetDatabases ( )
751769 {
752- throw new NotImplementedException ( ) ;
770+ throw new NotSupportedException ( "SQLite is a file-based database. You cannot list other databases." ) ;
753771 }
754772
755773 public override bool ConstraintExists ( string table , string name )
@@ -995,34 +1013,40 @@ public override void AddTable(string name, string engine, params IDbField[] fiel
9951013
9961014 foreach ( var u in uniques )
9971015 {
998- // var nm = "";
1016+ if ( ! string . IsNullOrEmpty ( u . Name ) )
1017+ {
1018+ stringBuilder . Append ( $ " CONSTRAINT { u . Name } ") ;
1019+ }
9991020
1000- // if (!string.IsNullOrEmpty(u.Name))
1001- // {
1002- // nm = string.Format(" CONSTRAINT {0}", u.Name);
1003- // }
10041021 var uniqueColumnsCommaSeparated = string . Join ( ", " , u . KeyColumns ) ;
10051022 stringBuilder . Append ( $ ", UNIQUE ({ uniqueColumnsCommaSeparated } )") ;
10061023 }
10071024
10081025 var foreignKeys = fields . Where ( x => x is ForeignKeyConstraint ) . Cast < ForeignKeyConstraint > ( ) . ToArray ( ) ;
10091026
1027+ List < string > foreignKeyStrings = [ ] ;
1028+
10101029 foreach ( var fk in foreignKeys )
10111030 {
1012- // Since in SQLite the foreign key name can be given as
1013- // CONSTRAINT <FK name>
1014- // but not being stored in any way hence not being retrievable using foreign_key_list
1015- // we leave it out in the following string.
1016-
10171031 var sourceColumnNamesQuotedString = string . Join ( ", " , fk . ChildColumns . Select ( QuoteColumnNameIfRequired ) ) ;
10181032 var parentColumnNamesQuotedString = string . Join ( ", " , fk . ParentColumns . Select ( QuoteColumnNameIfRequired ) ) ;
10191033 var parentTableNameQuoted = QuoteTableNameIfRequired ( fk . ParentTable ) ;
10201034
1021- var foreignKeyString = $ ", FOREIGN KEY ({ sourceColumnNamesQuotedString } ) REFERENCES { parentTableNameQuoted } ({ parentColumnNamesQuotedString } )";
1035+ if ( string . IsNullOrWhiteSpace ( fk . Name ) )
1036+ {
1037+ throw new Exception ( "No foreign key constraint name given" ) ;
1038+ }
1039+
1040+ foreignKeyStrings . Add ( $ "CONSTRAINT { fk . Name } FOREIGN KEY ({ sourceColumnNamesQuotedString } ) REFERENCES { parentTableNameQuoted } ({ parentColumnNamesQuotedString } )") ;
1041+ }
10221042
1023- stringBuilder . Append ( foreignKeyString ) ;
1043+ if ( foreignKeyStrings . Count != 0 )
1044+ {
1045+ stringBuilder . Append ( ", " ) ;
1046+ stringBuilder . Append ( string . Join ( ", " , foreignKeyStrings ) ) ;
10241047 }
10251048
1049+
10261050 stringBuilder . Append ( ")" ) ;
10271051
10281052 ExecuteNonQuery ( stringBuilder . ToString ( ) ) ;
@@ -1230,5 +1254,10 @@ protected override void ConfigureParameterWithValue(IDbDataParameter parameter,
12301254 base . ConfigureParameterWithValue ( parameter , index , value ) ;
12311255 }
12321256 }
1257+
1258+ [ GeneratedRegex ( @"CONSTRAINT\s+\w+\s+FOREIGN\s+KEY\s*\([^)]+\)\s+REFERENCES\s+\w+\s*\([^)]+\)" ) ]
1259+ private static partial Regex ForeignKeyRegex ( ) ;
1260+ [ GeneratedRegex ( @"\(([^)]+)\)" ) ]
1261+ private static partial Regex ForeignKeyParenthesisRegex ( ) ;
12331262 }
12341263}
0 commit comments