Skip to content

Commit e2426e4

Browse files
feat: support postgres network data types in batch insert
1 parent eb87752 commit e2426e4

21 files changed

Lines changed: 699 additions & 67 deletions

File tree

Drivers/NpgsqlDriver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public NpgsqlDriver(
6969
{ "bpchar", new() },
7070
{ "tinytext", new() },
7171
{ "varchar", new() },
72-
{ "jsonpath", new(NpgsqlTypeOverride: "NpgsqlDbType.JsonPath") },
73-
{ "macaddr8", new(NpgsqlTypeOverride: "NpgsqlDbType.MacAddr8") }
72+
{ "jsonpath", new() },
73+
{ "macaddr8", new() }
7474
},
7575
readerFn: ordinal => $"reader.GetString({ordinal})",
7676
readerArrayFn: ordinal => $"reader.GetFieldValue<string[]>({ordinal})"

docs/04_Postgres.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ we consider support for the different data types separately for batch inserts an
5555
| path |||
5656
| polygon |||
5757
| circle |||
58-
| cidr || |
59-
| inet || |
60-
| macaddr || |
58+
| cidr || |
59+
| inet || |
60+
| macaddr || |
6161
| macaddr8 |||
6262
| tsvector |||
6363
| tsquery |||

end2end/EndToEndScaffold/Config.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public enum KnownTestType
4949
PostgresFloatingPointCopyFrom,
5050
PostgresDateTimeCopyFrom,
5151
PostgresGuidCopyFrom,
52+
PostgresNetworkCopyFrom,
5253
PostgresArrayCopyFrom,
5354
PostgresGeoDataTypes,
5455
PostgresGeoCopyFrom,
@@ -210,6 +211,7 @@ internal static class Config
210211
KnownTestType.PostgresDateTimeCopyFrom,
211212
KnownTestType.PostgresGuidCopyFrom,
212213
KnownTestType.PostgresArrayCopyFrom,
214+
KnownTestType.PostgresNetworkCopyFrom,
213215
]
214216
}
215217
},
@@ -253,6 +255,7 @@ internal static class Config
253255
KnownTestType.PostgresDateTimeCopyFrom,
254256
KnownTestType.PostgresGuidCopyFrom,
255257
KnownTestType.PostgresArrayCopyFrom,
258+
KnownTestType.PostgresNetworkCopyFrom
256259
]
257260
}
258261
},

