Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ jobs:
run: |
if [ -z "${{ matrix.pg_prerelease }}" ]; then
dotnet test -c ${{ matrix.config }} test/Npgsql.PluginTests --logger "GitHubActions;report-warnings=false"
dotnet test -c ${{ matrix.config }} test/Npgsql.NodaTime.Tests --logger "GitHubActions;report-warnings=false"
fi
shell: bash

Expand Down
11 changes: 11 additions & 0 deletions Npgsql.sln
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.SourceGenerators", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.TrimmingTests", "test\Npgsql.TrimmingTests\Npgsql.TrimmingTests.csproj", "{844EC023-21B8-448D-93AD-5F6857F15DFF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Npgsql.NodaTime.Tests", "test\Npgsql.NodaTime.Tests\Npgsql.NodaTime.Tests.csproj", "{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -133,6 +135,14 @@ Global
{844EC023-21B8-448D-93AD-5F6857F15DFF}.Release|Any CPU.Build.0 = Release|Any CPU
{844EC023-21B8-448D-93AD-5F6857F15DFF}.Release|x86.ActiveCfg = Release|Any CPU
{844EC023-21B8-448D-93AD-5F6857F15DFF}.Release|x86.Build.0 = Release|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Debug|x86.ActiveCfg = Debug|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Debug|x86.Build.0 = Debug|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Release|Any CPU.Build.0 = Release|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Release|x86.ActiveCfg = Release|Any CPU
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -149,6 +159,7 @@ Global
{A77E5FAF-D775-4AB4-8846-8965C2104E60} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{63026A19-60B8-4906-81CB-216F30E8094B} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{844EC023-21B8-448D-93AD-5F6857F15DFF} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{C00D2EB1-5719-4372-9E1C-5ED05DC23A00} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C90AEECD-DB4C-4BE6-B506-16A449852FB8}
Expand Down
8 changes: 4 additions & 4 deletions src/Npgsql.GeoJSON/Internal/GeoJSONTypeHandlerResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Npgsql.GeoJSON.Internal
{
public class GeoJSONTypeHandlerResolver : ITypeHandlerResolver
public class GeoJSONTypeHandlerResolver : TypeHandlerResolver
{
readonly NpgsqlDatabaseInfo _databaseInfo;
readonly GeoJsonHandler _geometryHandler, _geographyHandler;
Expand Down Expand Up @@ -51,15 +51,15 @@ internal GeoJSONTypeHandlerResolver(NpgsqlConnector connector, GeoJSONOptions op
_geographyHandler = new GeoJsonHandler(pgGeographyType, options, crsMap);
}

public NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
public override NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
=> typeName switch
{
"geometry" => _geometryHandler,
"geography" => _geographyHandler,
_ => null
};

public NpgsqlTypeHandler? ResolveByClrType(Type type)
public override NpgsqlTypeHandler? ResolveByClrType(Type type)
=> ClrTypeToDataTypeName(type, _geographyAsDefault) is { } dataTypeName && ResolveByDataTypeName(dataTypeName) is { } handler
? handler
: null;
Expand All @@ -71,7 +71,7 @@ internal GeoJSONTypeHandlerResolver(NpgsqlConnector connector, GeoJSONOptions op
? "geography"
: "geometry";

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> DoGetMappingByDataTypeName(dataTypeName);

internal static TypeMappingInfo? DoGetMappingByDataTypeName(string dataTypeName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@

namespace Npgsql.GeoJSON.Internal
{
public class GeoJSONTypeHandlerResolverFactory : ITypeHandlerResolverFactory
public class GeoJSONTypeHandlerResolverFactory : TypeHandlerResolverFactory
{
readonly GeoJSONOptions _options;
readonly bool _geographyAsDefault;

public GeoJSONTypeHandlerResolverFactory(GeoJSONOptions options, bool geographyAsDefault)
=> (_options, _geographyAsDefault) = (options, geographyAsDefault);

public ITypeHandlerResolver Create(NpgsqlConnector connector)
public override TypeHandlerResolver Create(NpgsqlConnector connector)
=> new GeoJSONTypeHandlerResolver(connector, _options, _geographyAsDefault);

public string? GetDataTypeNameByClrType(Type type)
public override string? GetDataTypeNameByClrType(Type type)
=> GeoJSONTypeHandlerResolver.ClrTypeToDataTypeName(type, _geographyAsDefault);

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> GeoJSONTypeHandlerResolver.DoGetMappingByDataTypeName(dataTypeName);
}
}
8 changes: 4 additions & 4 deletions src/Npgsql.Json.NET/Internal/JsonNetTypeHandlerResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Npgsql.Json.NET.Internal
{
public class JsonNetTypeHandlerResolver : ITypeHandlerResolver
public class JsonNetTypeHandlerResolver : TypeHandlerResolver
{
readonly NpgsqlDatabaseInfo _databaseInfo;
readonly JsonbHandler _jsonbHandler;
Expand Down Expand Up @@ -38,23 +38,23 @@ internal JsonNetTypeHandlerResolver(
_ => null
};

public NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
public override NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
=> typeName switch
{
"jsonb" => _jsonbHandler,
"json" => _jsonHandler,
_ => null
};

public NpgsqlTypeHandler? ResolveByClrType(Type type)
public override NpgsqlTypeHandler? ResolveByClrType(Type type)
=> ClrTypeToDataTypeName(type, _dataTypeNamesByClrType) is { } dataTypeName && ResolveByDataTypeName(dataTypeName) is { } handler
? handler
: null;

internal static string? ClrTypeToDataTypeName(Type type, Dictionary<Type, string> clrTypes)
=> clrTypes.TryGetValue(type, out var dataTypeName) ? dataTypeName : null;

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> DoGetMappingByDataTypeName(dataTypeName);

internal static TypeMappingInfo? DoGetMappingByDataTypeName(string dataTypeName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Npgsql.Json.NET.Internal
{
public class JsonNetTypeHandlerResolverFactory : ITypeHandlerResolverFactory
public class JsonNetTypeHandlerResolverFactory : TypeHandlerResolverFactory
{
readonly Type[] _jsonbClrTypes;
readonly Type[] _jsonClrTypes;
Expand All @@ -34,13 +34,13 @@ public JsonNetTypeHandlerResolverFactory(
_byType[type] = "json";
}

public ITypeHandlerResolver Create(NpgsqlConnector connector)
public override TypeHandlerResolver Create(NpgsqlConnector connector)
=> new JsonNetTypeHandlerResolver(connector, _byType, _settings);

public string? GetDataTypeNameByClrType(Type type)
public override string? GetDataTypeNameByClrType(Type type)
=> JsonNetTypeHandlerResolver.ClrTypeToDataTypeName(type, _byType);

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> JsonNetTypeHandlerResolver.DoGetMappingByDataTypeName(dataTypeName);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Npgsql.NetTopologySuite.Internal
{
public class NetTopologySuiteTypeHandlerResolver : ITypeHandlerResolver
public class NetTopologySuiteTypeHandlerResolver : TypeHandlerResolver
{
readonly NpgsqlDatabaseInfo _databaseInfo;
readonly bool _geographyAsDefault;
Expand All @@ -37,15 +37,15 @@ internal NetTopologySuiteTypeHandlerResolver(
_geographyHandler = new NetTopologySuiteHandler(pgGeographyType, reader, writer);
}

public NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
public override NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
=> typeName switch
{
"geometry" => _geometryHandler,
"geography" => _geographyHandler,
_ => null
};

public NpgsqlTypeHandler? ResolveByClrType(Type type)
public override NpgsqlTypeHandler? ResolveByClrType(Type type)
=> ClrTypeToDataTypeName(type, _geographyAsDefault) is { } dataTypeName && ResolveByDataTypeName(dataTypeName) is { } handler
? handler
: null;
Expand All @@ -57,7 +57,7 @@ internal NetTopologySuiteTypeHandlerResolver(
? "geography"
: "geometry";

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> DoGetMappingByDataTypeName(dataTypeName);

internal static TypeMappingInfo? DoGetMappingByDataTypeName(string dataTypeName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Npgsql.NetTopologySuite.Internal
{
public class NetTopologySuiteTypeHandlerResolverFactory : ITypeHandlerResolverFactory
public class NetTopologySuiteTypeHandlerResolverFactory : TypeHandlerResolverFactory
{
readonly CoordinateSequenceFactory _coordinateSequenceFactory;
readonly PrecisionModel _precisionModel;
Expand All @@ -27,14 +27,14 @@ public NetTopologySuiteTypeHandlerResolverFactory(
_geographyAsDefault = geographyAsDefault;
}

public ITypeHandlerResolver Create(NpgsqlConnector connector)
public override TypeHandlerResolver Create(NpgsqlConnector connector)
=> new NetTopologySuiteTypeHandlerResolver(connector, _coordinateSequenceFactory, _precisionModel, _handleOrdinates,
_geographyAsDefault);

public string? GetDataTypeNameByClrType(Type type)
public override string? GetDataTypeNameByClrType(Type type)
=> NetTopologySuiteTypeHandlerResolver.ClrTypeToDataTypeName(type, _geographyAsDefault);

public TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> NetTopologySuiteTypeHandlerResolver.DoGetMappingByDataTypeName(dataTypeName);
}
}
60 changes: 60 additions & 0 deletions src/Npgsql.NodaTime/Internal/LegacyTimestampHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Diagnostics;
using NodaTime;
using Npgsql.BackendMessages;
using Npgsql.Internal;
using Npgsql.Internal.TypeHandling;
using Npgsql.PostgresTypes;
using BclTimestampHandler = Npgsql.Internal.TypeHandlers.DateTimeHandlers.TimestampHandler;

namespace Npgsql.NodaTime.Internal
{
sealed partial class LegacyTimestampHandler : NpgsqlSimpleTypeHandler<Instant>,
INpgsqlSimpleTypeHandler<LocalDateTime>, INpgsqlSimpleTypeHandler<DateTime>
{
readonly bool _convertInfinityDateTime;
readonly BclTimestampHandler _bclHandler;

internal LegacyTimestampHandler(PostgresType postgresType, bool convertInfinityDateTime)
: base(postgresType)
{
_convertInfinityDateTime = convertInfinityDateTime;
_bclHandler = new BclTimestampHandler(postgresType, convertInfinityDateTime);
}

#region Read

public override Instant Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription = null)
=> TimestampTzHandler.ReadInstant(buf, _convertInfinityDateTime);

LocalDateTime INpgsqlSimpleTypeHandler<LocalDateTime>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
=> TimestampHandler.ReadLocalDateTime(buf);

DateTime INpgsqlSimpleTypeHandler<DateTime>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
=> _bclHandler.Read(buf, len, fieldDescription);

#endregion Read

#region Write

public override int ValidateAndGetLength(Instant value, NpgsqlParameter? parameter)
=> 8;

int INpgsqlSimpleTypeHandler<LocalDateTime>.ValidateAndGetLength(LocalDateTime value, NpgsqlParameter? parameter)
=> 8;

public override void Write(Instant value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> TimestampTzHandler.WriteInstant(value, buf, _convertInfinityDateTime);

void INpgsqlSimpleTypeHandler<LocalDateTime>.Write(LocalDateTime value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> TimestampHandler.WriteLocalDateTime(value, buf);

int INpgsqlSimpleTypeHandler<DateTime>.ValidateAndGetLength(DateTime value, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTime>)_bclHandler).ValidateAndGetLength(value, parameter);

void INpgsqlSimpleTypeHandler<DateTime>.Write(DateTime value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTime>)_bclHandler).Write(value, buf, parameter);

#endregion Write
}
}
98 changes: 98 additions & 0 deletions src/Npgsql.NodaTime/Internal/LegacyTimestampTzHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using NodaTime;
using NodaTime.TimeZones;
using Npgsql.BackendMessages;
using Npgsql.Internal;
using Npgsql.Internal.TypeHandling;
using Npgsql.PostgresTypes;
using BclTimestampTzHandler = Npgsql.Internal.TypeHandlers.DateTimeHandlers.TimestampTzHandler;

namespace Npgsql.NodaTime.Internal
{
sealed partial class LegacyTimestampTzHandler : NpgsqlSimpleTypeHandler<Instant>, INpgsqlSimpleTypeHandler<ZonedDateTime>,
INpgsqlSimpleTypeHandler<OffsetDateTime>, INpgsqlSimpleTypeHandler<DateTimeOffset>,
INpgsqlSimpleTypeHandler<DateTime>
{
readonly IDateTimeZoneProvider _dateTimeZoneProvider;
readonly TimestampTzHandler _wrappedHandler;

public LegacyTimestampTzHandler(PostgresType postgresType, bool convertInfinityDateTime)
: base(postgresType)
{
_dateTimeZoneProvider = DateTimeZoneProviders.Tzdb;
_wrappedHandler = new TimestampTzHandler(postgresType, convertInfinityDateTime);
}

#region Read

public override Instant Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription = null)
=> _wrappedHandler.Read(buf, len, fieldDescription);

ZonedDateTime INpgsqlSimpleTypeHandler<ZonedDateTime>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
{
try
{
var zonedDateTime = ((INpgsqlSimpleTypeHandler<ZonedDateTime>)_wrappedHandler).Read(buf, len, fieldDescription);

var value = buf.ReadInt64();
if (value == long.MaxValue || value == long.MinValue)
throw new NotSupportedException("Infinity values not supported for timestamp with time zone");
return zonedDateTime.WithZone(_dateTimeZoneProvider[buf.Connection.Timezone]);
}
catch (Exception e) when (
string.Equals(buf.Connection.Timezone, "localtime", StringComparison.OrdinalIgnoreCase) &&
(e is TimeZoneNotFoundException || e is DateTimeZoneNotFoundException))
{
throw new TimeZoneNotFoundException(
"The special PostgreSQL timezone 'localtime' is not supported when reading values of type 'timestamp with time zone'. " +
"Please specify a real timezone in 'postgresql.conf' on the server, or set the 'PGTZ' environment variable on the client.",
e);
}
}

OffsetDateTime INpgsqlSimpleTypeHandler<OffsetDateTime>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
=> ((INpgsqlSimpleTypeHandler<ZonedDateTime>)this).Read(buf, len, fieldDescription).ToOffsetDateTime();

DateTimeOffset INpgsqlSimpleTypeHandler<DateTimeOffset>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
=> _wrappedHandler.Read<DateTimeOffset>(buf, len, fieldDescription);

DateTime INpgsqlSimpleTypeHandler<DateTime>.Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription)
=> _wrappedHandler.Read<DateTime>(buf, len, fieldDescription);

#endregion Read

#region Write

public override int ValidateAndGetLength(Instant value, NpgsqlParameter? parameter)
=> 8;

int INpgsqlSimpleTypeHandler<ZonedDateTime>.ValidateAndGetLength(ZonedDateTime value, NpgsqlParameter? parameter)
=> 8;

public int ValidateAndGetLength(OffsetDateTime value, NpgsqlParameter? parameter)
=> 8;

public override void Write(Instant value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> _wrappedHandler.Write(value, buf, parameter);

void INpgsqlSimpleTypeHandler<ZonedDateTime>.Write(ZonedDateTime value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> _wrappedHandler.Write(value.ToInstant(), buf, parameter);

public void Write(OffsetDateTime value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> _wrappedHandler.Write(value.ToInstant(), buf, parameter);

int INpgsqlSimpleTypeHandler<DateTimeOffset>.ValidateAndGetLength(DateTimeOffset value, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTimeOffset>)_wrappedHandler).ValidateAndGetLength(value, parameter);

void INpgsqlSimpleTypeHandler<DateTimeOffset>.Write(DateTimeOffset value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTimeOffset>)_wrappedHandler).Write(value, buf, parameter);

int INpgsqlSimpleTypeHandler<DateTime>.ValidateAndGetLength(DateTime value, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTime>)_wrappedHandler).ValidateAndGetLength(value, parameter);

void INpgsqlSimpleTypeHandler<DateTime>.Write(DateTime value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
=> ((INpgsqlSimpleTypeHandler<DateTime>)_wrappedHandler).Write(value, buf, parameter);

#endregion Write
}
}
Loading