Skip to content

Commit 6a50da7

Browse files
[release] feat: allow override for SQLite integer and text types to bool (#332)
* feat: allow override for SQLite integer and text types to bool * fix: remove redundant param for SqlMapper delegate
1 parent 543a9cc commit 6a50da7

File tree

29 files changed

+621
-159
lines changed

29 files changed

+621
-159
lines changed

Drivers/SqliteDriver.cs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,38 @@ public sealed partial class SqliteDriver(
2727
{
2828
{"blob", new()}
2929
},
30-
readerFn: (ordinal, _) => $"reader.GetFieldValue<byte[]>({ordinal})"
30+
readerFn: (ordinal, _) => $"{Variable.Reader.AsVarName()}.GetFieldValue<byte[]>({ordinal})"
3131
),
3232
["string"] = new(
3333
new()
3434
{
3535
{"text", new()}
3636
},
37-
readerFn: (ordinal, _) => $"reader.GetString({ordinal})"
37+
readerFn: (ordinal, _) => $"{Variable.Reader.AsVarName()}.GetString({ordinal})"
3838
),
3939
["int"] = new(
4040
new()
4141
{
4242
{ "integer", new() },
4343
{ "integernotnulldefaultunixepoch", new() }
4444
},
45-
readerFn: (ordinal, _) => $"reader.GetInt32({ordinal})",
45+
readerFn: (ordinal, _) => $"{Variable.Reader.AsVarName()}.GetInt32({ordinal})",
4646
convertFunc: x => $"Convert.ToInt32({x})"
4747
),
4848
["decimal"] = new(
4949
new()
5050
{
5151
{"real", new()}
5252
},
53-
readerFn: (ordinal, _) => $"reader.GetDecimal({ordinal})"
53+
readerFn: (ordinal, _) => $"{Variable.Reader.AsVarName()}.GetDecimal({ordinal})"
5454
),
5555
["DateTime"] = new(
5656
[],
5757
readerFn: (ordinal, dbType) =>
5858
{
59-
if (IntegerDbTypes.Contains(dbType))
60-
return $"DateTime.UnixEpoch.AddSeconds(reader.GetInt32({ordinal}))";
61-
return $"DateTime.Parse(reader.GetString({ordinal}))";
59+
if (IntegerDbTypes.Contains(dbType.ToLower()))
60+
return $"DateTimeOffset.FromUnixTimeSeconds({Variable.Reader.AsVarName()}.GetInt32({ordinal})).DateTime";
61+
return $"DateTime.Parse({Variable.Reader.AsVarName()}.GetString({ordinal}))";
6262
},
6363
writerFn: (el, dbType, notNull, isDapper, isLegacy) =>
6464
{
@@ -67,17 +67,53 @@ public sealed partial class SqliteDriver(
6767
if (IntegerDbTypes.Contains(dbType.ToLower()))
6868
return $"{el} != null ? (int?) new DateTimeOffset({elWithOptionalNull}.ToUniversalTime()).ToUnixTimeSeconds() : {nullValue}";
6969
return $"{el} != null ? {elWithOptionalNull}.ToString(\"{DateTimeStringFormat}\") : {nullValue}";
70+
},
71+
sqlMapper: "SqlMapper.AddTypeHandler(typeof(DateTime), new DateTimeTypeHandler());",
72+
sqlMapperImpl: DateTimeTypeHandler
73+
),
74+
["bool"] = new(
75+
[],
76+
readerFn: (ordinal, dbType) =>
77+
{
78+
var getFunc = IntegerDbTypes.Contains(dbType.ToLower()) ? "GetInt32" : "GetString";
79+
return $"Convert.ToBoolean({Variable.Reader.AsVarName()}.{getFunc}({ordinal}))";
80+
},
81+
writerFn: (el, dbType, notNull, isDapper, isLegacy) =>
82+
{
83+
var nullValue = isDapper ? "null" : "(object)DBNull.Value";
84+
var optionalCast = notNull ? string.Empty : "(int?)";
85+
var convertFunc = IntegerDbTypes.Contains(dbType.ToLower()) ? $"{optionalCast} Convert.ToInt32" : "Convert.ToString";
86+
return $"{el} != null ? {convertFunc}({el}) : {nullValue}";
7087
}
7188
),
7289
["object"] = new(
7390
new()
7491
{
7592
{ "any", new() }
7693
},
77-
readerFn: (ordinal, _) => $"reader.GetValue({ordinal})"
94+
readerFn: (ordinal, _) => $"{Variable.Reader.AsVarName()}.GetValue({ordinal})"
7895
)
7996
};
8097

98+
private static readonly SqlMapperImplFunc DateTimeTypeHandler = _ => $$"""
99+
private class DateTimeTypeHandler : SqlMapper.TypeHandler<DateTime>
100+
{
101+
public override DateTime Parse(object value)
102+
{
103+
if (value is string s)
104+
return DateTime.Parse(s);
105+
if (value is long l)
106+
return DateTimeOffset.FromUnixTimeSeconds(l).DateTime;
107+
throw new DataException($"Cannot convert {value?.GetType()} to DateTime");
108+
}
109+
110+
public override void SetValue(IDbDataParameter parameter, DateTime value)
111+
{
112+
parameter.Value = value;
113+
}
114+
}
115+
""";
116+
81117
public override string TransactionClassName => "SqliteTransaction";
82118

83119
public override ISet<string> GetUsingDirectivesForQueries()

end2end/EndToEndScaffold/Templates/SqliteTests.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,32 @@ public static class SqliteTests
1010
{
1111
Impl = $$"""
1212
[Test]
13-
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
14-
[TestCase(null, null, null, new byte[] { }, null, null)]
15-
[TestCase(null, null, null, null, null, null)]
13+
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, true, false, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
14+
[TestCase(null, null, null, new byte[] { }, null, null, null, null)]
15+
[TestCase(null, null, null, null, null, null, null, null)]
1616
public async Task TestSqliteTypes(
1717
int? cInteger,
1818
decimal? cReal,
1919
string cText,
2020
byte[] cBlob,
21-
DateTime cTextDatetimeOverride,
21+
bool? cTextBoolOverride,
22+
bool? cIntegerBoolOverride,
23+
DateTime? cTextDatetimeOverride,
2224
DateTime? cIntegerDatetimeOverride)
2325
{
26+
if (cTextDatetimeOverride.HasValue && cTextDatetimeOverride.Value.Kind != DateTimeKind.Utc)
27+
cTextDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride.Value, DateTimeKind.Utc);
2428
if (cIntegerDatetimeOverride.HasValue && cIntegerDatetimeOverride.Value.Kind != DateTimeKind.Utc)
25-
cIntegerDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride, DateTimeKind.Utc);
29+
cIntegerDatetimeOverride = DateTime.SpecifyKind(cIntegerDatetimeOverride.Value, DateTimeKind.Utc);
30+
2631
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs
2732
{
2833
CInteger = cInteger,
2934
CReal = cReal,
3035
CText = cText,
3136
CBlob = cBlob,
37+
CTextBoolOverride = cTextBoolOverride,
38+
CIntegerBoolOverride = cIntegerBoolOverride,
3239
CTextDatetimeOverride = cTextDatetimeOverride,
3340
CIntegerDatetimeOverride = cIntegerDatetimeOverride
3441
});
@@ -39,6 +46,8 @@ await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs
3946
CReal = cReal,
4047
CText = cText,
4148
CBlob = cBlob,
49+
CTextBoolOverride = cTextBoolOverride,
50+
CIntegerBoolOverride = cIntegerBoolOverride,
4251
CTextDatetimeOverride = cTextDatetimeOverride,
4352
CIntegerDatetimeOverride = cIntegerDatetimeOverride
4453
};
@@ -51,6 +60,8 @@ void AssertSingularEquals(QuerySql.GetSqliteTypesRow x, QuerySql.GetSqliteTypesR
5160
Assert.That(x.CReal, Is.EqualTo(y.CReal));
5261
Assert.That(x.CText, Is.EqualTo(y.CText));
5362
Assert.That(x.CBlob, Is.EqualTo(y.CBlob));
63+
Assert.That(x.CTextBoolOverride, Is.EqualTo(y.CTextBoolOverride));
64+
Assert.That(x.CIntegerBoolOverride, Is.EqualTo(y.CIntegerBoolOverride));
5465
AssertDateTimeEquals(x.CTextDatetimeOverride, y.CTextDatetimeOverride);
5566
AssertDateTimeEquals(x.CIntegerDatetimeOverride, y.CIntegerDatetimeOverride);
5667
}

end2end/EndToEndTests/SqliteDapperTester.generated.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,20 +328,24 @@ void AssertSingularEquals(QuerySql.GetAuthorByNamePatternRow x, QuerySql.GetAuth
328328
}
329329

330330
[Test]
331-
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332-
[TestCase(null, null, null, new byte[] { }, null, null)]
333-
[TestCase(null, null, null, null, null, null)]
334-
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, DateTime cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
331+
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, true, false, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332+
[TestCase(null, null, null, new byte[] { }, null, null, null, null)]
333+
[TestCase(null, null, null, null, null, null, null, null)]
334+
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, bool? cTextBoolOverride, bool? cIntegerBoolOverride, DateTime? cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
335335
{
336+
if (cTextDatetimeOverride.HasValue && cTextDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337+
cTextDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride.Value, DateTimeKind.Utc);
336338
if (cIntegerDatetimeOverride.HasValue && cIntegerDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337-
cIntegerDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride, DateTimeKind.Utc);
338-
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339+
cIntegerDatetimeOverride = DateTime.SpecifyKind(cIntegerDatetimeOverride.Value, DateTimeKind.Utc);
340+
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextBoolOverride = cTextBoolOverride, CIntegerBoolOverride = cIntegerBoolOverride, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339341
var expected = new QuerySql.GetSqliteTypesRow
340342
{
341343
CInteger = cInteger,
342344
CReal = cReal,
343345
CText = cText,
344346
CBlob = cBlob,
347+
CTextBoolOverride = cTextBoolOverride,
348+
CIntegerBoolOverride = cIntegerBoolOverride,
345349
CTextDatetimeOverride = cTextDatetimeOverride,
346350
CIntegerDatetimeOverride = cIntegerDatetimeOverride
347351
};
@@ -353,6 +357,8 @@ void AssertSingularEquals(QuerySql.GetSqliteTypesRow x, QuerySql.GetSqliteTypesR
353357
Assert.That(x.CReal, Is.EqualTo(y.CReal));
354358
Assert.That(x.CText, Is.EqualTo(y.CText));
355359
Assert.That(x.CBlob, Is.EqualTo(y.CBlob));
360+
Assert.That(x.CTextBoolOverride, Is.EqualTo(y.CTextBoolOverride));
361+
Assert.That(x.CIntegerBoolOverride, Is.EqualTo(y.CIntegerBoolOverride));
356362
AssertDateTimeEquals(x.CTextDatetimeOverride, y.CTextDatetimeOverride);
357363
AssertDateTimeEquals(x.CIntegerDatetimeOverride, y.CIntegerDatetimeOverride);
358364
}

end2end/EndToEndTests/SqliteTester.generated.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,20 +328,24 @@ void AssertSingularEquals(QuerySql.GetAuthorByNamePatternRow x, QuerySql.GetAuth
328328
}
329329

330330
[Test]
331-
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332-
[TestCase(null, null, null, new byte[] { }, null, null)]
333-
[TestCase(null, null, null, null, null, null)]
334-
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, DateTime cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
331+
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, true, false, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332+
[TestCase(null, null, null, new byte[] { }, null, null, null, null)]
333+
[TestCase(null, null, null, null, null, null, null, null)]
334+
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, bool? cTextBoolOverride, bool? cIntegerBoolOverride, DateTime? cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
335335
{
336+
if (cTextDatetimeOverride.HasValue && cTextDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337+
cTextDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride.Value, DateTimeKind.Utc);
336338
if (cIntegerDatetimeOverride.HasValue && cIntegerDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337-
cIntegerDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride, DateTimeKind.Utc);
338-
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339+
cIntegerDatetimeOverride = DateTime.SpecifyKind(cIntegerDatetimeOverride.Value, DateTimeKind.Utc);
340+
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextBoolOverride = cTextBoolOverride, CIntegerBoolOverride = cIntegerBoolOverride, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339341
var expected = new QuerySql.GetSqliteTypesRow
340342
{
341343
CInteger = cInteger,
342344
CReal = cReal,
343345
CText = cText,
344346
CBlob = cBlob,
347+
CTextBoolOverride = cTextBoolOverride,
348+
CIntegerBoolOverride = cIntegerBoolOverride,
345349
CTextDatetimeOverride = cTextDatetimeOverride,
346350
CIntegerDatetimeOverride = cIntegerDatetimeOverride
347351
};
@@ -353,6 +357,8 @@ void AssertSingularEquals(QuerySql.GetSqliteTypesRow x, QuerySql.GetSqliteTypesR
353357
Assert.That(x.CReal, Is.EqualTo(y.CReal));
354358
Assert.That(x.CText, Is.EqualTo(y.CText));
355359
Assert.That(x.CBlob, Is.EqualTo(y.CBlob));
360+
Assert.That(x.CTextBoolOverride, Is.EqualTo(y.CTextBoolOverride));
361+
Assert.That(x.CIntegerBoolOverride, Is.EqualTo(y.CIntegerBoolOverride));
356362
AssertDateTimeEquals(x.CTextDatetimeOverride, y.CTextDatetimeOverride);
357363
AssertDateTimeEquals(x.CIntegerDatetimeOverride, y.CIntegerDatetimeOverride);
358364
}

end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,20 +328,24 @@ void AssertSingularEquals(QuerySql.GetAuthorByNamePatternRow x, QuerySql.GetAuth
328328
}
329329

330330
[Test]
331-
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332-
[TestCase(null, null, null, new byte[] { }, null, null)]
333-
[TestCase(null, null, null, null, null, null)]
334-
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, DateTime cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
331+
[TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 }, true, false, "2020-01-01 14:15:16", "2025-01-01 17:18:19")]
332+
[TestCase(null, null, null, new byte[] { }, null, null, null, null)]
333+
[TestCase(null, null, null, null, null, null, null, null)]
334+
public async Task TestSqliteTypes(int? cInteger, decimal? cReal, string cText, byte[] cBlob, bool? cTextBoolOverride, bool? cIntegerBoolOverride, DateTime? cTextDatetimeOverride, DateTime? cIntegerDatetimeOverride)
335335
{
336+
if (cTextDatetimeOverride.HasValue && cTextDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337+
cTextDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride.Value, DateTimeKind.Utc);
336338
if (cIntegerDatetimeOverride.HasValue && cIntegerDatetimeOverride.Value.Kind != DateTimeKind.Utc)
337-
cIntegerDatetimeOverride = DateTime.SpecifyKind(cTextDatetimeOverride, DateTimeKind.Utc);
338-
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339+
cIntegerDatetimeOverride = DateTime.SpecifyKind(cIntegerDatetimeOverride.Value, DateTimeKind.Utc);
340+
await QuerySql.InsertSqliteTypes(new QuerySql.InsertSqliteTypesArgs { CInteger = cInteger, CReal = cReal, CText = cText, CBlob = cBlob, CTextBoolOverride = cTextBoolOverride, CIntegerBoolOverride = cIntegerBoolOverride, CTextDatetimeOverride = cTextDatetimeOverride, CIntegerDatetimeOverride = cIntegerDatetimeOverride });
339341
var expected = new QuerySql.GetSqliteTypesRow
340342
{
341343
CInteger = cInteger,
342344
CReal = cReal,
343345
CText = cText,
344346
CBlob = cBlob,
347+
CTextBoolOverride = cTextBoolOverride,
348+
CIntegerBoolOverride = cIntegerBoolOverride,
345349
CTextDatetimeOverride = cTextDatetimeOverride,
346350
CIntegerDatetimeOverride = cIntegerDatetimeOverride
347351
};
@@ -353,6 +357,8 @@ void AssertSingularEquals(QuerySql.GetSqliteTypesRow x, QuerySql.GetSqliteTypesR
353357
Assert.That(x.CReal, Is.EqualTo(y.CReal));
354358
Assert.That(x.CText, Is.EqualTo(y.CText));
355359
Assert.That(x.CBlob, Is.EqualTo(y.CBlob));
360+
Assert.That(x.CTextBoolOverride, Is.EqualTo(y.CTextBoolOverride));
361+
Assert.That(x.CIntegerBoolOverride, Is.EqualTo(y.CIntegerBoolOverride));
356362
AssertDateTimeEquals(x.CTextDatetimeOverride, y.CTextDatetimeOverride);
357363
AssertDateTimeEquals(x.CIntegerDatetimeOverride, y.CIntegerDatetimeOverride);
358364
}

0 commit comments

Comments
 (0)