Skip to content

Commit ffa999f

Browse files
first commit
1 parent 1c3a3fd commit ffa999f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1125
-1779
lines changed

.env

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
SOURCE_WASM_FILE_UBUNTU="WasmRunner/obj/release/net8.0/wasi-wasm/wasm/for-publish/WasmRunner.wasm"
22
SOURCE_WASM_FILE="WasmRunner/bin/Release/net8.0/wasi-wasm/AppBundle/WasmRunner.wasm"
33
TESTS_CONTAINER_NAME="plugin-tests"
4-
MYSQL_CONNECTION_STRING="server=mysqldb;database=tests;user=root"
5-
POSTGRES_CONNECTION_STRING="host=postgresdb;database=tests;username=user;password=pass"
4+
DB_NAME="tests"
5+
DB_USER="root"
6+
DB_PASSWORD="pass"
7+
MYSQL_HOST="mysqldb"
8+
POSTGRES_HOST="postgresdb"
69
SQLC_CI_FILE="sqlc.ci.yaml"

CodeGenerator/CodeGenerator.cs

+61-132
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,26 @@
1-
using Grpc.Core;
2-
using Microsoft.CodeAnalysis.CSharp;
3-
using Microsoft.CodeAnalysis.CSharp.Syntax;
1+
using Google.Protobuf;
42
using Plugin;
3+
using RubyCodegen;
54
using SqlcGenCsharp.Drivers;
6-
using SqlcGenCsharp.Generators;
75
using System;
86
using System.Collections.Generic;
97
using System.IO;
108
using System.Linq;
119
using System.Threading.Tasks;
12-
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
1310
using File = Plugin.File;
1411

1512
namespace SqlcGenCsharp;
1613

1714
public class CodeGenerator
1815
{
1916
private static readonly char[] Separator = ['/'];
20-
21-
private static readonly string[] ResharperDisables =
22-
[
23-
"InconsistentNaming",
24-
"UnusedAutoPropertyAccessor.Global",
25-
"NotAccessedPositionalProperty.Global"
26-
];
27-
28-
private string? _namespaceName;
2917
private Options? _options;
3018
private DbDriver? _dbDriver;
31-
private DataClassesGen? _dataClassesGen;
32-
private RootGen? _rootGen;
33-
private UtilsGen? _utilsGen;
34-
private CsprojGen? _csprojGen;
3519

3620
private void InitGenerators(GenerateRequest generateRequest)
3721
{
3822
Options = new Options(generateRequest);
39-
NamespaceName = GenerateNamespace(generateRequest);
4023
DbDriver = InstantiateDriver();
41-
42-
// initialize file generators
43-
CsprojGen = new CsprojGen(generateRequest.Settings.Codegen.Out, Options);
44-
RootGen = new RootGen(Options);
45-
UtilsGen = new UtilsGen(NamespaceName, Options);
46-
DataClassesGen = new DataClassesGen(DbDriver);
47-
}
48-
49-
private string NamespaceName
50-
{
51-
get => _namespaceName!;
52-
set => _namespaceName = value;
5324
}
5425

5526
private Options Options
@@ -64,36 +35,12 @@ private DbDriver DbDriver
6435
set => _dbDriver = value;
6536
}
6637

67-
private DataClassesGen DataClassesGen
68-
{
69-
get => _dataClassesGen!;
70-
set => _dataClassesGen = value;
71-
}
72-
73-
private RootGen RootGen
74-
{
75-
get => _rootGen!;
76-
set => _rootGen = value;
77-
}
78-
79-
private UtilsGen UtilsGen
80-
{
81-
get => _utilsGen!;
82-
set => _utilsGen = value;
83-
}
84-
85-
private CsprojGen CsprojGen
86-
{
87-
get => _csprojGen!;
88-
set => _csprojGen = value;
89-
}
90-
9138
private DbDriver InstantiateDriver()
9239
{
9340
return Options.DriverName switch
9441
{
95-
DriverName.MySqlConnector => new MySqlConnectorDriver(Options.DotnetFramework),
96-
DriverName.Npgsql => new NpgsqlDriver(Options.DotnetFramework),
42+
DriverName.Mysql2 => new Mysql2Driver(),
43+
DriverName.Pg => new PgDriver(),
9744
_ => throw new ArgumentException($"unknown driver: {Options.DriverName}")
9845
};
9946
}
@@ -104,8 +51,7 @@ public Task<GenerateResponse> Generate(GenerateRequest generateRequest)
10451
var fileQueries = GetFileQueries();
10552
var files = fileQueries
10653
.Select(fq => GenerateFile(fq.Value, fq.Key))
107-
.Append(UtilsGen.GenerateFile())
108-
.AppendIf(CsprojGen.GenerateFile(), Options.GenerateCsproj);
54+
.Append(GenerateGemfile());
10955

11056
return Task.FromResult(new GenerateResponse { Files = { files } });
11157

@@ -138,116 +84,99 @@ private string GenerateNamespace(GenerateRequest generateRequest)
13884

13985
private File GenerateFile(IEnumerable<Query> queries, string className)
14086
{
141-
var (usingDirectives, classDeclaration) = GenerateClass(queries, className);
142-
var root = RootGen.CompilationRootGen(
143-
IdentifierName(NamespaceName), usingDirectives, classDeclaration);
144-
root = AddResharperDisables(root);
145-
root = root.AddCommentOnTop(Consts.AutoGeneratedComment);
87+
var (requiredGems, classDeclaration) = GenerateClass(queries, className);
88+
var contents = $"""
89+
{Consts.AutoGeneratedComment}
90+
{requiredGems.Select(r => r.Build()).JoinByNewLine()}
91+
92+
{classDeclaration.Build()}
93+
""";
14694

14795
return new File
14896
{
149-
Name = $"{className}.cs",
150-
Contents = root.ToByteString()
97+
Name = $"{className.SnakeCase()}.rb",
98+
Contents = ByteString.CopyFromUtf8(contents)
15199
};
152100
}
153101

154-
private static CompilationUnitSyntax AddResharperDisables(CompilationUnitSyntax compilationUnit)
102+
private File GenerateGemfile()
155103
{
156-
return ResharperDisables
157-
.Aggregate(compilationUnit, (current, resharperDisable) =>
158-
current.AddCommentOnTop($"// ReSharper disable {resharperDisable}"));
159-
}
104+
var requireGems = DbDriver.GetRequiredGems().Select(gem => $"gem '{gem.GetName()}'").JoinByNewLine();
105+
return new File
106+
{
107+
Name = "Gemfile",
108+
Contents = ByteString.CopyFromUtf8($"""
109+
source 'https://rubygems.org'
160110
161-
private (UsingDirectiveSyntax[], MemberDeclarationSyntax) GenerateClass(IEnumerable<Query> queries,
162-
string className)
163-
{
164-
var usingDirectives = DbDriver.GetUsingDirectives();
165-
var classMembers = queries.SelectMany(GetMembersForSingleQuery).ToArray();
166-
return (usingDirectives, GetClassDeclaration(className, classMembers));
111+
{requireGems}
112+
""")
113+
};
167114
}
168115

169-
private ClassDeclarationSyntax GetClassDeclaration(string className,
170-
IEnumerable<MemberDeclarationSyntax> classMembers)
116+
private (IEnumerable<RequireGem>, ClassDeclaration) GenerateClass(IEnumerable<Query> queries, string className)
171117
{
172-
var classDeclaration = (ClassDeclarationSyntax)(Options.DotnetFramework.LatestDotnetSupported()
173-
? GetWithPrimaryConstructor()
174-
: GetWithRegularConstructor());
175-
return classDeclaration.AddMembers(classMembers.ToArray());
176-
177-
MemberDeclarationSyntax GetWithPrimaryConstructor()
178-
{
179-
return ParseMemberDeclaration(
180-
$"class {className}(string {Variable.ConnectionString.Name()})" + "{}")!
181-
.AddModifiers(Token(SyntaxKind.PublicKeyword));
182-
}
183-
184-
MemberDeclarationSyntax GetWithRegularConstructor()
185-
{
186-
return ParseMemberDeclaration(
187-
$$"""
188-
class {{className}}
189-
{
190-
public {{className}}(string {{Variable.ConnectionString.Name()}})
191-
{
192-
this.{{Variable.ConnectionString.Name()}} = {{Variable.ConnectionString.Name()}};
193-
}
194-
private string {{Variable.ConnectionString.Name()}} { get; }
195-
}
196-
""")!
197-
.AddModifiers(Token(SyntaxKind.PublicKeyword));
198-
}
118+
var requiredGems = DbDriver.GetRequiredGems();
119+
var initMethod = DbDriver.GetInitMethod();
120+
var queryMembers = queries
121+
.SelectMany(q =>
122+
{
123+
IEnumerable<IComposable> members = new List<IComposable>();
124+
members = members.Append(GetQueryTextConstant(q));
125+
members = members.AppendIfNotNull(GetQueryColumnsDataclass(q));
126+
members = members.AppendIfNotNull(GetQueryParamsDataclass(q));
127+
members = members.Append(GetMethodDeclaration(q));
128+
return members;
129+
});
130+
var classMembers = new[] { initMethod }.Concat(queryMembers);
131+
return (requiredGems, new ClassDeclaration(className, classMembers));
199132
}
200133

