Skip to content

Commit 0238e11

Browse files
fix: columns mapping refactoring
1 parent 15d8c2e commit 0238e11

15 files changed

Lines changed: 251 additions & 340 deletions

File tree

Drivers/ColumnMapping.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ public class ColumnMapping(
1010
Func<int, string> readerFn,
1111
Func<int, string>? readerArrayFn = null,
1212
string? usingDirective = null,
13-
Func<string, bool, bool, string>? writerFn = null)
13+
Func<string, bool, bool, string>? writerFn = null,
14+
string? sqlMapper = null,
15+
string? sqlMapperImpl = null)
1416
{
17+
public Dictionary<string, DbTypeInfo> DbTypes { get; } = dbTypes;
1518
public Func<int, string> ReaderFn { get; } = readerFn;
1619
public Func<int, string>? ReaderArrayFn { get; } = readerArrayFn;
1720
public string? UsingDirective { get; } = usingDirective;
1821
public Func<string, bool, bool, string>? WriterFn { get; } = writerFn;
19-
public Dictionary<string, DbTypeInfo> DbTypes { get; } = dbTypes;
22+
public string? SqlMapper { get; } = sqlMapper;
23+
public string? SqlMapperImpl { get; } = sqlMapperImpl;
2024
}

Drivers/DbDriver.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ public override void SetValue(IDbDataParameter parameter, JsonElement value)
7373
}
7474
""";
7575

76-
protected abstract Dictionary<string, Tuple<string, string?>> KnownMappings { get; }
77-
7876
protected const string TransformQueryForSliceArgsImpl = """
7977
public static string TransformQueryForSliceArgs(string originalSql, int sliceSize, string paramName)
8078
{
@@ -160,21 +158,19 @@ public virtual ISet<string> GetUsingDirectivesForModels()
160158

161159
public virtual string[] GetConstructorStatements()
162160
{
163-
return [
164-
$"this.{Variable.ConnectionString.AsPropertyName()} = {Variable.ConnectionString.AsVarName()};"
165-
];
161+
return [$"this.{Variable.ConnectionString.AsPropertyName()} = {Variable.ConnectionString.AsVarName()};"];
166162
}
167163

168164
public virtual string[] GetTransactionConstructorStatements()
169165
{
170166
return [$"this.{Variable.Transaction.AsPropertyName()} = {Variable.Transaction.AsVarName()};"];
171167
}
172168

173-
protected virtual ISet<string> GetConfigureSqlMappings()
169+
protected ISet<string> GetConfigureSqlMappings()
174170
{
175-
return KnownMappings
176-
.Where(m => TypeExistsInQueries(m.Key))
177-
.Select(m => m.Value.Item1)
171+
return ColumnMappings
172+
.Where(m => TypeExistsInQueries(m.Key) && m.Value.SqlMapper is not null)
173+
.Select(m => m.Value.SqlMapper!)
178174
.ToHashSet();
179175
}
180176

@@ -184,9 +180,9 @@ public virtual MemberDeclarationSyntax[] GetMemberDeclarationsForUtils()
184180
if (!Options.UseDapper)
185181
return [.. memberDeclarations];
186182

187-
memberDeclarations.AddRange(KnownMappings
188-
.Where(m => TypeExistsInQueries(m.Key) && m.Value.Item2 is not null)
189-
.Select(m => ParseMemberDeclaration(m.Value.Item2!)!));
183+
memberDeclarations.AddRange(ColumnMappings
184+
.Where(m => TypeExistsInQueries(m.Key) && m.Value.SqlMapperImpl is not null)
185+
.Select(m => ParseMemberDeclaration(m.Value.SqlMapperImpl!)!));
190186

191187
return [.. memberDeclarations,
192188
ParseMemberDeclaration($$"""

Drivers/MySqlConnectorDriver.cs

Lines changed: 101 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -26,98 +26,98 @@ public partial class MySqlConnectorDriver(
2626
public override Dictionary<string, ColumnMapping> ColumnMappings { get; } =
2727
new()
2828
{
29-
["bool"] = new ColumnMapping(
30-
new Dictionary<string, DbTypeInfo>
29+
["bool"] = new(
30+
new()
3131
{
32-
{ "tinyint", new DbTypeInfo(Length: 1) }
32+
{ "tinyint", new(Length: 1) }
3333
},
3434
ordinal => $"reader.GetBoolean({ordinal})"
3535
),
36-
["short"] = new ColumnMapping(
37-
new Dictionary<string, DbTypeInfo>
36+
["short"] = new(
37+
new()
3838
{
39-
{ "tinyint", new DbTypeInfo() },
40-
{ "smallint", new DbTypeInfo() },
41-
{ "year", new DbTypeInfo() }
39+
{ "tinyint", new() },
40+
{ "smallint", new() },
41+
{ "year", new() }
4242
},
4343
ordinal => $"reader.GetInt16({ordinal})"
4444
),
45-
["long"] = new ColumnMapping(
46-
new Dictionary<string, DbTypeInfo>
45+
["long"] = new(
46+
new()
4747
{
48-
{ "bigint", new DbTypeInfo() }
48+
{ "bigint", new() }
4949
},
5050
ordinal => $"reader.GetInt64({ordinal})"
5151
),
5252
["byte"] = new ColumnMapping(
53-
new Dictionary<string, DbTypeInfo>
53+
new()
5454
{
55-
{ "bit", new DbTypeInfo() }
55+
{ "bit", new() }
5656
},
5757
ordinal => $"reader.GetFieldValue<byte>({ordinal})"
5858
),
59-
["byte[]"] = new ColumnMapping(
60-
new Dictionary<string, DbTypeInfo>
59+
["byte[]"] = new(
60+
new()
6161
{
62-
{ "binary", new DbTypeInfo() },
63-
{ "blob", new DbTypeInfo() },
64-
{ "longblob", new DbTypeInfo() },
65-
{ "mediumblob", new DbTypeInfo() },
66-
{ "tinyblob", new DbTypeInfo() },
67-
{ "varbinary", new DbTypeInfo() }
62+
{ "binary", new() },
63+
{ "blob", new() },
64+
{ "longblob", new() },
65+
{ "mediumblob", new() },
66+
{ "tinyblob", new() },
67+
{ "varbinary", new() }
6868
},
6969
ordinal => $"reader.GetFieldValue<byte[]>({ordinal})"
7070
),
71-
["string"] = new ColumnMapping(
72-
new Dictionary<string, DbTypeInfo>
71+
["string"] = new(
72+
new()
7373
{
74-
{ "char", new DbTypeInfo() },
75-
{ "longtext", new DbTypeInfo() },
76-
{ "mediumtext", new DbTypeInfo() },
77-
{ "text", new DbTypeInfo() },
78-
{ "time", new DbTypeInfo() },
79-
{ "tinytext", new DbTypeInfo() },
80-
{ "varchar", new DbTypeInfo() },
81-
{ "var_string", new DbTypeInfo() },
74+
{ "char", new() },
75+
{ "longtext", new() },
76+
{ "mediumtext", new() },
77+
{ "text", new() },
78+
{ "time", new() },
79+
{ "tinytext", new() },
80+
{ "varchar", new() },
81+
{ "var_string", new() },
8282
},
8383
ordinal => $"reader.GetString({ordinal})"
8484
),
85-
["DateTime"] = new ColumnMapping(
86-
new Dictionary<string, DbTypeInfo>
85+
["DateTime"] = new(
86+
new()
8787
{
88-
{ "date", new DbTypeInfo() },
89-
{ "datetime", new DbTypeInfo() },
90-
{ "timestamp", new DbTypeInfo() }
88+
{ "date", new() },
89+
{ "datetime", new() },
90+
{ "timestamp", new() }
9191
},
9292
ordinal => $"reader.GetDateTime({ordinal})"
9393
),
94-
["int"] = new ColumnMapping(
95-
new Dictionary<string, DbTypeInfo>
94+
["int"] = new(
95+
new()
9696
{
97-
{ "int", new DbTypeInfo() },
98-
{ "mediumint", new DbTypeInfo() }
97+
{ "int", new() },
98+
{ "mediumint", new() }
9999
},
100100
ordinal => $"reader.GetInt32({ordinal})"
101101
),
102-
["double"] = new ColumnMapping(
103-
new Dictionary<string, DbTypeInfo>
102+
["double"] = new(
103+
new()
104104
{
105-
{ "double", new DbTypeInfo() },
106-
{ "float", new DbTypeInfo() }
105+
{ "double", new() },
106+
{ "float", new() }
107107
},
108108
ordinal => $"reader.GetDouble({ordinal})"
109109
),
110-
["decimal"] = new ColumnMapping(
111-
new Dictionary<string, DbTypeInfo>
110+
["decimal"] = new(
111+
new()
112112
{
113-
{ "decimal", new DbTypeInfo() }
113+
{ "decimal", new() }
114114
},
115115
ordinal => $"reader.GetDecimal({ordinal})"
116116
),
117-
["JsonElement"] = new ColumnMapping(
118-
new Dictionary<string, DbTypeInfo>
117+
["JsonElement"] = new(
118+
new()
119119
{
120-
{ "json", new DbTypeInfo() }
120+
{ "json", new() }
121121
},
122122
readerFn: ordinal => $"JsonSerializer.Deserialize<JsonElement>(reader.GetString({ordinal}))",
123123
writerFn: (el, notNull, isDapper) =>
@@ -127,27 +127,19 @@ public partial class MySqlConnectorDriver(
127127
var nullValue = isDapper ? "null" : "(object)DBNull.Value";
128128
return $"{el}.HasValue ? {el}.Value.GetRawText() : {nullValue}";
129129
},
130-
usingDirective: "System.Text.Json"
130+
usingDirective: "System.Text.Json",
131+
sqlMapper: "SqlMapper.AddTypeHandler(typeof(JsonElement), new JsonElementTypeHandler());",
132+
sqlMapperImpl: JsonElementTypeHandler
131133
),
132-
["object"] = new ColumnMapping(
133-
new Dictionary<string, DbTypeInfo>
134+
["object"] = new(
135+
new()
134136
{
135-
{ "any", new DbTypeInfo() }
137+
{ "any", new() }
136138
},
137139
ordinal => $"reader.GetValue({ordinal})"
138140
)
139141
};
140142

141-
protected sealed override Dictionary<string, Tuple<string, string?>> KnownMappings { get; } = new()
142-
{
143-
{
144-
"JsonElement",
145-
new (
146-
$"SqlMapper.AddTypeHandler(typeof(JsonElement), new JsonElementTypeHandler());",
147-
JsonElementTypeHandler
148-
)
149-
}
150-
};
151143
public override string TransactionClassName => "MySqlTransaction";
152144

153145
public override ISet<string> GetUsingDirectivesForQueries()
@@ -365,7 +357,7 @@ public string GetCopyFromImpl(Query query, string queryTextConstant)
365357
{{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime>({{optionsVar}});
366358
{{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime?>({{optionsVar}});
367359
{{GetBoolAndByteConverters().JoinByNewLine()}}
368-
{{GetCsvNullConverters().JoinByNewLine()}}
360+
{{GetCsvNullConverters(query).JoinByNewLine()}}
369361
await {{csvWriterVar}}.WriteRecordsAsync({{Variable.Args.AsVarName()}});
370362
}
371363
@@ -388,90 +380,55 @@ public string GetCopyFromImpl(Query query, string queryTextConstant)
388380
await {{connectionVar}}.CloseAsync();
389381
}
390382
""";
383+
}
391384

392-
string GetCsvNullConverter(string csharpType)
393-
{
394-
var nullableCsharpType = AddNullableSuffixIfNeeded(csharpType, false);
395-
return $"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{nullableCsharpType}>({nullConverterFn});";
396-
}
385+
private readonly ISet<string> BoolAndByteTypes = new HashSet<string>
386+
{
387+
"bool",
388+
"byte",
389+
"byte[]"
390+
};
397391

398-
string[] GetCsvNullConverters()
392+
private ISet<string> GetCsvNullConverters(Query query)
393+
{
394+
var nullConverterFn = Variable.NullConverterFn.AsVarName();
395+
var converters = new HashSet<string>();
396+
foreach (var p in query.Params)
399397
{
400-
var primitivesConverters = new HashSet<string>()
401-
.AddRangeIf(
402-
[GetCsvNullConverter("short")],
403-
TypeExistsInQueries("short")
404-
)
405-
.AddRangeIf(
406-
[GetCsvNullConverter("int")],
407-
TypeExistsInQueries("int")
408-
)
409-
.AddRangeIf(
410-
[GetCsvNullConverter("long")],
411-
TypeExistsInQueries("long")
412-
)
413-
.AddRangeIf(
414-
[GetCsvNullConverter("float")],
415-
TypeExistsInQueries("float")
416-
)
417-
.AddRangeIf(
418-
[GetCsvNullConverter("decimal")],
419-
TypeExistsInQueries("decimal")
420-
)
421-
.AddRangeIf(
422-
[GetCsvNullConverter("double")],
423-
TypeExistsInQueries("double")
424-
)
425-
.AddRangeIf(
426-
[GetCsvNullConverter("DateTime")],
427-
TypeExistsInQueries("DateTime")
428-
)
429-
.AddRangeIf(
430-
[GetCsvNullConverter("string")],
431-
TypeExistsInQueries("string")
432-
)
433-
.AddRangeIf(
434-
[GetCsvNullConverter("JsonElement")],
435-
TypeExistsInQueries("JsonElement")
436-
)
437-
.AddRangeIf(
438-
[GetCsvNullConverter("object")],
439-
TypeExistsInQueries("object")
440-
);
441-
442-
var enumConverters = Enums.SelectMany(s =>
398+
var csharpType = GetCsharpTypeWithoutNullableSuffix(p.Column, query);
399+
if (!BoolAndByteTypes.Contains(csharpType) && TypeExistsInQueries(csharpType))
443400
{
444-
return s.Value.Select(e =>
445-
GetCsvNullConverter(e.Key.ToModelName(s.Key, DefaultSchema)));
446-
});
447-
448-
return [.. primitivesConverters, .. enumConverters];
401+
var nullableCsharpType = AddNullableSuffixIfNeeded(csharpType, false);
402+
converters.Add($"{Variable.CsvWriter.AsVarName()}.Context.TypeConverterCache.AddConverter<{nullableCsharpType}>({nullConverterFn});");
403+
}
449404
}
405+
return converters;
406+
}
450407

451-
ISet<string> GetBoolAndByteConverters()
452-
{
453-
return new HashSet<string>()
454-
.AddRangeIf(
455-
[
456-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("bool", true)}>(new Utils.{BoolToBitCsvConverter}());",
457-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("bool", false)}>(new Utils.{BoolToBitCsvConverter}());"
458-
],
459-
TypeExistsInQueries("bool")
460-
)
461-
.AddRangeIf(
462-
[
463-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte", true)}>(new Utils.{ByteCsvConverter}());",
464-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte", false)}>(new Utils.{ByteCsvConverter}());",
465-
],
466-
TypeExistsInQueries("byte")
467-
)
468-
.AddRangeIf(
469-
[
470-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte[]", true)}>(new Utils.{ByteArrayCsvConverter}());",
471-
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte[]", false)}>(new Utils.{ByteArrayCsvConverter}());",
472-
],
473-
TypeExistsInQueries("byte[]")
474-
);
475-
}
408+
private ISet<string> GetBoolAndByteConverters()
409+
{
410+
var csvWriterVar = Variable.CsvWriter.AsVarName();
411+
return new HashSet<string>()
412+
.AddRangeIf(
413+
[
414+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("bool", true)}>(new Utils.{BoolToBitCsvConverter}());",
415+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("bool", false)}>(new Utils.{BoolToBitCsvConverter}());"
416+
],
417+
TypeExistsInQueries("bool")
418+
)
419+
.AddRangeIf(
420+
[
421+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte", true)}>(new Utils.{ByteCsvConverter}());",
422+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte", false)}>(new Utils.{ByteCsvConverter}());",
423+
],
424+
TypeExistsInQueries("byte")
425+
)
426+
.AddRangeIf(
427+
[
428+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte[]", true)}>(new Utils.{ByteArrayCsvConverter}());",
429+
$"{csvWriterVar}.Context.TypeConverterCache.AddConverter<{AddNullableSuffixIfNeeded("byte[]", false)}>(new Utils.{ByteArrayCsvConverter}());",
430+
],
431+
TypeExistsInQueries("byte[]")
432+
);
476433
}
477434
}

0 commit comments

Comments
 (0)