Skip to content

Commit d154e40

Browse files
[release] add timestamp,date & datetime data types support for mysql and postgres (#95)
1 parent 02d68a2 commit d154e40

File tree

11 files changed

+64
-39
lines changed

11 files changed

+64
-39
lines changed

Drivers/DbDriver.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ public abstract class DbDriver(DotnetFramework dotnetFramework)
1313
{
1414
public DotnetFramework DotnetFramework { get; } = dotnetFramework;
1515

16+
private HashSet<string> CsharpPrimitives { get; } = ["long", "double", "int", "float", "bool", "DateTime"];
17+
1618
public virtual UsingDirectiveSyntax[] GetUsingDirectives()
1719
{
1820
return
1921
[
2022
UsingDirective(ParseName("System.Collections.Generic")),
21-
UsingDirective(ParseName("System.Threading.Tasks"))
23+
UsingDirective(ParseName("System.Threading.Tasks")),
24+
UsingDirective(ParseName("System"))
2225
];
2326
}
2427

@@ -73,9 +76,8 @@ public abstract MemberDeclarationSyntax ManyDeclare(string sqlTextConstant, stri
7376

7477
public abstract MemberDeclarationSyntax ExecDeclare(string text, string argInterface, Query query);
7578

76-
public static bool IsCsharpPrimitive(string csharpType)
79+
public bool IsCsharpPrimitive(string csharpType)
7780
{
78-
var csharpPrimitives = new HashSet<string> { "long", "double", "int", "float", "bool" };
79-
return csharpPrimitives.Contains(csharpType.Replace("?", ""));
81+
return CsharpPrimitives.Contains(csharpType.Replace("?", ""));
8082
}
8183
}

Drivers/Generators/CommonGen.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ string GetNullExpression(Column column)
5555
var csharpType = dbDriver.GetColumnType(column);
5656
if (csharpType == "string")
5757
return "string.Empty";
58-
return !dbDriver.DotnetFramework.LatestDotnetSupported() && DbDriver.IsCsharpPrimitive(csharpType)
58+
return !dbDriver.DotnetFramework.LatestDotnetSupported() && dbDriver.IsCsharpPrimitive(csharpType)
5959
? $"({csharpType}) null"
6060
: "null";
6161
}

Drivers/MySqlConnectorDriver.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@ public partial class MySqlConnectorDriver(DotnetFramework dotnetFramework) : DbD
2828
]),
2929
("string", ordinal => $"reader.GetString({ordinal})", [
3030
"char",
31-
"date",
32-
"datetime",
3331
"decimal",
3432
"longtext",
3533
"mediumtext",
3634
"text",
3735
"time",
38-
"timestamp",
3936
"tinytext",
4037
"varchar"
4138
]),
39+
("DateTime", ordinal => $"reader.GetDateTime({ordinal})", [
40+
"date",
41+
"datetime",
42+
"timestamp"
43+
]),
4244
("int", ordinal => $"reader.GetInt32({ordinal})", [
4345
"int",
4446
"mediumint",

Drivers/NpgsqlDriver.cs

+6-3
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,21 @@ public class NpgsqlDriver(DotnetFramework dotnetFramework) : DbDriver(dotnetFram
2929
("string", ordinal => $"reader.GetString({ordinal})",
3030
[
3131
"char",
32-
"date",
33-
"datetime",
32+
3433
"longtext",
3534
"mediumtext",
3635
"text",
3736
"bpchar",
3837
"time",
39-
"timestamp",
4038
"tinytext",
4139
"varchar",
4240
"pg_catalog.varchar"
4341
]),
42+
("DateTime", ordinal => $"reader.GetDateTime({ordinal})", [
43+
"date",
44+
"datetime",
45+
"timestamp"
46+
]),
4447
("object", ordinal => $"reader.GetString({ordinal})", ["json"]),
4548
("int", ordinal => $"reader.GetInt32({ordinal})", [
4649
"integer",

EndToEndTests/MySqlConnectorTests.cs

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ await QuerySql.CreateAuthor(new QuerySql.CreateAuthorArgs
4444
Bio: DataGenerator.DrSeussQuote
4545
}
4646
]);
47+
48+
foreach (var a in actualAuthors)
49+
{
50+
Assert.That(a.Created >= DateTime.Now.Subtract(TimeSpan.FromSeconds(30)) && a.Created < DateTime.Now);
51+
}
4752
}
4853

4954
[Test]

EndToEndTests/NpgsqlTests.cs

+5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ await QuerySql.CreateAuthor(new QuerySql.CreateAuthorArgs
4747
Bio: DataGenerator.DrSeussQuote
4848
}
4949
]);
50+
51+
foreach (var a in actualAuthors)
52+
{
53+
Assert.That(a.Created >= DateTime.Now.Subtract(TimeSpan.FromSeconds(30)) && a.Created < DateTime.Now);
54+
}
5055
}
5156