end2end/EndToEndScaffold/Templates/PostgresTests.cs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,6 @@ public void TestPostgresInvalidJson()
525525
}
526526
"""
527527
},
528-
529528
[KnownTestType.PostgresNetworkDataTypes] = new TestImpl
530529
{
531530
Impl = $$"""
@@ -991,6 +990,66 @@ void AssertSingularEquals(QuerySql.GetPostgresTypesRow x, QuerySql.GetPostgresTy
991990
}
992991
}
993992
"""
993+
},
994+
[KnownTestType.PostgresNetworkCopyFrom] = new TestImpl
995+
{
996+
Impl = $$"""
997+
private static IEnumerable<TestCaseData> PostgresNetworkCopyFromTestCases
998+
{
999+
get
1000+
{
1001+
yield return new TestCaseData(
1002+
200,
1003+
new NpgsqlCidr("192.168.1.0/24"),
1004+
new IPAddress(new byte[] { 192, 168, 1, 1 }),
1005+
new PhysicalAddress(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 })
1006+
).SetName("Valid Network Copy From");
1007+
yield return new TestCaseData(
1008+
10,
1009+
null,
1010+
null,
1011+
null
1012+
).SetName("Null Network Copy From");
1013+
}
1014+
}
1015+
1016+
[Test]
1017+
[TestCaseSource(nameof(PostgresNetworkCopyFromTestCases))]
1018+
public async Task TestPostgresNetworkCopyFrom(
1019+
int batchSize,
1020+
NpgsqlCidr? cCidr,
1021+
IPAddress cInet,
1022+
PhysicalAddress cMacaddr)
1023+
{
1024+
var batchArgs = Enumerable.Range(0, batchSize)
1025+
.Select(_ => new QuerySql.InsertPostgresTypesBatchArgs
1026+
{
1027+
CCidr = cCidr,
1028+
CInet = cInet,
1029+
CMacaddr = cMacaddr
1030+
})
1031+
.ToList();
1032+
await QuerySql.InsertPostgresTypesBatch(batchArgs);
1033+
1034+
var expected = new QuerySql.GetPostgresTypesCntRow
1035+
{
1036+
Cnt = batchSize,
1037+
CCidr = cCidr,
1038+
CInet = cInet,
1039+
CMacaddr = cMacaddr
1040+
};
1041+
var actual = await QuerySql.GetPostgresTypesCnt();
1042+
AssertSingularEquals(expected, actual{{Consts.UnknownRecordValuePlaceholder}});
1043+
1044+
void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgresTypesCntRow y)
1045+
{
1046+
Assert.That(x.Cnt, Is.EqualTo(y.Cnt));
1047+
Assert.That(x.CCidr, Is.EqualTo(y.CCidr));
1048+
Assert.That(x.CInet, Is.EqualTo(y.CInet));
1049+
Assert.That(x.CMacaddr, Is.EqualTo(y.CMacaddr));
1050+
}
1051+
}
1052+
"""
9941053
}
9951054
};
9961055
}

end2end/EndToEndTests/NpgsqlDapperTester.generated.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,39 @@ void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgre
661661
}
662662
}
663663

664+
private static IEnumerable<TestCaseData> PostgresNetworkCopyFromTestCases
665+
{
666+
get
667+
{
668+
yield return new TestCaseData(200, new NpgsqlCidr("192.168.1.0/24"), new IPAddress(new byte[] { 192, 168, 1, 1 }), new PhysicalAddress(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 })).SetName("Valid Network Copy From");
669+
yield return new TestCaseData(10, null, null, null).SetName("Null Network Copy From");
670+
}
671+
}
672+
673+
[Test]
674+
[TestCaseSource(nameof(PostgresNetworkCopyFromTestCases))]
675+
public async Task TestPostgresNetworkCopyFrom(int batchSize, NpgsqlCidr? cCidr, IPAddress cInet, PhysicalAddress cMacaddr)
676+
{
677+
var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertPostgresTypesBatchArgs { CCidr = cCidr, CInet = cInet, CMacaddr = cMacaddr }).ToList();
678+
await QuerySql.InsertPostgresTypesBatch(batchArgs);
679+
var expected = new QuerySql.GetPostgresTypesCntRow
680+
{
681+
Cnt = batchSize,
682+
CCidr = cCidr,
683+
CInet = cInet,
684+
CMacaddr = cMacaddr
685+
};
686+
var actual = await QuerySql.GetPostgresTypesCnt();
687+
AssertSingularEquals(expected, actual);
688+
void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgresTypesCntRow y)
689+
{
690+
Assert.That(x.Cnt, Is.EqualTo(y.Cnt));
691+
Assert.That(x.CCidr, Is.EqualTo(y.CCidr));
692+
Assert.That(x.CInet, Is.EqualTo(y.CInet));
693+
Assert.That(x.CMacaddr, Is.EqualTo(y.CMacaddr));
694+
}
695+
}
696+
664697
[Test]
665698
[TestCase(100, new byte[] { 0x53, 0x56 })]
666699
[TestCase(10, new byte[] { })]

end2end/EndToEndTests/NpgsqlTester.generated.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,39 @@ void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgre
661661
}
662662
}
663663

664+
private static IEnumerable<TestCaseData> PostgresNetworkCopyFromTestCases
665+
{
666+
get
667+
{
668+
yield return new TestCaseData(200, new NpgsqlCidr("192.168.1.0/24"), new IPAddress(new byte[] { 192, 168, 1, 1 }), new PhysicalAddress(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 })).SetName("Valid Network Copy From");
669+
yield return new TestCaseData(10, null, null, null).SetName("Null Network Copy From");
670+
}
671+
}
672+
673+
[Test]
674+
[TestCaseSource(nameof(PostgresNetworkCopyFromTestCases))]
675+
public async Task TestPostgresNetworkCopyFrom(int batchSize, NpgsqlCidr? cCidr, IPAddress cInet, PhysicalAddress cMacaddr)
676+
{
677+
var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertPostgresTypesBatchArgs { CCidr = cCidr, CInet = cInet, CMacaddr = cMacaddr }).ToList();
678+
await QuerySql.InsertPostgresTypesBatch(batchArgs);
679+
var expected = new QuerySql.GetPostgresTypesCntRow
680+
{
681+
Cnt = batchSize,
682+
CCidr = cCidr,
683+
CInet = cInet,
684+
CMacaddr = cMacaddr
685+
};
686+
var actual = await QuerySql.GetPostgresTypesCnt();
687+
AssertSingularEquals(expected, actual.Value);
688+
void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgresTypesCntRow y)
689+
{
690+
Assert.That(x.Cnt, Is.EqualTo(y.Cnt));
691+
Assert.That(x.CCidr, Is.EqualTo(y.CCidr));
692+
Assert.That(x.CInet, Is.EqualTo(y.CInet));
693+
Assert.That(x.CMacaddr, Is.EqualTo(y.CMacaddr));
694+
}
695+
}
696+
664697
[Test]
665698
[TestCase(100, new byte[] { 0x53, 0x56 })]
666699
[TestCase(10, new byte[] { })]

end2end/EndToEndTestsLegacy/NpgsqlDapperTester.generated.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,39 @@ void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgre
661661
}
662662
}
663663

664+
private static IEnumerable<TestCaseData> PostgresNetworkCopyFromTestCases
665+
{
666+
get
667+
{
668+
yield return new TestCaseData(200, new NpgsqlCidr("192.168.1.0/24"), new IPAddress(new byte[] { 192, 168, 1, 1 }), new PhysicalAddress(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 })).SetName("Valid Network Copy From");
669+
yield return new TestCaseData(10, null, null, null).SetName("Null Network Copy From");
670+
}
671+
}
672+
673+
[Test]
674+
[TestCaseSource(nameof(PostgresNetworkCopyFromTestCases))]
675+
public async Task TestPostgresNetworkCopyFrom(int batchSize, NpgsqlCidr? cCidr, IPAddress cInet, PhysicalAddress cMacaddr)
676+
{
677+
var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertPostgresTypesBatchArgs { CCidr = cCidr, CInet = cInet, CMacaddr = cMacaddr }).ToList();
678+
await QuerySql.InsertPostgresTypesBatch(batchArgs);
679+
var expected = new QuerySql.GetPostgresTypesCntRow
680+
{
681+
Cnt = batchSize,
682+
CCidr = cCidr,
683+
CInet = cInet,
684+
CMacaddr = cMacaddr
685+
};
686+
var actual = await QuerySql.GetPostgresTypesCnt();
687+
AssertSingularEquals(expected, actual);
688+
void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgresTypesCntRow y)
689+
{
690+
Assert.That(x.Cnt, Is.EqualTo(y.Cnt));
691+
Assert.That(x.CCidr, Is.EqualTo(y.CCidr));
692+
Assert.That(x.CInet, Is.EqualTo(y.CInet));
693+
Assert.That(x.CMacaddr, Is.EqualTo(y.CMacaddr));
694+
}
695+
}
696+
664697
[Test]
665698
[TestCase(100, new byte[] { 0x53, 0x56 })]
666699
[TestCase(10, new byte[] { })]

end2end/EndToEndTestsLegacy/NpgsqlTester.generated.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,39 @@ void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgre
661661
}
662662
}
663663

664+
private static IEnumerable<TestCaseData> PostgresNetworkCopyFromTestCases
665+
{
666+
get
667+
{
668+
yield return new TestCaseData(200, new NpgsqlCidr("192.168.1.0/24"), new IPAddress(new byte[] { 192, 168, 1, 1 }), new PhysicalAddress(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 })).SetName("Valid Network Copy From");
669+
yield return new TestCaseData(10, null, null, null).SetName("Null Network Copy From");
670+
}
671+
}
672+
673+
[Test]
674+
[TestCaseSource(nameof(PostgresNetworkCopyFromTestCases))]
675+
public async Task TestPostgresNetworkCopyFrom(int batchSize, NpgsqlCidr? cCidr, IPAddress cInet, PhysicalAddress cMacaddr)
676+
{
677+
var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertPostgresTypesBatchArgs { CCidr = cCidr, CInet = cInet, CMacaddr = cMacaddr }).ToList();
678+
await QuerySql.InsertPostgresTypesBatch(batchArgs);
679+
var expected = new QuerySql.GetPostgresTypesCntRow
680+
{
681+
Cnt = batchSize,
682+
CCidr = cCidr,
683+
CInet = cInet,
684+
CMacaddr = cMacaddr
685+
};
686+
var actual = await QuerySql.GetPostgresTypesCnt();
687+
AssertSingularEquals(expected, actual);
688+
void AssertSingularEquals(QuerySql.GetPostgresTypesCntRow x, QuerySql.GetPostgresTypesCntRow y)
689+
{
690+
Assert.That(x.Cnt, Is.EqualTo(y.Cnt));
691+
Assert.That(x.CCidr, Is.EqualTo(y.CCidr));
692+
Assert.That(x.CInet, Is.EqualTo(y.CInet));
693+
Assert.That(x.CMacaddr, Is.EqualTo(y.CMacaddr));
694+
}
695+
}
696+
664697
[Test]
665698
[TestCase(100, new byte[] { 0x53, 0x56 })]
666699
[TestCase(10, new byte[] { })]

examples/NpgsqlDapperExample/QuerySql.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ public async Task InsertPostgresTypes(InsertPostgresTypesArgs args)
628628
await this.Transaction.Connection.ExecuteAsync(InsertPostgresTypesSql, queryParams, transaction: this.Transaction);
629629
}
630630

631-
private const string InsertPostgresTypesBatchSql = "COPY postgres_types (c_boolean, c_smallint, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea) FROM STDIN (FORMAT BINARY)";
631+
private const string InsertPostgresTypesBatchSql = "COPY postgres_types (c_boolean, c_smallint, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea, c_cidr, c_inet, c_macaddr) FROM STDIN (FORMAT BINARY)";
632632
public class InsertPostgresTypesBatchArgs
633633
{
634634
public bool? CBoolean { get; init; }
@@ -652,6 +652,9 @@ public class InsertPostgresTypesBatchArgs
652652
public string? CText { get; init; }
653653
public Guid? CUuid { get; init; }
654654
public byte[]? CBytea { get; init; }
655+
public NpgsqlCidr? CCidr { get; init; }
656+
public IPAddress? CInet { get; init; }
657+
public PhysicalAddress? CMacaddr { get; init; }
655658
};
656659
public async Task InsertPostgresTypesBatch(List<InsertPostgresTypesBatchArgs> args)
657660
{
@@ -684,6 +687,9 @@ public async Task InsertPostgresTypesBatch(List<InsertPostgresTypesBatchArgs> ar
684687
await writer.WriteAsync(row.CText);
685688
await writer.WriteAsync(row.CUuid);
686689
await writer.WriteAsync(row.CBytea);
690+
await writer.WriteAsync(row.CCidr);
691+
await writer.WriteAsync(row.CInet);
692+
await writer.WriteAsync(row.CMacaddr);
687693
}
688694

689695
await writer.CompleteAsync();
@@ -753,7 +759,7 @@ public class GetPostgresTypesRow
753759
return await this.Transaction.Connection.QueryFirstOrDefaultAsync<GetPostgresTypesRow?>(GetPostgresTypesSql, transaction: this.Transaction);
754760
}
755761

756-
private const string GetPostgresTypesCntSql = "SELECT c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea, COUNT (* ) AS cnt FROM postgres_types GROUP BY c_smallint, c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea LIMIT 1 ";
762+
private const string GetPostgresTypesCntSql = "SELECT c_smallint , c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea, c_cidr, c_inet, c_macaddr, COUNT (* ) AS cnt FROM postgres_types GROUP BY c_smallint, c_boolean, c_integer, c_bigint, c_real, c_numeric, c_decimal, c_double_precision, c_money, c_date, c_time, c_timestamp, c_timestamp_with_tz, c_interval, c_char, c_varchar, c_character_varying, c_bpchar, c_text, c_uuid, c_bytea, c_cidr, c_inet, c_macaddr LIMIT 1 ";
757763
public class GetPostgresTypesCntRow
758764
{
759765
public short? CSmallint { get; init; }
@@ -777,6 +783,9 @@ public class GetPostgresTypesCntRow
777783
public string? CText { get; init; }
778784
public Guid? CUuid { get; init; }
779785
public byte[]? CBytea { get; init; }
786+
public NpgsqlCidr? CCidr { get; init; }
787+
public IPAddress? CInet { get; init; }
788+
public PhysicalAddress? CMacaddr { get; init; }
780789
public required long Cnt { get; init; }
781790
};
782791
public async Task<GetPostgresTypesCntRow?> GetPostgresTypesCnt()

0 commit comments

Comments
 (0)