diff --git a/Class1.cs b/Class1.cs
deleted file mode 100644
index 5edbcbd..0000000
--- a/Class1.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace DbMigrate
-{
- public class Class1
- {
- }
-}
diff --git a/DbMigrate.csproj b/DbMigrate.csproj
index 03eeaa1..7c5b906 100644
--- a/DbMigrate.csproj
+++ b/DbMigrate.csproj
@@ -1,10 +1,10 @@
-
+
Debug
AnyCPU
- a4a58207-cf8c-46fd-9749-3d4d8816e11a
+ {A4A58207-CF8C-46FD-9749-3D4D8816E11A}
Library
Properties
DbMigrate
@@ -31,24 +31,20 @@
4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
-
+
\ No newline at end of file
diff --git a/Extensions.cs b/Extensions.cs
new file mode 100644
index 0000000..e97bcba
--- /dev/null
+++ b/Extensions.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace DbMigrate {
+ internal static class Extensions {
+ public static string[] GetCommonColumns(this SqlTable table, SqlTable table2) {
+ return table.GetColumnNames().Where(f => table2.HasColumn(f)).ToArray();
+ }
+
+ public static void ParseSql(this SqlTable table, string sql, string tableName = null) {
+ if (tableName != null) {
+ table.TableName = tableName;
+ }
+
+ bool inTable = false;
+ bool inColumns = false;
+
+ Match m = null;
+ foreach (string line in Regex.Split(sql, "\\r\\n")) {
+ if (string.IsNullOrEmpty(line) || line.StartsWith("--")) {
+ continue;
+ }
+
+ m = Regex.Match(line, "^CREATE TABLE( IF NOT EXISTS)? (\\S+) ");
+ if (m.Success) {
+ if (string.IsNullOrEmpty(tableName) && string.IsNullOrEmpty(table.TableName)) {
+ // Set table name from the above regex match
+ table.TableName = m.Groups[2].Value.Trim();
+ }
+ if (!inTable && (table.TableName == null || m.Groups[2].Value.Trim() == table.TableName)) {
+ table.CreateTableSql += line + Environment.NewLine;
+ inTable = true;
+ inColumns = true;
+ continue;
+ } else {
+ if (inTable) {
+ // We are done with this table
+ return;
+ }
+ continue;
+ }
+ }
+
+ m = Regex.Match(line, "^CREATE INDEX( IF NOT EXISTS)? (\\S+) ");
+ if (m.Success && inTable) {
+ table.Indexes.Add(m.Groups[2].Value.Trim(), line.Trim());
+ continue;
+ }
+
+ m = Regex.Match(line, "^CREATE TRIGGER( IF NOT EXISTS)? (\\S+) ");
+ if (m.Success && inTable) {
+ table.Triggers.Add(m.Groups[2].Value.Trim(), line.Trim());
+ continue;
+ }
+
+ if (inColumns) {
+ if (line.Trim().StartsWith(")")) {
+ inColumns = false;
+ } else {
+ m = Regex.Match(line.Trim(), "^(\\S+).*");
+ if (m.Success) {
+ string columnLine = line.Trim();
+ if (columnLine.EndsWith(",")) {
+ columnLine = columnLine.Substring(0, columnLine.Length - 1);
+ }
+ table.Columns.Add(m.Groups[1].Value.Trim(), columnLine);
+ }
+ }
+ }
+
+ table.CreateTableSql += line + Environment.NewLine;
+ }
+ }
+ }
+}
diff --git a/SqlDatabase.cs b/SqlDatabase.cs
new file mode 100644
index 0000000..8b9f495
--- /dev/null
+++ b/SqlDatabase.cs
@@ -0,0 +1,120 @@
+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;
+ }
+ }
+ }
+}
diff --git a/SqlTable.cs b/SqlTable.cs
new file mode 100644
index 0000000..fdbc95a
--- /dev/null
+++ b/SqlTable.cs
@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DbMigrate {
+ public class SqlTable {
+ public string TableName { get; set; }
+ public string CreateTableSql { get; set; }
+ public string OriginalSql { get; set; }
+ public Dictionary Columns { get; set; }
+ public Dictionary Indexes { get; set; }
+ public Dictionary Triggers { get; set; }
+
+
+
+ public SqlTable() {
+ Columns = new Dictionary();
+ Indexes = new Dictionary();
+ Triggers = new Dictionary();
+ }
+
+ public SqlTable(string sql) {
+ OriginalSql = sql;
+ this.ParseSql(sql);
+ }
+
+ public string FullSql() {
+ StringBuilder sb = new StringBuilder();
+ //sb.AppendLine("-- Create Table " + TableName);
+ sb.AppendLine(CreateTableSql);
+
+ if (Indexes.Count > 0) {
+ sb.AppendLine("\r\n-- Create Indexes");
+ foreach (string index in Indexes.Keys) {
+ sb.AppendLine(Indexes[index]);
+ }
+ }
+
+ if (Triggers.Count > 0) {
+ sb.AppendLine("\r\n-- Create Triggers");
+ foreach (string trigger in Triggers.Keys) {
+ sb.AppendLine(Triggers[trigger]);
+ }
+ }
+
+ sb.AppendLine();
+ return sb.ToString();
+ }
+
+ public string[] GetColumnNames() {
+ return Columns.Keys.ToArray();
+ }
+
+ public string[] GetColumns() {
+ return Columns.Values.ToArray();
+ }
+
+ public bool HasColumn(string columnName) {
+ return Columns.ContainsKey(columnName);
+ }
+
+ public string[] GetTriggerNames() {
+ return Triggers.Keys.ToArray();
+ }
+
+ public string[] GetTriggers() {
+ return Triggers.Values.ToArray();
+ }
+
+ public string[] GetIndexNames() {
+ return Indexes.Keys.ToArray();
+ }
+
+ public string[] GetIndexes() {
+ return Indexes.Values.ToArray();
+ }
+
+ }
+}