5257
[Test]

MySqlConnectorExample/QuerySql.cs

+12-10
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
// ReSharper disable InconsistentNaming
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
7+
using System;
78
using MySqlConnector;
89

910
namespace MySqlConnectorExampleGen;
1011
public class QuerySql(string connectionString)
1112
{
12-
private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1";
13-
public readonly record struct GetAuthorRow(long Id, string Name, string? Bio);
13+
private const string GetAuthorSql = "SELECT id, name, bio, created FROM authors WHERE name = @name LIMIT 1";
14+
public readonly record struct GetAuthorRow(long Id, string Name, string? Bio, DateTime Created);
1415
public readonly record struct GetAuthorArgs(string Name);
1516
public async Task<GetAuthorRow?> GetAuthor(GetAuthorArgs args)
1617
{
@@ -26,16 +27,17 @@ public class QuerySql(string connectionString)
2627
{
2728
Id = reader.GetInt64(0),
2829
Name = reader.GetString(1),
29-
Bio = reader.IsDBNull(2) ? null : reader.GetString(2)
30+
Bio = reader.IsDBNull(2) ? null : reader.GetString(2),
31+
Created = reader.GetDateTime(3)
3032
};
3133
}
3234

3335
return null;
3436
}
3537
}
3638

37-
private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name";
38-
public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio);
39+
private const string ListAuthorsSql = "SELECT id, name, bio, created FROM authors ORDER BY name";
40+
public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio, DateTime Created);
3941
public async Task<List<ListAuthorsRow>> ListAuthors()
4042
{
4143
{
@@ -46,7 +48,7 @@ public async Task<List<ListAuthorsRow>> ListAuthors()
4648
var result = new List<ListAuthorsRow>();
4749
while (await reader.ReadAsync())
4850
{
49-
result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) });
51+
result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Created = reader.GetDateTime(3) });
5052
}
5153

5254
return result;
@@ -121,7 +123,7 @@ public async Task TruncateAuthors()
121123
}
122124

