Add project files.
This commit is contained in:
29
Extensions/DatabaseExtensions.cs
Normal file
29
Extensions/DatabaseExtensions.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using DbTools.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace DbTools {
|
||||
internal static class DatabaseExtensions {
|
||||
|
||||
public static string ExportSql(this Database db) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (var table in db.Tables.GetTables()) {
|
||||
sb.AppendLine(table.FullSql());
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static void ImportFromSqlite(this Database db) {
|
||||
|
||||
}
|
||||
|
||||
public static string[] GetAllIndexes(this Database db) {
|
||||
List<string> indexes = new List<string>();
|
||||
foreach (var table in db.Tables.GetTables()) {
|
||||
indexes.AddRange(table.Indexes.Keys);
|
||||
}
|
||||
return indexes.ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
141
Extensions/TableExtensions.cs
Normal file
141
Extensions/TableExtensions.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using DbTools.Model;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DbTools {
|
||||
internal static class TableExtensions {
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the column names that are common between the current table and the specified table.
|
||||
/// </summary>
|
||||
/// <param name="table1">The source table from which to retrieve column names.</param>
|
||||
/// <param name="table2">The table to compare against for common column names.</param>
|
||||
/// <returns>An array of strings containing the names of columns that exist in both tables. The array will be empty if no
|
||||
/// common columns are found.</returns>
|
||||
public static string[] GetCommonColumns(this Table table1, Table table2) {
|
||||
return table1.GetColumnNames().Where(f => table2.HasColumn(f)).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the provided SQL script to extract and populate table metadata, including the table name, columns,
|
||||
/// indexes, and triggers.
|
||||
/// </summary>
|
||||
/// <remarks>This method processes the SQL script line by line to identify and extract the table
|
||||
/// definition, column definitions, indexes, and triggers. - If <paramref name="tableName"/> is specified, only
|
||||
/// metadata for the specified table is extracted. - If <paramref name="tableName"/> is not specified, the table
|
||||
/// name is inferred from the first `CREATE TABLE` statement in the script. Lines starting with `--` are
|
||||
/// ignored as comments. The method stops processing once the metadata for the specified or inferred table is
|
||||
/// fully extracted.</remarks>
|
||||
/// <param name="table">The <see cref="Table"/> instance to populate with metadata extracted from the SQL script.</param>
|
||||
/// <param name="sql">The SQL script to parse. The script should define a table and optionally include indexes and triggers.</param>
|
||||
/// <param name="tableName">An optional name of the table to extract from the SQL script. If not provided, the table name will be
|
||||
/// inferred from the SQL script.</param>
|
||||
public static void ParseSql(this Table 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;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateDropTable(this Table table) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (table.HasTriggers()) {
|
||||
foreach (var trigger in table.Triggers.Keys) {
|
||||
sb.AppendLine($"DROP TRIGGER IF EXISTS {trigger};");
|
||||
}
|
||||
}
|
||||
if (table.HasIndexes()) {
|
||||
foreach (var index in table.Indexes.Keys) {
|
||||
sb.AppendLine($"DROP INDEX IF EXISTS {index};");
|
||||
}
|
||||
}
|
||||
sb.AppendLine($"DROP TABLE IF EXISTS {table.TableName};");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GenerateTableMigration(this Table newTable, Table oldTable) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
string tableName = newTable.TableName;
|
||||
|
||||
sb.AppendLine("\r\n-- Table " + tableName + " requires alteration - Create temp table and move data");
|
||||
string[] commonColumns = newTable.GetCommonColumns(oldTable);
|
||||
string columnList = string.Join(",", commonColumns);
|
||||
|
||||
string sql = newTable.CreateTableSql;
|
||||
string newTableName = tableName + "_" + DateTime.Now.ToString("yyyyMMddHHmmss");
|
||||
sql = Regex.Replace(sql, "CREATE TABLE (\\w*)", "CREATE TABLE IF NOT EXISTS $1_" + newTableName.Substring(newTableName.IndexOf("_") + 1));
|
||||
sb.AppendLine(sql);
|
||||
|
||||
sb.AppendLine("\r\n-- Copy data from existing table to new table");
|
||||
sb.AppendLine("INSERT INTO " + newTableName + " (" + columnList + ")");
|
||||
sb.AppendLine("\tSELECT " + columnList);
|
||||
sb.AppendLine("\tFROM " + tableName + ";");
|
||||
sb.AppendLine("\r\n-- Drop existing table");
|
||||
sb.AppendLine("DROP TABLE " + tableName + ";");
|
||||
sb.AppendLine("\r\n-- Rename the new table to replace the old table");
|
||||
sb.AppendLine("ALTER TABLE " + newTableName + " RENAME TO " + tableName + ";");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user