Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 138 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,159 @@ A C# class generator from SQL CREATE TABLE Statements (MySQLs)
dotnet tool install --global MySQLToCsharp
```

## Sample

Open MySQLToCsharp.sln and set following.

> MySQLToCsharp project > Properties > Debug > Application arguments

```
dir -i ../../../../../samples/tables -o ../../../../../samples/MySQLToCsharpSampleConsoleApp -n MySQLToCsharpSampleConsoleApp
```

Debug Run MySQLToCsharp.

```
Output Directory: ../../../../../samples/MySQLToCsharpSampleConsoleApp
[-] skipped: BinaryData.cs (no change)
[-] skipped: Character.cs (no change)
[-] skipped: CharacterSlot.cs (no change)
[-] skipped: Multi.cs (no change)
[-] skipped: Player.cs (no change)
[-] skipped: Room.cs (no change)
[-] skipped: String.cs (no change)
[-] skipped: Weapon.cs (no change)
```

change Converter to `StandardDateTimeAsOffsetConverter` and Debug Run.

```
dir -i ../../../../../samples/tables -o ../../../../../samples/MySQLToCsharpSampleConsoleApp -n MySQLToCsharpSampleConsoleApp -c StandardDateTimeAsOffsetConverter
```

This change CharacterSlot.cs as MySQL `DATETIME` will convert to C# `DateTimeOffset`.

```
Output Directory: ../../../../../samples/MySQLToCsharpSampleConsoleApp
[-] skipped: BinaryData.cs (no change)
[-] skipped: Character.cs (no change)
[o] generate: CharacterSlot.cs
[-] skipped: Multi.cs (no change)
[-] skipped: Player.cs (no change)
[-] skipped: Room.cs (no change)
[-] skipped: String.cs (no change)
[-] skipped: Weapon.cs (no change)
```

## How to run

There are 3 options to generate C# code from MySQL Create Table query.

1. input sql string and generate a class.
1. read sql file and generate a class.
1. read directory path and generate class for each *.sql file.
1. query: input sql string and generate a class.
1. file: read sql file and generate a class.
1. dir: read directory path and generate class for each *.sql file.

generate from query.
```shell
$ MySQLToCsharp --help

Usage: MySQLToCsharp <Command>

Commands:
query Convert DDL sql query and generate C# class.
file Convert DDL sql file and generate C# class.
dir Convert DDL sql files in the folder and generate C# class.
```

### query

help.

```shell
# query
mysql2csharp --query -i "CREATE TABLE sercol1 (id INT, val INT);" -o bin/out -n MyNameSpace.Data
$ MySQLToCsharp query --help

Usage: MySQLToCsharp query [options...]

Convert DDL sql query and generate C# class.

Options:
-i, -input <String> input mysql ddl query to parse (Required)
-o, -output <String> output directory path of generated C# class file (Required)
-n, -namespace <String> namespace to write (Required)
-c, -converter <String> converter name to use (Default: StandardConverter)
-addbom <Boolean> (Default: False)
-dry <Boolean> (Default: False)
```

generate from file.
sample

```shell
# file
dotnet mysql2csharp --file -i "./MySQLToCsharp.Tests/test_data/sql/create_table.sql" -o bin/out -n MyNameSpace.Data
dotnet mysql2csharp query -i "CREATE TABLE sercol1 (id INT, val INT);" -o bin/out -n MyNameSpace.Data
```

read directory and generate for all *.sql
### file

help.

```shell
$ MySQLToCsharp file --help

Usage: MySQLToCsharp file [options...]

Convert DDL sql file and generate C# class.