123125
private const string TestSql = "SELECT c_bit, c_tinyint, c_bool, c_boolean, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_serial, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_date, c_time, c_datetime, c_timestamp, c_year, c_char, c_nchar, c_national_char, c_varchar, c_binary, c_varbinary, c_tinyblob, c_tinytext, c_blob, c_text, c_mediumblob, c_mediumtext, c_longblob, c_longtext, c_json FROM node_mysql_types LIMIT 1";
124-
public readonly record struct TestRow(byte[]? C_bit, int? C_tinyint, int? C_bool, int? C_boolean, int? C_smallint, int? C_mediumint, int? C_int, int? C_integer, long? C_bigint, long C_serial, string? C_decimal, string? C_dec, string? C_numeric, string? C_fixed, double? C_float, double? C_double, double? C_double_precision, string? C_date, string? C_time, string? C_datetime, string? C_timestamp, int? C_year, string? C_char, string? C_nchar, string? C_national_char, string? C_varchar, byte[]? C_binary, byte[]? C_varbinary, byte[]? C_tinyblob, string? C_tinytext, byte[]? C_blob, string? C_text, byte[]? C_mediumblob, string? C_mediumtext, byte[]? C_longblob, string? C_longtext, object? C_json);
126+
public readonly record struct TestRow(byte[]? C_bit, int? C_tinyint, int? C_bool, int? C_boolean, int? C_smallint, int? C_mediumint, int? C_int, int? C_integer, long? C_bigint, long C_serial, string? C_decimal, string? C_dec, string? C_numeric, string? C_fixed, double? C_float, double? C_double, double? C_double_precision, DateTime? C_date, string? C_time, DateTime? C_datetime, DateTime? C_timestamp, int? C_year, string? C_char, string? C_nchar, string? C_national_char, string? C_varchar, byte[]? C_binary, byte[]? C_varbinary, byte[]? C_tinyblob, string? C_tinytext, byte[]? C_blob, string? C_text, byte[]? C_mediumblob, string? C_mediumtext, byte[]? C_longblob, string? C_longtext, object? C_json);
125127
public async Task<TestRow?> Test()
126128
{
127129
{
@@ -150,10 +152,10 @@ public async Task TruncateAuthors()
150152
C_float = reader.IsDBNull(14) ? null : reader.GetDouble(14),
151153
C_double = reader.IsDBNull(15) ? null : reader.GetDouble(15),
152154
C_double_precision = reader.IsDBNull(16) ? null : reader.GetDouble(16),
153-
C_date = reader.IsDBNull(17) ? null : reader.GetString(17),
155+
C_date = reader.IsDBNull(17) ? null : reader.GetDateTime(17),
154156
C_time = reader.IsDBNull(18) ? null : reader.GetString(18),
155-
C_datetime = reader.IsDBNull(19) ? null : reader.GetString(19),
156-
C_timestamp = reader.IsDBNull(20) ? null : reader.GetString(20),
157+
C_datetime = reader.IsDBNull(19) ? null : reader.GetDateTime(19),
158+
C_timestamp = reader.IsDBNull(20) ? null : reader.GetDateTime(20),
157159
C_year = reader.IsDBNull(21) ? null : reader.GetInt32(21),
158160
C_char = reader.IsDBNull(22) ? null : reader.GetString(22),
159161
C_nchar = reader.IsDBNull(23) ? null : reader.GetString(23),

NpgsqlExample/QuerySql.cs

+15-12
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
// ReSharper disable InconsistentNaming
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
7+
using System;
78
using Npgsql;
89

910
namespace NpgsqlExampleGen;
1011
public class QuerySql(string connectionString)
1112
{
12-
private const string GetAuthorSql = "SELECT id, name, bio FROM authors WHERE name = @name LIMIT 1";
13-
public readonly record struct GetAuthorRow(long Id, string Name, string? Bio);
13+
private const string GetAuthorSql = "SELECT id, name, bio, created FROM authors WHERE name = @name LIMIT 1";
14+
public readonly record struct GetAuthorRow(long Id, string Name, string? Bio, DateTime Created);
1415
public readonly record struct GetAuthorArgs(string Name);
1516
public async Task<GetAuthorRow?> GetAuthor(GetAuthorArgs args)
1617
{
@@ -25,16 +26,17 @@ public class QuerySql(string connectionString)
2526
{
2627
Id = reader.GetInt64(0),
2728
Name = reader.GetString(1),
28-
Bio = reader.IsDBNull(2) ? null : reader.GetString(2)
29+
Bio = reader.IsDBNull(2) ? null : reader.GetString(2),
30+
Created = reader.GetDateTime(3)
2931
};
3032
}
3133

3234
return null;
3335
}
3436
}
3537

36-
private const string ListAuthorsSql = "SELECT id, name, bio FROM authors ORDER BY name";
37-
public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio);
38+
private const string ListAuthorsSql = "SELECT id, name, bio, created FROM authors ORDER BY name";
39+
public readonly record struct ListAuthorsRow(long Id, string Name, string? Bio, DateTime Created);
3840
public async Task<List<ListAuthorsRow>> ListAuthors()
3941
{
4042
{
@@ -44,15 +46,15 @@ public async Task<List<ListAuthorsRow>> ListAuthors()
4446
var result = new List<ListAuthorsRow>();
4547
while (await reader.ReadAsync())
4648
{
47-
result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2) });
49+
result.Add(new ListAuthorsRow { Id = reader.GetInt64(0), Name = reader.GetString(1), Bio = reader.IsDBNull(2) ? null : reader.GetString(2), Created = reader.GetDateTime(3) });
4850
}
4951

5052
return result;
5153
}
5254
}
5355

