121 lines
4.6 KiB
C#
121 lines
4.6 KiB
C#
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<SqlTable> Tables { get; set; } = new List<SqlTable>();
|
|
|
|
|
|
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<SqlTable> 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<string> BuildSql(string dbConnectionString, bool includeIfNotExist = false) {
|
|
using (OleDbConnection cn = new OleDbConnection(dbConnectionString)) {
|
|
string sql = "";
|
|
|
|
//List<string> TableSql = new List<string>();
|
|
IEnumerable<SqliteTableDefinition> TableDefs = await cn.QueryAsync<SqliteTableDefinition>("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<SqliteTableDefinition> 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<SqliteTableDefinition> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|