Options:
-i, -input <String> input file path to parse mysql ddl query (Required)
-o, -output <String> output directory path of generated C# class file (Required)
-n, -namespace <String> namespace to write (Required)
-c, -converter <String> converter name to use (Default: StandardConverter)
-addbom <Boolean> (Default: False)
-dry <Boolean> (Default: False)
```

sample

```shell
dotnet mysql2csharp file -i "./MySQLToCsharp.Tests/test_data/sql/create_table.sql" -o bin/out -n MyNameSpace.Data
```

### dir

help.

```shell
# dirctory
dotnet mysql2csharp --dir -i "./MySQLToCsharp.Tests/test_data/sql/" -o bin/out -n MyNameSpace.Data
$ MySQLToCsharp dir --help

Usage: MySQLToCsharp dir [options...]

Convert DDL sql files in the folder and generate C# class.

Options:
-i, -input <String> input folder path to parse mysql ddl query (Required)
-o, -output <String> output directory path of generated C# class files (Required)
-n, -namespace <String> namespace to write (Required)
-c, -converter <String> converter name to use (Default: StandardConverter)
-addbom <Boolean> (Default: False)
-dry <Boolean> (Default: False)
```

sample

```shell
dotnet mysql2csharp dir -i "./MySQLToCsharp.Tests/test_data/sql/" -o bin/out -n MyNameSpace.Data
```

## Available Conveters

* StandardConverter
* StandardBitAsBoolConverter
* StandardDateTimeAsOffsetConverter

## Help

```
$ dotnet mysql2csharp query --help
$ dotnet mysql2csharp dir --help
$ dotnet mysql2csharp file --help
```

## Generate MySQL Lexer/Parser/Listener/Visitor from ANTLR4 grammer
Expand Down
11 changes: 7 additions & 4 deletions src/MySQLToCsharp/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public Generator(bool addbom, ITypeConverter typeConverter)
encoding = new UTF8Encoding(addbom);
}

public void Save(string @namespace, IEnumerable<MySqlTableDefinition> tables, string outputFolderPath)
public void Save(string @namespace, IEnumerable<MySqlTableDefinition> tables, string outputFolderPath, bool dry)
{
foreach (var table in tables)
{
Save(@namespace, table, outputFolderPath);
Save(@namespace, table, outputFolderPath, dry);
}
}
public void Save(string @namespace, MySqlTableDefinition table, string outputFolderPath)
public void Save(string @namespace, MySqlTableDefinition table, string outputFolderPath, bool dry)
{
var @class = GetClassName(table.Name);
var fileName = @class + extension;
Expand All @@ -56,7 +56,10 @@ public void Save(string @namespace, MySqlTableDefinition table, string outputFol
}
}
Console.WriteLine($"[o] generate: {fileName}");
File.WriteAllText(outputFile, generated, encoding);
if (!dry)
{
File.WriteAllText(outputFile, generated, encoding);
}
}

private string Generate(string @namespace, string classname, MySqlTableDefinition table, ITypeConverter typeConverter)
Expand Down
2 changes: 1 addition & 1 deletion src/MySQLToCsharp/MySQLToCsharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

<ItemGroup>
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.8.0" />
<PackageReference Include="MicroBatchFramework" Version="1.2.0" />
<PackageReference Include="ConsoleAppFramework" Version="2.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
60 changes: 38 additions & 22 deletions src/MySQLToCsharp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using MicroBatchFramework;
using ConsoleAppFramework;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MySQLToCsharp.Listeners;
using MySQLToCsharp.Parsers;
using MySQLToCsharp.TypeConverters;
using System;
using System.Linq;
using System.Threading.Tasks;

Expand All @@ -13,63 +13,79 @@ partial class Program
{
static async Task Main(string[] args)
{
await BatchHost.CreateDefaultBuilder().RunBatchEngineAsync<QueryToCSharp>(args);
await Host.CreateDefaultBuilder()
.ConfigureLogging(logging => logging.ReplaceToSimpleConsole())
.RunConsoleAppFrameworkAsync<QueryToCSharp>(args);
}
}
public class QueryToCSharp : BatchBase
public class QueryToCSharp : ConsoleAppBase
{
const string defaultConverter = nameof(StandardConverter);
readonly ILogger<QueryToCSharp> logger;

[Command(new[] { "--query", "-q" }, "read input sql and generate C# class.")]
public QueryToCSharp(ILogger<QueryToCSharp> logger) => (this.logger) = logger;

[Command(new[] { "query" }, "Convert DDL sql query and generate C# class.")]
public void ParseString(
[Option("-i", "mysql query to parse")]string input,
[Option("-o", "directory path to output C# class file")]string output,
[Option("-i", "input mysql ddl query to parse")]string input,
[Option("-o", "output directory path of generated C# class file")]string output,
[Option("-n", "namespace to write")]string @namespace,
[Option("-c", "converter name to use")]string converter = defaultConverter,
[Option("--addbom", "add bom or not")]bool addbom = false)
bool addbom = false,
bool dry = false)
{
var listener = new CreateTableStatementDetectListener();
IParser parser = new Parser();
parser.Parse(input, listener);
var definition = listener.TableDefinition;
var resolvedConverter = TypeConverterResolver.Resolve(converter);

Context.Logger.LogInformation($"Output Directory: {output}");
new Generator(addbom, resolvedConverter).Save(@namespace, definition, output);
PrintDryMessage(dry);
logger.LogInformation($"Output Directory: {output}");
new Generator(addbom, resolvedConverter).Save(@namespace, definition, output, dry);
}

[Command(new[] { "--file", "-f" }, "read specified .sql file and generate C# class.")]
[Command(new[] { "file" }, "Convert DDL sql file and generate C# class.")]
public void ParseFromFile(
[Option("-i", "file path to parse mysql query")]string input,
[Option("-o", "directory path to output C# class file")]string output,
[Option("-i", "input file path to parse mysql ddl query")]string input,
[Option("-o", "output directory path of generated C# class file")]string output,
[Option("-n", "namespace to write")]string @namespace,
[Option("-c", "converter name to use")]string converter = defaultConverter,
[Option("--addbom", "add bom or not")]bool addbom = false)
bool addbom = false,
bool dry = false)
{
var definition = Parser.FromFile(input, false);
var resolvedConverter = TypeConverterResolver.Resolve(converter);

Context.Logger.LogInformation($"Output Directory: {output}");
new Generator(addbom, resolvedConverter).Save(@namespace, definition, output);
PrintDryMessage(dry);
logger.LogInformation($"Output Directory: {output}");
new Generator(addbom, resolvedConverter).Save(@namespace, definition, output, dry);
}

[Command(new[] { "--dir", "-d" }, "list directory's *.sql file and generate C# class.")]
[Command(new[] { "dir" }, "Convert DDL sql files in the folder and generate C# class.")]
public void ParseFromFolder(
[Option("-i", "folder path to parse mysql query")]string input,
[Option("-o", "directory path to output C# class file")]string output,
[Option("-i", "input folder path to parse mysql ddl query")]string input,
[Option("-o", "output directory path of generated C# class files")]string output,
[Option("-n", "namespace to write")]string @namespace,
[Option("-c", "converter name to use")]string converter = defaultConverter,
[Option("--addbom", "add bom or not")]bool addbom = false)
bool addbom = false,
bool dry = false)
{
var definitions = Parser.FromFolder(input, false).ToArray();
var resolvedConverter = TypeConverterResolver.Resolve(converter);
var generator = new Generator(addbom, resolvedConverter);

Context.Logger.LogInformation($"Output Directory: {output}");
PrintDryMessage(dry);
logger.LogInformation($"Output Directory: {output}");
foreach (var definition in definitions)
{
generator.Save(@namespace, definition, output);
generator.Save(@namespace, definition, output, dry);
}
}

private void PrintDryMessage(bool dry)
{
if (dry) logger.LogInformation($"[NOTE] dry run mode, {nameof(QueryToCSharp)} will not save to file.");
}
}
}