54-
private const string CreateAuthorSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id, name, bio";
55-
public readonly record struct CreateAuthorRow(long Id, string Name, string? Bio);
56+
private const string CreateAuthorSql = "INSERT INTO authors (name, bio) VALUES (@name, @bio) RETURNING id, name, bio, created";
57+
public readonly record struct CreateAuthorRow(long Id, string Name, string? Bio, DateTime Created);
5658
public readonly record struct CreateAuthorArgs(string Name, string? Bio);
5759
public async Task<CreateAuthorRow?> CreateAuthor(CreateAuthorArgs args)
5860
{
@@ -68,7 +70,8 @@ public async Task<List<ListAuthorsRow>> ListAuthors()
6870
{
6971
Id = reader.GetInt64(0),
7072
Name = reader.GetString(1),
71-
Bio = reader.IsDBNull(2) ? null : reader.GetString(2)
73+
Bio = reader.IsDBNull(2) ? null : reader.GetString(2),
74+
Created = reader.GetDateTime(3)
7275
};
7376
}
7477

@@ -132,7 +135,7 @@ public async Task<long> UpdateAuthors(UpdateAuthorsArgs args)
132135
}
133136

134137
private const string TestSql = "SELECT c_bit, c_smallint, c_boolean, c_integer, c_bigint, c_serial, c_decimal, c_numeric, c_real, c_double_precision, c_date, c_time, c_timestamp, c_char, c_varchar, c_character_varying, c_bytea, c_text, c_json FROM node_postgres_types LIMIT 1";
135-
public readonly record struct TestRow(byte[]? C_bit, int? C_smallint, bool? C_boolean, int? C_integer, int? C_bigint, long? C_serial, float? C_decimal, float? C_numeric, float? C_real, float? C_double_precision, string? C_date, string? C_time, string? C_timestamp, string? C_char, string? C_varchar, string? C_character_varying, byte[]? C_bytea, string? C_text, object? C_json);
138+
public readonly record struct TestRow(byte[]? C_bit, int? C_smallint, bool? C_boolean, int? C_integer, int? C_bigint, long? C_serial, float? C_decimal, float? C_numeric, float? C_real, float? C_double_precision, DateTime? C_date, string? C_time, DateTime? C_timestamp, string? C_char, string? C_varchar, string? C_character_varying, byte[]? C_bytea, string? C_text, object? C_json);
136139
public async Task<TestRow?> Test()
137140
{
138141
{
@@ -153,9 +156,9 @@ public async Task<long> UpdateAuthors(UpdateAuthorsArgs args)
153156
C_numeric = reader.IsDBNull(7) ? null : reader.GetFloat(7),
154157
C_real = reader.IsDBNull(8) ? null : reader.GetFloat(8),
155158
C_double_precision = reader.IsDBNull(9) ? null : reader.GetFloat(9),
156-
C_date = reader.IsDBNull(10) ? null : reader.GetString(10),
159+
C_date = reader.IsDBNull(10) ? null : reader.GetDateTime(10),
157160
C_time = reader.IsDBNull(11) ? null : reader.GetString(11),
158-
C_timestamp = reader.IsDBNull(12) ? null : reader.GetString(12),
161+
C_timestamp = reader.IsDBNull(12) ? null : reader.GetDateTime(12),
159162
C_char = reader.IsDBNull(13) ? null : reader.GetString(13),
160163
C_varchar = reader.IsDBNull(14) ? null : reader.GetString(14),
161164
C_character_varying = reader.IsDBNull(15) ? null : reader.GetString(15),

SqliteExample/QuerySql.cs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// ReSharper disable InconsistentNaming
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
7+
using System;
78
using Microsoft.Data.Sqlite;
89
using System;
910

examples/authors/mysql/schema.sql

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
CREATE TABLE authors (
2-
id BIGINT PRIMARY KEY AUTO_INCREMENT,
3-
name text NOT NULL,
4-
bio text
2+
id BIGINT PRIMARY KEY AUTO_INCREMENT,
3+
name TEXT NOT NULL,
4+
bio TEXT,
5+
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
56
);
67

78
CREATE TABLE node_mysql_types (

examples/authors/postgresql/schema.sql

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
CREATE TABLE authors (
2-
id BIGSERIAL PRIMARY KEY,
3-
name text NOT NULL,
4-
bio text
2+
id BIGSERIAL PRIMARY KEY,
3+
name TEXT NOT NULL,
4+
bio TEXT,
5+
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
56
);
67

78
CREATE TABLE node_postgres_types (

0 commit comments

Comments
 (0)