Skip to content

Instantly share code, notes, and snippets.

@Sandip124
Created February 14, 2022 04:53
Show Gist options
  • Save Sandip124/454fbd63c623711020269625af2ed209 to your computer and use it in GitHub Desktop.
Save Sandip124/454fbd63c623711020269625af2ed209 to your computer and use it in GitHub Desktop.
Sql Splitter
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SchemaSplitter
{
class Program
{
public const string FileName = "schema.sql";
public const string OutputDirectoryPath = "output";
static async Task Main(string[] args)
{
var fileName = args.Length > 0 && !string.IsNullOrEmpty(args[0]) ? args[0] : FileName;
try
{
var currentDirectory = Directory.GetCurrentDirectory();
var absolutePath = Path.Combine(currentDirectory, fileName!);
var outputDirectory = Path.Combine(currentDirectory, OutputDirectoryPath);
CleanDirectory(outputDirectory);
if (File.Exists(absolutePath))
{
var fileLine = CleanUpFileForSplitting(fileName);
var stringBuilder = new StringBuilder();
foreach (var line in fileLine)
{
if (IsComment(line)) continue;
if (line.StartsWith("SET SQL_MODE")) continue;
stringBuilder.AppendLine(line);
var sourceString = stringBuilder.ToString();
var resultFileName = GetFileNameFromSqlStatement(sourceString);
var outputDirPath = outputDirectory;
resultFileName = GenerateDirectoryAndFileName(sourceString, resultFileName, ref outputDirPath);
Console.WriteLine(resultFileName);
CreateDirectoryIfNotExists(outputDirPath);
await SaveFile(sourceString, outputDirPath, resultFileName);
stringBuilder.Clear();
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void CleanDirectory(string outputDirectory)
{
Directory.Delete(outputDirectory, true);
}
private static async Task SaveFile(string sourceString, string dirPath, string resultFileName)
{
var path = Path.Combine(dirPath, GetFileNameWithExtension(resultFileName));
if (File.Exists(path))
{
await using var file = File.Open(path, FileMode.Append, FileAccess.Write);
await using var writer = new StreamWriter(file);
await writer.WriteLineAsync(sourceString);
await writer.FlushAsync();
}
else
{
await using var fs = File.Create(path);
var content = new UTF8Encoding(true).GetBytes(sourceString);
fs.Write(content, 0, content.Length);
}
}
private static void CreateDirectoryIfNotExists(string dirPath)
{
if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
}
private static string GetFileNameWithExtension(string resultFileName,string extension = "sql")
{
return $"{resultFileName}.{extension}";
}
private static string GenerateDirectoryAndFileName(string sourceString, string resultFileName, ref string dirPath)
{
const string schemaPath = "schema";
const string seedPath = "seed";
const string constraintPath = "constraint";
if (sourceString.StartsWith("CREATE TABLE"))
{
resultFileName = $"{schemaPath}_{resultFileName}";
dirPath = Path.Combine(dirPath, schemaPath);
}
else if (sourceString.StartsWith("ALTER TABLE"))
{
resultFileName = $"{constraintPath}_{resultFileName}";
dirPath = Path.Combine(dirPath, constraintPath);
}
else if (sourceString.StartsWith("INSERT INTO"))
{
resultFileName = $"{seedPath}_{resultFileName}";
dirPath = Path.Combine(dirPath, seedPath);
}
return resultFileName;
}
private static IEnumerable<string> CleanUpFileForSplitting(string fileName)
{
var fileLine = File.ReadAllText(fileName);
fileLine = fileLine.Replace("START TRANSACTION;","");
fileLine = fileLine.Replace("COMMIT;","");
var multipleLinesCleaned = Regex.Replace(fileLine, @"^\s+$[\n\n]*", "\n", RegexOptions.Multiline);
var result = multipleLinesCleaned.Split(new[] { "\n\n" },
StringSplitOptions.RemoveEmptyEntries);
return result;
}
private static string GetFileNameFromSqlStatement(string sourceString, string delimiter = "`")
{
var startIndex = sourceString.IndexOf(delimiter, StringComparison.Ordinal) + 1;
var secondIndex = sourceString.IndexOf(delimiter, startIndex, StringComparison.Ordinal);
var length = secondIndex - startIndex;
var resultFileName = sourceString.Substring(startIndex, length);
return resultFileName;
}
private static bool IsComment(string line)
{
return line.StartsWith("/*") && line.EndsWith("*/;");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment