Skip to content

Commit 321c3ec

Browse files
[release] [minor] fix: standardize assertions across end2end tests (#268)
* fix: standardize assertions across end2end tests * fix: change mysql set data type to map to HashSet instead of array * fix: add test for invalid xml for postgres xml data type * fix: split postgres authors and data types tables to different files * fix: postgres legacy end2end tests * fix: split mysql authors and data types tables to different files * fix: sql constant bad whitespace transformation * fix: whitespace regex + more concise code * fix: re-generate code * fix: add missing mysql datetime tests * fix: separate the rest of mysql data types by group * fix: re-generate code * fix: separate sqlite schema and query files by type and authors * fix: extract common transaction exception throw to a constant * fix: more refactoring * fix: simplify Drivers method placement * fix: missing assertions in postgres guid end2end tests * fix: revert incorrect changes to Drivers * fix: refactor to support postgres enums * fix: remove redundant using directives * fix: enum logic for mysql * fix: move enum logic to be behind an abstract class * fix: postgres EnumToCsharpDataType * fix: separate string data types to their own table * feat: support full text search data types * fix: move test types config to constants * fix: more separate data types queries for Postgtres * fix: move authors schema to be first in config * fix: separate numeric data types queries for Postgtres * fix: separate rest of postgres data types to own table * feat: support array data types in batch inserts * fix: update Postgres data types doc * fix: Update Postgrs doc with data type conversion example
1 parent 7f80202 commit 321c3ec

124 files changed

Lines changed: 30902 additions & 20299 deletions

File tree

Some content is hidden

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

.github/workflows/legacy-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151

5252
- name: Init PostgresSQL Schema
5353
shell: powershell
54-
run: psql -U $Env:POSTGRES_USER -f 'examples/config/postgresql/schema.sql'
54+
run: psql -U $Env:POSTGRES_USER -f 'examples/config/postgresql/types/schema.sql' -f 'examples/config/postgresql/authors/schema.sql'
5555
env:
5656
PGSERVICE: ${{ steps.postgres.outputs.service-name }}
5757
PGPASSWORD: ${{ env.POSTGRES_PASSWORD }}
@@ -101,7 +101,7 @@ jobs:
101101
$env:Path += ";C:\Program Files\MySQL\MySQL Server 8.0\bin"
102102
[Environment]::SetEnvironmentVariable("Path", $env:Path, "Machine")
103103
mysql -u root -e "SET GLOBAL local_infile=1; CREATE DATABASE $Env:TESTS_DB;"
104-
mysql -u root $Env:TESTS_DB --execute="source examples/config/mysql/schema.sql"
104+
mysql -u root $Env:TESTS_DB --execute="source examples/config/mysql/types/schema.sql; source examples/config/mysql/authors/schema.sql;"
105105
106106
- name: Run Tests
107107
shell: powershell

CodeGenerator/CodeGenerator.cs

Lines changed: 18 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,13 @@
99
using System.Text;
1010
using System.Text.Json;
1111
using System.Threading.Tasks;
12-
using Enum = Plugin.Enum;
1312

1413
namespace SqlcGenCsharp;
1514

1615
public class CodeGenerator
1716
{
18-
private readonly HashSet<string> _excludedSchemas =
19-
[
20-
"pg_catalog",
21-
"information_schema"
22-
];
23-
2417
private Options? _options;
25-
private Dictionary<string, Dictionary<string, Table>>? _tables;
26-
private Dictionary<string, Dictionary<string, Enum>>? _enums;
18+
private Catalog? _catalog;
2719
private List<Query>? _queries;
2820
private DbDriver? _dbDriver;
2921
private QueriesGen? _queriesGen;
@@ -37,16 +29,10 @@ private Options Options
3729
set => _options = value;
3830
}
3931

40-
private Dictionary<string, Dictionary<string, Table>> Tables
32+
private Catalog Catalog
4133
{
42-
get => _tables!;
43-
set => _tables = value;
44-
}
45-
46-
private Dictionary<string, Dictionary<string, Enum>> Enums
47-
{
48-
get => _enums!;
49-
set => _enums = value;
34+
get => _catalog!;
35+
set => _catalog = value;
5036
}
5137

5238
private List<Query> Queries
@@ -89,79 +75,29 @@ private void InitGenerators(GenerateRequest generateRequest)
8975
{
9076
var outputDirectory = generateRequest.Settings.Codegen.Out;
9177
var projectName = new DirectoryInfo(outputDirectory).Name;
92-
Options = new Options(generateRequest);
78+
Options = new(generateRequest);
9379
if (Options.DebugRequest)
9480
return;
9581

9682
Queries = generateRequest.Queries.ToList();
97-
Tables = ConstructTablesLookup(generateRequest.Catalog);
98-
Enums = ConstructEnumsLookup(generateRequest.Catalog);
99-
10083
var namespaceName = Options.NamespaceName == string.Empty ? projectName : Options.NamespaceName;
101-
DbDriver = InstantiateDriver(generateRequest.Catalog.DefaultSchema);
84+
Catalog = generateRequest.Catalog;
85+
DbDriver = InstantiateDriver();
10286

10387
// initialize file generators
104-
CsprojGen = new CsprojGen(outputDirectory, projectName, namespaceName, Options);
105-
QueriesGen = new QueriesGen(DbDriver, namespaceName);
106-
ModelsGen = new ModelsGen(DbDriver, namespaceName);
107-
UtilsGen = new UtilsGen(DbDriver, namespaceName);
108-
}
109-
110-
private Dictionary<string, Dictionary<string, Table>> ConstructTablesLookup(Catalog catalog)
111-
{
112-
return catalog.Schemas
113-
.Where(s => !_excludedSchemas.Contains(s.Name))
114-
.ToDictionary(
115-
s => s.Name == catalog.DefaultSchema ? string.Empty : s.Name,
116-
s => s.Tables.ToDictionary(t => t.Rel.Name, t => t));
117-
}
118-
119-
/// <summary>
120-
/// Enums in the request exist only in the default schema (in mysql), this remaps enums to their original schema.
121-
/// </summary>
122-
/// <param name="catalog"></param>
123-
/// <returns></returns>
124-
private Dictionary<string, Dictionary<string, Enum>> ConstructEnumsLookup(Catalog catalog)
125-
{
126-
var defaultSchemaCatalog = catalog.Schemas.First(s => s.Name == catalog.DefaultSchema);
127-
var schemaEnumTuples = defaultSchemaCatalog.Enums
128-
.Select(e => new
129-
{
130-
EnumItem = e,
131-
Schema = FindEnumSchema(e)
132-
});
133-
var schemaToEnums = schemaEnumTuples
134-
.GroupBy(x => x.Schema)
135-
.ToDictionary(
136-
group => group.Key,
137-
group => group.ToDictionary(
138-
x => x.EnumItem.Name,
139-
x => x.EnumItem)
140-
);
141-
return schemaToEnums;
142-
}
143-
144-
private string FindEnumSchema(Enum e)
145-
{
146-
foreach (var schemaTables in Tables)
147-
{
148-
foreach (var table in schemaTables.Value)
149-
{
150-
var isEnumColumn = table.Value.Columns.Any(c => c.Type.Name == e.Name);
151-
if (isEnumColumn)
152-
return schemaTables.Key;
153-
}
154-
}
155-
throw new InvalidDataException($"No enum {e.Name} schema found.");
88+
CsprojGen = new(outputDirectory, projectName, namespaceName, Options);
89+
QueriesGen = new(DbDriver, namespaceName);
90+
ModelsGen = new(DbDriver, namespaceName);
91+
UtilsGen = new(DbDriver, namespaceName);
15692
}
15793

158-
private DbDriver InstantiateDriver(string defaultSchema)
94+
private DbDriver InstantiateDriver()
15995
{
16096
return Options.DriverName switch
16197
{
162-
DriverName.MySqlConnector => new MySqlConnectorDriver(Options, defaultSchema, Tables, Enums, Queries),
163-
DriverName.Npgsql => new NpgsqlDriver(Options, defaultSchema, Tables, Enums, Queries),
164-
DriverName.Sqlite => new SqliteDriver(Options, defaultSchema, Tables, Enums, Queries),
98+
DriverName.MySqlConnector => new MySqlConnectorDriver(Options, Catalog, Queries),
99+
DriverName.Npgsql => new NpgsqlDriver(Options, Catalog, Queries),
100+
DriverName.Sqlite => new SqliteDriver(Options, Catalog, Queries),
165101
_ => throw new ArgumentException($"unknown driver: {Options.DriverName}")
166102
};
167103
}
@@ -182,7 +118,7 @@ public Task<GenerateResponse> Generate(GenerateRequest generateRequest)
182118
var files = GetFileQueries()
183119
.Select(fq => QueriesGen.GenerateFile(fq.Value, fq.Key))
184120
.AddRangeExcludeNulls([
185-
ModelsGen.GenerateFile(Tables, Enums),
121+
ModelsGen.GenerateFile(DbDriver.Tables, DbDriver.Enums),
186122
UtilsGen.GenerateFile()
187123
])
188124
.AddRangeIf([CsprojGen.GenerateFile()], Options.GenerateCsproj);
@@ -218,12 +154,12 @@ private static Plugin.File RequestToJsonFile(GenerateRequest request)
218154
{
219155
var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithIndentation());
220156
request.PluginOptions = GetOptionsWithoutDebugRequest(request);
221-
return new Plugin.File { Name = "request.json", Contents = ByteString.CopyFromUtf8(formatter.Format(request)) };
157+
return new() { Name = "request.json", Contents = ByteString.CopyFromUtf8(formatter.Format(request)) };
222158
}
223159

224160
private static Plugin.File RequestToProtobufFile(GenerateRequest request)
225161
{
226162
request.PluginOptions = GetOptionsWithoutDebugRequest(request);
227-
return new Plugin.File { Name = "request.message", Contents = request.ToByteString() };
163+
return new() { Name = "request.message", Contents = request.ToByteString() };
228164
}
229165
}

CodeGenerator/Generators/EnumsGen.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,28 @@ public static class {{name}}Extensions
3131
.Select(v => $"[\"{v}\"] = {name}.{v.ToPascalCase()}")
3232
.JoinByComma()}}
3333
};
34+
35+
private static readonly Dictionary<{{name}}, string> EnumToString = new Dictionary<{{name}}, string>()
36+
{
37+
[{{name}}.Invalid] = string.Empty,
38+
{{possibleValues
39+
.Select(v => $"[{name}.{v.ToPascalCase()}] = \"{v}\"")
40+
.JoinByComma()}}
41+
};
3442
3543
public static {{name}} To{{name}}(this string me)
3644
{
3745
return StringToEnum[me];
3846
}
3947
40-
public static {{name}}[] To{{name}}Arr(this string me)
48+
public static string Stringify(this {{name}} me)
49+
{
50+
return EnumToString[me];
51+
}
52+
53+
public static HashSet<{{name}}> To{{name}}Set(this string me)
4154
{
42-
return me.Split(',').ToList().Select(v => StringToEnum[v]).ToArray();
55+
return new HashSet<{{name}}>(me.Split(',').ToList().Select(v => StringToEnum[v]));
4356
}
4457
}
4558
""")!;

CodeGenerator/Generators/ModelsGen.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Plugin;
33
using SqlcGenCsharp.Drivers;
44
using System.Collections.Generic;
5-
using System.Collections.Immutable;
65
using System.Linq;
76
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
87

@@ -17,7 +16,6 @@ internal class ModelsGen(DbDriver dbDriver, string namespaceName)
1716

1817
private DataClassesGen DataClassesGen { get; } = new(dbDriver);
1918

20-
2119
private EnumsGen EnumsGen { get; } = new(dbDriver);
2220

2321
public File GenerateFile(
@@ -59,8 +57,12 @@ private MemberDeclarationSyntax[] GenerateEnums(Dictionary<string, Dictionary<st
5957
{
6058
return s.Value.SelectMany(e =>
6159
{
62-
var enumName = e.Value.Name.ToModelName(s.Key, dbDriver.DefaultSchema);
63-
return EnumsGen.Generate(enumName, e.Value.Vals);
60+
if (dbDriver is EnumDbDriver enumDbDriver)
61+
{
62+
var enumName = enumDbDriver.EnumToModelName(s.Key, e.Value);
63+
return EnumsGen.Generate(enumName, e.Value.Vals);
64+
}
65+
return [];
6466
});
6567
}).ToArray();
6668
}

CodeGenerator/Generators/QueriesGen.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Linq;
7+
using System.Text.RegularExpressions;
78
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
89

910

1011
namespace SqlcGenCsharp.Generators;
1112

12-
internal class QueriesGen(DbDriver dbDriver, string namespaceName)
13+
internal partial class QueriesGen(DbDriver dbDriver, string namespaceName)
1314
{
1415
private static readonly string[] ResharperDisables =
1516
[
@@ -132,16 +133,22 @@ private IEnumerable<MemberDeclarationSyntax> GetMembersForSingleQuery(Query quer
132133

133134
private MemberDeclarationSyntax? GetQueryTextConstant(Query query)
134135
{
135-
var transformQueryText = dbDriver.TransformQueryText(query);
136-
if (transformQueryText == string.Empty)
136+
var transformedQueryText = dbDriver.TransformQueryText(query);
137+
if (transformedQueryText == string.Empty)
137138
return null;
139+
140+
var singleLineQueryText = LongWhitespaceRegex().Replace(transformedQueryText, " ");
138141
return ParseMemberDeclaration(
139142
$"""
140-
private const string {ClassMember.Sql.Name(query.Name)} = "{transformQueryText}";
143+
private const string {ClassMember.Sql.Name(query.Name)} = "{singleLineQueryText}";
141144
""")!
142145
.AppendNewLine();
143146
}
144147

148+
149+
[GeneratedRegex(@"\s{1,}")]
150+
private static partial Regex LongWhitespaceRegex();
151+
145152
private MemberDeclarationSyntax AddMethodDeclaration(Query query)
146153
{
147154
var queryTextConstant = ClassMember.Sql.Name(query.Name);

CodegenTests/CodegenSchemaTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ public void TestSchemaScopedEnum()
4747
var expected = new HashSet<string>
4848
{
4949
"DummySchemaDummyTable",
50-
"DummySchemaDummyTableDummyColumn",
51-
"DummySchemaDummyTableDummyColumnExtensions"
50+
"DummyTableDummyColumn",
51+
"DummyTableDummyColumnExtensions"
5252
};
5353
var actual = GetMemberNames(modelsCode);
5454
Assert.That(actual.IsSupersetOf(expected));

CodegenTests/CodegenTypeOverrideTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Plugin;
33
using SqlcGenCsharp;
44
using System.Text;
5-
using System.Xml;
65

76
namespace CodegenTests;
87

0 commit comments

Comments
 (0)