using System.Collections.Generic; using System.Data.OleDb; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace DbMigrate { public class SqlDatabase { public string ConnectionString { get; set; } public string SqlScript { get; set; } public List Tables { get; set; } = new List(); public SqlDatabase() { } public void Connect(string connectionString) { ConnectionString = connectionString; } public void LoadSql(string sql) { SqlScript = sql; Tables = ParseTablesFromSql(sql).ToList(); } public void LoadSqlFromFile(string fileName) { if (!File.Exists(fileName)) { throw new FileNotFoundException("SQL file '" + fileName + "' was not found and could not be loaded."); } string sql = File.ReadAllText(fileName); LoadSql(sql); } public IEnumerable ParseTablesFromSql(string sql) { SqlTable table = null; StringBuilder sb = new StringBuilder(); foreach (string line in Regex.Split(sql, "\\r\\n")) { if (string.IsNullOrEmpty(line) || line.StartsWith("--")) { continue; } if (line.ToUpper().StartsWith("CREATE TABLE ")) { if (table != null) { table.ParseSql(sb.ToString()); yield return table; } // Start a new table table = new SqlTable(); sb = new StringBuilder(); sb.AppendLine(line); continue; } sb.AppendLine(line); } table.ParseSql(sb.ToString()); yield return table; } public async Task BuildSql(string dbConnectionString, bool includeIfNotExist = false) { using (OleDbConnection cn = new OleDbConnection(dbConnectionString)) { string sql = ""; //List TableSql = new List(); IEnumerable TableDefs = await cn.QueryAsync("select * from sqlite_master"); foreach (SqliteTableDefinition table in TableDefs.Where(f => f.type == "table").OrderBy(f => f.tbl_name)) { if (table.tbl_name == "sqlite_sequence") { continue; } Match m = Regex.Match(table.sql, "CREATE TABLE \\S+ \\((.*)\\)", RegexOptions.Singleline); if (!m.Success) { Trace.TraceWarning("Unable to match regex on table " + table.name); continue; } int startIndex = m.Groups[1].Index; int length = m.Groups[1].Length; string columns = Regex.Replace(m.Groups[1].Value, "\\s{2,}", " "); columns = Regex.Replace(columns.Replace(", ", ",").Replace(",\n", ","), ",(?!\\d+\\))", ",\r\n\t"); sql += "-- BEGIN TABLE " + table.tbl_name + " --\r\n"; sql += table.sql.Substring(0, startIndex) + "\r\n\t" + columns.Trim() + "\r\n" + table.sql.Substring(startIndex + length) + ";\r\n"; List indexes = TableDefs.Where(f => f.type == "index" && f.tbl_name == table.tbl_name && !string.IsNullOrEmpty(f.sql)).ToList(); if (indexes.Count > 0) { sql += "\r\n-- INDEXES --\r\n"; foreach (var index in indexes) { if (string.IsNullOrEmpty(index.sql)) { continue; } sql += index.sql + ";\r\n"; } } List triggers = TableDefs.Where(f => f.type == "trigger" && f.tbl_name == table.tbl_name && !string.IsNullOrEmpty(f.sql)).ToList(); if (triggers.Count > 0) { sql += "\r\n-- TRIGGERS --\r\n"; foreach (var trigger in triggers) { if (string.IsNullOrEmpty(trigger.sql)) { continue; } sql += trigger.sql + ";\r\n"; } } sql += "-- END TABLE " + table.tbl_name + " --\r\n\r\n"; //TableSql.Add(sql); } return sql; } } } }