201-
private MemberDeclarationSyntax[] GetMembersForSingleQuery(Query query)
134+
private static SimpleStatement GenerateDataclass(string name, ClassMember classMember, IEnumerable<Column> columns,
135+
Options options)
202136
{
203-
return new[]
204-
{
205-
GetQueryTextConstant(query),
206-
GetQueryColumnsDataclass(query),
207-
GetQueryParamsDataclass(query),
208-
AddMethodDeclaration(query)
209-
}
210-
.Where(member => member != null)
211-
.Cast<MemberDeclarationSyntax>()
212-
.ToArray();
137+
var dataclassName = $"{name.FirstCharToUpper()}{classMember.Name()}";
138+
var dataColumns = columns.Select(c => $":{c.Name.ToLower()}").JoinByCommaAndNewLine();
139+
return new SimpleStatement(dataclassName,
140+
new SimpleExpression(options.RubyMajorVersion.LatestRubySupported()
141+
? $"Struct.new(\n{dataColumns.Indent()}\n)"
142+
: $"Data.define(\n{dataColumns.Indent()}\n)"));
213143
}
214144

215-
private MemberDeclarationSyntax? GetQueryColumnsDataclass(Query query)
145+
private SimpleStatement? GetQueryColumnsDataclass(Query query)
216146
{
147+
if (query.Columns.Count <= 0) return null;
217148
return query.Columns.Count <= 0
218149
? null
219-
: DataClassesGen.Generate(query.Name, ClassMember.Row, query.Columns, Options);
150+
: GenerateDataclass(query.Name, ClassMember.Row, query.Columns, Options);
220151
}
221152

222-
private MemberDeclarationSyntax? GetQueryParamsDataclass(Query query)
153+
private SimpleStatement? GetQueryParamsDataclass(Query query)
223154
{
224155
if (query.Params.Count <= 0) return null;
225156
var columns = query.Params.Select(p => p.Column);
226-
return DataClassesGen.Generate(query.Name, ClassMember.Args, columns, Options);
157+
return GenerateDataclass(query.Name, ClassMember.Args, columns, Options);
227158
}
228159

229-
private MemberDeclarationSyntax GetQueryTextConstant(Query query)
160+
private static SimpleStatement GetQueryTextConstant(Query query)
230161
{
231-
return ParseMemberDeclaration(
232-
$"private const string {query.Name}{ClassMember.Sql.Name()} = \"{DbDriver.TransformQueryText(query)}\";")
233-
!
234-
.AppendNewLine();
162+
return new SimpleStatement($"{query.Name}{ClassMember.Sql}", new SimpleExpression($"%q({query.Text})"));
235163
}
236164

237-
private MemberDeclarationSyntax AddMethodDeclaration(Query query)
165+
private MethodDeclaration GetMethodDeclaration(Query query)
238166
{
239167
var queryTextConstant = GetInterfaceName(ClassMember.Sql);
240-
var argInterface = GetInterfaceName(ClassMember.Args);
168+
var argInterface = GetInterfaceName(ClassMember.Args).SnakeCase();
241169
var returnInterface = GetInterfaceName(ClassMember.Row);
170+
var funcName = query.Name.SnakeCase();
242171

243172
return query.Cmd switch
244173
{
245-
":exec" => DbDriver.ExecDeclare(query.Name, queryTextConstant, argInterface, query.Params),
246-
":one" => DbDriver.OneDeclare(query.Name, queryTextConstant, argInterface, returnInterface,
174+
":one" => DbDriver.OneDeclare(funcName, queryTextConstant, argInterface, returnInterface,
247175
query.Params, query.Columns),
248-
":many" => DbDriver.ManyDeclare(query.Name, queryTextConstant, argInterface, returnInterface,
176+
":many" => DbDriver.ManyDeclare(funcName, queryTextConstant, argInterface, returnInterface,
249177
query.Params, query.Columns),
250-
":execlastid" => DbDriver.ExecLastIdDeclare(query.Name, queryTextConstant, argInterface, query.Params),
178+
":exec" => DbDriver.ExecDeclare(funcName, queryTextConstant, argInterface, query.Params),
179+
":execlastid" => DbDriver.ExecLastIdDeclare(funcName, queryTextConstant, argInterface, query.Params),
251180
_ => throw new InvalidDataException()
252181
};
253182

CodeGenerator/CodeGenerator.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
<ItemGroup>
1010
<PackageReference Include="Google.Protobuf" Version="3.26.0-rc2"/>
11-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2"/>
1211
</ItemGroup>
1312

1413
<ItemGroup>

CodeGenerator/Consts.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ namespace SqlcGenCsharp;
22

33
public static class Consts
44
{
5-
public const string AutoGeneratedComment = "// auto-generated by sqlc - do not edit";
5+
public const string AutoGeneratedComment = "# auto-generated by sqlc - do not edit";
66
}

CodeGenerator/Generators/CsprojGen.cs

-52
This file was deleted.

0 commit comments

Comments
 (0)