Skip to content

Commit dbd9be9

Browse files
committed
Fix delayed converter resolution for nullables (#6453)
(cherry picked from commit 013e771)
1 parent cc260f0 commit dbd9be9

File tree

3 files changed

+49
-41
lines changed

3 files changed

+49
-41
lines changed

src/Npgsql/Internal/Converters/ArrayConverter.cs

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -590,45 +590,40 @@ protected override PgConverter<T> CreateConverter(PgConverterResolution effectiv
590590
protected override PgConverterResolution? GetEffectiveResolution(T? values, PgTypeId? expectedEffectivePgTypeId)
591591
{
592592
PgConverterResolution? resolution = null;
593-
if (values is null)
593+
switch (values)
594594
{
595-
resolution = EffectiveTypeInfo.GetDefaultResolution(expectedEffectivePgTypeId);
596-
}
597-
else
598-
{
599-
switch (values)
600-
{
601-
case TElement[] array:
602-
foreach (var value in array)
603-
{
604-
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
605-
resolution ??= result;
606-
}
607-
break;
608-
case List<TElement> list:
609-
foreach (var value in list)
610-
{
611-
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
612-
resolution ??= result;
613-
}
614-
break;
615-
case IList<TElement> list:
616-
foreach (var value in list)
617-
{
618-
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
619-
resolution ??= result;
620-
}
621-
break;
622-
case Array array:
623-
foreach (var value in array)
624-
{
625-
var result = EffectiveTypeInfo.GetResolutionAsObject(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
626-
resolution ??= result;
627-
}
628-
break;
629-
default:
630-
throw new NotSupportedException();
631-
}
595+
case TElement[] array:
596+
foreach (var value in array)
597+
{
598+
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
599+
resolution ??= result;
600+
}
601+
break;
602+
case List<TElement> list:
603+
foreach (var value in list)
604+
{
605+
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
606+
resolution ??= result;
607+
}
608+
break;
609+
case IList<TElement> list:
610+
foreach (var value in list)
611+
{
612+
var result = EffectiveTypeInfo.GetResolution(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
613+
resolution ??= result;
614+
}
615+
break;
616+
case Array array:
617+
foreach (var value in array)
618+
{
619+
var result = EffectiveTypeInfo.GetResolutionAsObject(value, resolution?.PgTypeId ?? expectedEffectivePgTypeId);
620+
resolution ??= result;
621+
}
622+
break;
623+
case null:
624+
break;
625+
default:
626+
throw new NotSupportedException();
632627
}
633628

634629
return resolution;

src/Npgsql/Internal/Converters/NullableConverter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public NullableConverterResolver(PgResolverTypeInfo effectiveTypeInfo)
5454
=> new NullableConverter<T>(effectiveResolution.GetConverter<T>());
5555

5656
protected override PgConverterResolution? GetEffectiveResolution(T? value, PgTypeId? expectedEffectivePgTypeId)
57-
=> value is null
58-
? EffectiveTypeInfo.GetDefaultResolution(expectedEffectivePgTypeId)
59-
: EffectiveTypeInfo.GetResolution(value.GetValueOrDefault(), expectedEffectivePgTypeId);
57+
=> value is { } inner
58+
? EffectiveTypeInfo.GetResolution(inner, expectedEffectivePgTypeId)
59+
: null;
6060
}

test/Npgsql.Tests/Types/DateTimeTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,19 @@ await AssertType(datasource,
497497
"timestamp with time zone[]",
498498
NpgsqlDbType.TimestampTz | NpgsqlDbType.Array);
499499

500+
// Make sure delayed converter resolution works when null precedes a non-null value.
501+
// We expect the resolution of null values to not lock in the default type timestamp.
502+
// This would cause the subsequent non-null value to fail to convert, as it requires timestamptz.
503+
await AssertType(datasource,
504+
new DateTime?[]
505+
{
506+
null,
507+
new DateTime(1998, 4, 12, 13, 26, 38, DateTimeKind.Utc)
508+
},
509+
@"{NULL,""1998-04-12 15:26:38+02""}",
510+
"timestamp with time zone[]",
511+
NpgsqlDbType.TimestampTz | NpgsqlDbType.Array);
512+
500513
await AssertType(datasource,
501514
new DateTime?[]
502515
{

0 commit comments

Comments
 (0)