diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 98d37d1be..78e3708e5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ on: pull_request: env: - dotnet_sdk_version: '6.0.100-preview.4.21255.9' + dotnet_sdk_version: '6.0.100-preview.6.21355.2' postgis_version: 3 DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true diff --git a/Directory.Build.props b/Directory.Build.props index 5cd6c8e47..06d9c5939 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,6 @@ + net6.0 9.0 true latest diff --git a/Directory.Packages.props b/Directory.Packages.props index 8b34185dd..49703b6ff 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,8 +1,8 @@ - 6.0.0-preview.5.21301.9 - 6.0.0-preview.5.21301.5 - 6.0.0-preview5 + 6.0.0-preview.6.21352.1 + 6.0.0-preview.6.21352.12 + 6.0.0-preview6 diff --git a/global.json b/global.json index bf9854d68..4210b931f 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.100-preview.5.21302.13", + "version": "6.0.100-preview.6.21355.2", "rollForward": "latestMajor", "allowPrerelease": "false" } diff --git a/src/EFCore.PG.NTS/EFCore.PG.NTS.csproj b/src/EFCore.PG.NTS/EFCore.PG.NTS.csproj index c1031cfd4..ef183abf9 100644 --- a/src/EFCore.PG.NTS/EFCore.PG.NTS.csproj +++ b/src/EFCore.PG.NTS/EFCore.PG.NTS.csproj @@ -1,8 +1,5 @@ - net5.0 - net6.0 - Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite diff --git a/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj b/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj index 1ebf1d6bd..7ba5565ff 100644 --- a/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj +++ b/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj @@ -1,8 +1,5 @@ - net5.0 - net6.0 - Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime diff --git a/src/EFCore.PG/EFCore.PG.csproj b/src/EFCore.PG/EFCore.PG.csproj index 46c09b604..61be0d7fb 100644 --- a/src/EFCore.PG/EFCore.PG.csproj +++ b/src/EFCore.PG/EFCore.PG.csproj @@ -1,9 +1,6 @@  - net5.0;net6.0 - net6.0 - Npgsql.EntityFrameworkCore.PostgreSQL Npgsql.EntityFrameworkCore.PostgreSQL diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMemberTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMemberTranslator.cs index cbb7be5d2..cf7532cd3 100644 --- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMemberTranslator.cs +++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMemberTranslator.cs @@ -31,9 +31,7 @@ public NpgsqlDateTimeMemberTranslator(NpgsqlSqlExpressionFactory sqlExpressionFa { var type = member.DeclaringType; if (type != typeof(DateTime) && type != typeof(NpgsqlDateTime) && type != typeof(NpgsqlDate) -#if NET6_0_OR_GREATER && type != typeof(DateOnly) && type != typeof(TimeOnly) -#endif ) return null; diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMethodTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMethodTranslator.cs index eda94548b..e128bb662 100644 --- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMethodTranslator.cs +++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlDateTimeMethodTranslator.cs @@ -30,22 +30,18 @@ public class NpgsqlDateTimeMethodTranslator : IMethodCallTranslator { typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddSeconds), new[] { typeof(double) })!, "secs" }, //{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMilliseconds), new[] { typeof(double) })!, "milliseconds" } -#if NET6_0_OR_GREATER { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddYears), new[] { typeof(int) })!, "years" }, { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddMonths), new[] { typeof(int) })!, "months" }, { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddDays), new[] { typeof(int) })!, "days" }, { typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddHours), new[] { typeof(int) })!, "hours" }, { typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddMinutes), new[] { typeof(int) })!, "mins" }, -#endif }; -#if NET6_0_OR_GREATER private static readonly MethodInfo TimeOnlyIsBetweenMethod = typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.IsBetween), new[] { typeof(TimeOnly), typeof(TimeOnly) })!; private static readonly MethodInfo TimeOnlyAddTimeSpanMethod = typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.Add), new[] { typeof(TimeSpan) })!; -#endif private readonly ISqlExpressionFactory _sqlExpressionFactory; private readonly RelationalTypeMapping _intervalMapping; @@ -75,7 +71,6 @@ public NpgsqlDateTimeMethodTranslator( return translated; } -#if NET6_0_OR_GREATER if (method.DeclaringType == typeof(TimeOnly)) { if (method == TimeOnlyIsBetweenMethod) @@ -90,7 +85,6 @@ public NpgsqlDateTimeMethodTranslator( return _sqlExpressionFactory.Add(instance, arguments[0]); } } -#endif return null; } diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMathTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMathTranslator.cs index 3e0969a1e..4c7e1909b 100644 --- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMathTranslator.cs +++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlMathTranslator.cs @@ -29,28 +29,60 @@ public class NpgsqlMathTranslator : IMethodCallTranslator { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(int) })!, "abs" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(long) })!, "abs" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Abs), new[] { typeof(short) })!, "abs" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Abs), new[] { typeof(float) })!, "abs" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(decimal) })!, "ceiling" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Ceiling), new[] { typeof(double) })!, "ceiling" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Ceiling), new[] { typeof(float) })!, "ceiling" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(decimal) })!, "floor" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Floor), new[] { typeof(double) })!, "floor" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Floor), new[] { typeof(float) })!, "floor" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) })!, "power" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Pow), new[] { typeof(float), typeof(float) })!, "power" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Exp), new[] { typeof(double) })!, "exp" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Exp), new[] { typeof(float) })!, "exp" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Log10), new[] { typeof(double) })!, "log" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Log10), new[] { typeof(float) })!, "log" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Log), new[] { typeof(double) })!, "ln" }, - // Note: PostgreSQL has log(x,y) but only for decimal, whereas .NET has it only for double + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Log), new[] { typeof(float) })!, "ln" }, + // Note: PostgreSQL has log(x,y) but only for decimal, whereas .NET has it only for double/float + { typeof(Math).GetRuntimeMethod(nameof(Math.Sqrt), new[] { typeof(double) })!, "sqrt" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Sqrt), new[] { typeof(float) })!, "sqrt" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Acos), new[] { typeof(double) })!, "acos" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Acos), new[] { typeof(float) })!, "acos" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Asin), new[] { typeof(double) })!, "asin" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Asin), new[] { typeof(float) })!, "asin" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Atan), new[] { typeof(double) })!, "atan" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Atan), new[] { typeof(float) })!, "atan" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Atan2), new[] { typeof(double), typeof(double) })!, "atan2" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Atan2), new[] { typeof(float), typeof(float) })!, "atan2" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Cos), new[] { typeof(double) })!, "cos" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Cos), new[] { typeof(float) })!, "cos" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Sin), new[] { typeof(double) })!, "sin" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Sin), new[] { typeof(float) })!, "sin" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Tan), new[] { typeof(double) })!, "tan" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Tan), new[] { typeof(float) })!, "tan" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(double) })!, "round" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Round), new[] { typeof(decimal) })!, "round" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Round), new[] { typeof(float) })!, "round" }, + { typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(double) })!, "trunc" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Truncate), new[] { typeof(decimal) })!, "trunc" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Truncate), new[] { typeof(float) })!, "trunc" }, // https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(decimal), typeof(decimal) })!, "greatest" }, @@ -59,6 +91,7 @@ public class NpgsqlMathTranslator : IMethodCallTranslator { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(int), typeof(int) })!, "greatest" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(long), typeof(long) })!, "greatest" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Max), new[] { typeof(short), typeof(short) })!, "greatest" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Max), new[] { typeof(float), typeof(float) })!, "greatest" }, // https://www.postgresql.org/docs/current/functions-conditional.html#FUNCTIONS-GREATEST-LEAST { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(decimal), typeof(decimal) })!, "least" }, @@ -67,6 +100,7 @@ public class NpgsqlMathTranslator : IMethodCallTranslator { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(int), typeof(int) })!, "least" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(long), typeof(long) })!, "least" }, { typeof(Math).GetRuntimeMethod(nameof(Math.Min), new[] { typeof(short), typeof(short) })!, "least" }, + { typeof(MathF).GetRuntimeMethod(nameof(MathF.Min), new[] { typeof(float), typeof(float) })!, "least" }, }; private static readonly IEnumerable SignMethodInfos = new[] @@ -77,7 +111,8 @@ public class NpgsqlMathTranslator : IMethodCallTranslator typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(int) })!, typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(long) })!, typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(sbyte) })!, - typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) })! + typeof(Math).GetRuntimeMethod(nameof(Math.Sign), new[] { typeof(short) })!, + typeof(MathF).GetRuntimeMethod(nameof(MathF.Sign), new[] { typeof(float) })!, }; private static readonly MethodInfo RoundDecimalTwoParams diff --git a/src/EFCore.PG/Query/Internal/NpgsqlSqlTranslatingExpressionVisitor.cs b/src/EFCore.PG/Query/Internal/NpgsqlSqlTranslatingExpressionVisitor.cs index 8a6a3c9b1..f9c390b0e 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlSqlTranslatingExpressionVisitor.cs @@ -26,10 +26,8 @@ public class NpgsqlSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExp private static readonly ConstructorInfo DateTimeCtor2 = typeof(DateTime).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) })!; -#if NET6_0_OR_GREATER private static readonly ConstructorInfo DateOnlyCtor = typeof(DateOnly).GetConstructor(new[] { typeof(int), typeof(int), typeof(int) })!; -#endif private static readonly MethodInfo Like2MethodInfo = typeof(DbFunctionsExtensions).GetRuntimeMethod( @@ -437,7 +435,6 @@ protected override Expression VisitNew(NewExpression newExpression) "make_timestamp", sqlArguments, nullable: true, TrueArrays[6], typeof(DateTime)); } -#if NET6_0_OR_GREATER if (newExpression.Constructor == DateOnlyCtor) { return TryTranslateArguments(out var sqlArguments) @@ -445,7 +442,6 @@ protected override Expression VisitNew(NewExpression newExpression) "make_date", sqlArguments, nullable: true, TrueArrays[3], typeof(DateOnly)) : QueryCompilationContext.NotTranslatedExpression; } -#endif return QueryCompilationContext.NotTranslatedExpression; diff --git a/src/EFCore.PG/Query/NpgsqlSqlExpressionFactory.cs b/src/EFCore.PG/Query/NpgsqlSqlExpressionFactory.cs index 04f5a5b49..db3464420 100644 --- a/src/EFCore.PG/Query/NpgsqlSqlExpressionFactory.cs +++ b/src/EFCore.PG/Query/NpgsqlSqlExpressionFactory.cs @@ -158,7 +158,8 @@ public virtual PostgresNewArrayExpression NewArray( if (operatorType == ExpressionType.Subtract) { if (left.Type == typeof(DateTime) && right.Type == typeof(DateTime) || - left.Type == typeof(DateTimeOffset) && right.Type == typeof(DateTimeOffset)) + left.Type == typeof(DateTimeOffset) && right.Type == typeof(DateTimeOffset) || + left.Type == typeof(TimeOnly) && right.Type == typeof(TimeOnly)) { return (SqlBinaryExpression)ApplyTypeMapping( new SqlBinaryExpression(operatorType, left, right, typeof(TimeSpan), null), typeMapping); @@ -299,9 +300,7 @@ private SqlExpression ApplyTypeMappingOnSqlBinary(SqlBinaryExpression binary, Re && ( leftType == typeof(DateTime) || leftType == typeof(DateTimeOffset) -#if NET6_0_OR_GREATER || leftType == typeof(TimeOnly) -#endif ) || rightType.FullName == "NodaTime.Period" && ( @@ -328,10 +327,8 @@ private SqlExpression ApplyTypeMappingOnSqlBinary(SqlBinaryExpression binary, Re // LocalDateTime - LocalDateTime => Period if (leftType == typeof(DateTime) && rightType == typeof(DateTime) || leftType == typeof(DateTimeOffset) && rightType == typeof(DateTimeOffset) -#if NET6_0_OR_GREATER || leftType == typeof(DateOnly) && rightType == typeof(DateOnly) || leftType == typeof(TimeOnly) && rightType == typeof(TimeOnly) -#endif || leftType.FullName == "NodaTime.Instant" && rightType.FullName == "NodaTime.Instant" || leftType.FullName == "NodaTime.LocalDateTime" && rightType.FullName == "NodaTime.LocalDateTime" || leftType.FullName == "NodaTime.ZonedDateTime" && rightType.FullName == "NodaTime.ZonedDateTime" diff --git a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlDateTimeTypeMappings.cs b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlDateTimeTypeMappings.cs index 2f41a93fd..5d164d66e 100644 --- a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlDateTimeTypeMappings.cs +++ b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlDateTimeTypeMappings.cs @@ -71,9 +71,7 @@ protected override string GenerateNonNullSqlLiteral(object value) => value switch { DateTime d => FormattableString.Invariant($"DATE '{d:yyyy-MM-dd}'"), -#if NET6_0_OR_GREATER DateOnly d => FormattableString.Invariant($"DATE '{d:yyyy-MM-dd}'"), -#endif _ => throw new InvalidCastException($"Can't generate a date SQL literal for CLR type {value.GetType()}") }; } @@ -94,11 +92,9 @@ protected override string GenerateNonNullSqlLiteral(object value) TimeSpan ts => ts.Ticks % 10000000 == 0 ? FormattableString.Invariant($@"TIME '{value:hh\:mm\:ss}'") : FormattableString.Invariant($@"TIME '{value:hh\:mm\:ss\.FFFFFF}'"), -#if NET6_0_OR_GREATER TimeOnly t => t.Ticks % 10000000 == 0 ? FormattableString.Invariant($@"TIME '{value:HH\:mm\:ss}'") : FormattableString.Invariant($@"TIME '{value:HH\:mm\:ss\.FFFFFF}'"), -#endif _ => throw new InvalidCastException($"Can't generate a time SQL literal for CLR type {value.GetType()}") }; } diff --git a/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs b/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs index b28da5373..ccd6b97fa 100644 --- a/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs +++ b/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs @@ -72,10 +72,8 @@ public class NpgsqlTypeMappingSource : RelationalTypeMappingSource private readonly NpgsqlTimeTypeMapping _timeTimeSpan = new(typeof(TimeSpan)); private readonly NpgsqlTimeTzTypeMapping _timetz = new(); -#if NET6_0_OR_GREATER private readonly NpgsqlDateTypeMapping _dateDateOnly = new(typeof(DateOnly)); private readonly NpgsqlTimeTypeMapping _timeTimeOnly = new(typeof(TimeOnly)); -#endif // Network address types private readonly NpgsqlMacaddrTypeMapping _macaddr = new(); @@ -192,31 +190,9 @@ public NpgsqlTypeMappingSource(TypeMappingSourceDependencies dependencies, { "timestamp with time zone", new[] { _timestamptz, _timestamptzDto } }, { "timestamptz", new[] { _timestamptz, _timestamptzDto } }, { "interval", new[] { _interval } }, - - { "date", new RelationalTypeMapping[] -#if NET6_0_OR_GREATER - { _dateDateOnly, _dateDateTime } -#else - { _dateDateTime } -#endif - }, - - { "time without time zone", new RelationalTypeMapping[] -#if NET6_0_OR_GREATER - { _timeTimeOnly, _timeTimeSpan } -#else - { _timeTimeSpan } -#endif - }, - - { "time", new RelationalTypeMapping[] -#if NET6_0_OR_GREATER - { _timeTimeOnly, _timeTimeSpan } -#else - { _timeTimeSpan } -#endif - }, - + { "date", new RelationalTypeMapping[] { _dateDateOnly, _dateDateTime } }, + { "time without time zone", new RelationalTypeMapping[] { _timeTimeOnly, _timeTimeSpan } }, + { "time", new RelationalTypeMapping[] { _timeTimeOnly, _timeTimeSpan } }, { "time with time zone", new[] { _timetz } }, { "timetz", new[] { _timetz } }, { "macaddr", new[] { _macaddr } }, @@ -277,6 +253,8 @@ public NpgsqlTypeMappingSource(TypeMappingSourceDependencies dependencies, { typeof(JsonElement), _jsonbElement }, { typeof(char), _singleChar }, { typeof(DateTime), _timestamp }, + { typeof(DateOnly), _dateDateOnly }, + { typeof(TimeOnly), _timeTimeOnly }, { typeof(TimeSpan), _interval }, { typeof(DateTimeOffset), _timestamptzDto }, { typeof(PhysicalAddress), _macaddr }, @@ -287,11 +265,6 @@ public NpgsqlTypeMappingSource(TypeMappingSourceDependencies dependencies, { typeof(Dictionary), _hstore }, { typeof(NpgsqlTid), _tid }, -#if NET6_0_OR_GREATER - { typeof(DateOnly), _dateDateOnly }, - { typeof(TimeOnly), _timeTimeOnly }, -#endif - { typeof(NpgsqlPoint), _point }, { typeof(NpgsqlBox), _box }, { typeof(NpgsqlLine), _line }, diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 2cf9d2a78..2631be37a 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -2,10 +2,6 @@ - - net6.0 - - $(NoWarn);xUnit1003;xUnit1004;xUnit1013;EF1001 diff --git a/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs index 597d77c4d..c80f20f55 100644 --- a/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/BuiltInDataTypesNpgsqlTest.cs @@ -98,10 +98,8 @@ public virtual void Can_query_using_any_mapped_data_type() DateTimeOffsetAsTimetz = new DateTimeOffset(1, 1, 1, 12, 0, 0, TimeSpan.FromHours(2)), TimeSpanAsInterval = new TimeSpan(11, 15, 12), -#if NET6_0_OR_GREATER DateOnlyAsDate = new DateOnly(2015, 1, 2), TimeOnlyAsTime = new TimeOnly(11, 15, 12), -#endif StringAsText = "Gumball Rules!", StringAsVarchar = "Gumball Rules OK", @@ -205,13 +203,11 @@ public virtual void Can_query_using_any_mapped_data_type() TimeSpan? param19 = new TimeSpan(11, 15, 12); Assert.Same(entity, context.Set().Single(e => e.Int == 999 && e.TimeSpanAsInterval == param19)); -#if NET6_0_OR_GREATER DateOnly? param20 = new DateOnly(2015, 1, 2); Assert.Same(entity, context.Set().Single(e => e.Int == 999 && e.DateOnlyAsDate == param20)); TimeOnly? param21 = new TimeOnly(11, 15, 12); Assert.Same(entity, context.Set().Single(e => e.Int == 999 && e.TimeOnlyAsTime == param21)); -#endif // ReSharper disable once ConvertToConstant.Local var param22 = "Gumball Rules!"; @@ -380,13 +376,11 @@ public virtual void Can_query_using_any_mapped_data_types_with_nulls() TimeSpan? param19 = null; Assert.Same(entity, context.Set().Single(e => e.Int == 911 && e.TimeSpanAsInterval == param19)); -#if NET6_0_OR_GREATER DateOnly? param20 = null; Assert.Same(entity, context.Set().Single(e => e.Int == 911 && e.DateOnlyAsDate == param20)); TimeOnly? param21 = null; Assert.Same(entity, context.Set().Single(e => e.Int == 911 && e.TimeOnlyAsTime == param21)); -#endif string param22 = null; Assert.Same(entity, context.Set().Single(e => e.Int == 911 && e.StringAsText == param22)); @@ -695,10 +689,8 @@ private static void AssertNullMappedNullableDataTypes(MappedNullableDataTypes en Assert.Null(entity.DateTimeOffsetAsTimetz); Assert.Null(entity.TimeSpanAsInterval); - #if NET6_0_OR_GREATER Assert.Null(entity.DateOnlyAsDate); Assert.Null(entity.TimeOnlyAsTime); - #endif Assert.Null(entity.StringAsText); Assert.Null(entity.StringAsVarchar); @@ -1307,13 +1299,11 @@ protected class MappedNullableDataTypes [Column(TypeName = "time")] public TimeSpan? TimeSpanAsTime { get; set; } -#if NET6_0_OR_GREATER [Column(TypeName = "date")] public DateOnly? DateOnlyAsDate { get; set; } [Column(TypeName = "time")] public TimeOnly? TimeOnlyAsTime { get; set; } -#endif [Column(TypeName = "timetz")] public DateTimeOffset? DateTimeOffsetAsTimetz { get; set; } diff --git a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs index 849352b0b..5b0d228f1 100644 --- a/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Migrations/MigrationsNpgsqlTest.cs @@ -57,7 +57,7 @@ public override async Task Create_table_all_settings() ""SSN"" character varying(11) COLLATE ""POSIX"" NOT NULL, CONSTRAINT ""PK_People"" PRIMARY KEY (""CustomId""), CONSTRAINT ""AK_People_SSN"" UNIQUE (""SSN""), - CONSTRAINT ""CK_EmployerId"" CHECK (""EmployerId"" > 0), + CONSTRAINT ""CK_People_EmployerId"" CHECK (""EmployerId"" > 0), CONSTRAINT ""FK_People_Employers_EmployerId"" FOREIGN KEY (""EmployerId"") REFERENCES ""Employers"" (""Id"") ON DELETE RESTRICT ); COMMENT ON TABLE dbo2.""People"" IS 'Table comment'; @@ -1974,7 +1974,7 @@ public override async Task Add_check_constraint_with_name() await base.Add_check_constraint_with_name(); AssertSql( - @"ALTER TABLE ""People"" ADD CONSTRAINT ""CK_Foo"" CHECK (""DriverLicense"" > 0);"); + @"ALTER TABLE ""People"" ADD CONSTRAINT ""CK_People_Foo"" CHECK (""DriverLicense"" > 0);"); } public override async Task Drop_check_constraint() @@ -1982,7 +1982,7 @@ public override async Task Drop_check_constraint() await base.Drop_check_constraint(); AssertSql( - @"ALTER TABLE ""People"" DROP CONSTRAINT ""CK_Foo"";"); + @"ALTER TABLE ""People"" DROP CONSTRAINT ""CK_People_Foo"";"); } #endregion diff --git a/test/EFCore.PG.FunctionalTests/Query/GearsOfWarQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/GearsOfWarQueryNpgsqlTest.cs index c2a1bd32c..6bb71bcb0 100644 --- a/test/EFCore.PG.FunctionalTests/Query/GearsOfWarQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/GearsOfWarQueryNpgsqlTest.cs @@ -17,7 +17,7 @@ public GearsOfWarQueryNpgsqlTest(GearsOfWarQueryNpgsqlFixture fixture, ITestOutp : base(fixture) { Fixture.TestSqlLoggerFactory.Clear(); - // Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); } public override async Task Byte_array_contains_literal(bool async) @@ -174,7 +174,7 @@ public override async Task Where_TimeSpan_Minutes(bool async) await base.Where_TimeSpan_Minutes(async); AssertSql( - @"SELECT m.""Id"", m.""CodeName"", m.""Duration"", m.""Rating"", m.""Timeline"" + @"SELECT m.""Id"", m.""CodeName"", m.""Date"", m.""Duration"", m.""Rating"", m.""Time"", m.""Timeline"" FROM ""Missions"" AS m WHERE floor(date_part('minute', m.""Duration""))::INT = 1"); } @@ -184,7 +184,7 @@ public override async Task Where_TimeSpan_Seconds(bool async) await base.Where_TimeSpan_Seconds(async); AssertSql( - @"SELECT m.""Id"", m.""CodeName"", m.""Duration"", m.""Rating"", m.""Timeline"" + @"SELECT m.""Id"", m.""CodeName"", m.""Date"", m.""Duration"", m.""Rating"", m.""Time"", m.""Timeline"" FROM ""Missions"" AS m WHERE floor(date_part('second', m.""Duration""))::INT = 1"); } @@ -194,15 +194,13 @@ public override async Task Where_TimeSpan_Milliseconds(bool async) await base.Where_TimeSpan_Milliseconds(async); AssertSql( - @"SELECT m.""Id"", m.""CodeName"", m.""Duration"", m.""Rating"", m.""Timeline"" + @"SELECT m.""Id"", m.""CodeName"", m.""Date"", m.""Duration"", m.""Rating"", m.""Time"", m.""Timeline"" FROM ""Missions"" AS m WHERE (floor(date_part('millisecond', m.""Duration""))::INT % 1000) = 1"); } #endregion TimeSpan -#if DATEONLY_TIMEONLY_TESTS_IMPLEMENTED_UPSTREAM -#if NET6_0_OR_GREATER #region DateOnly [ConditionalTheory] @@ -222,7 +220,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_Year(bool async) + public override async Task Where_DateOnly_Year(bool async) { await AssertQuery( async, @@ -237,7 +235,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_Month(bool async) + public override async Task Where_DateOnly_Month(bool async) { await AssertQuery( async, @@ -252,7 +250,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_Day(bool async) + public override async Task Where_DateOnly_Day(bool async) { await AssertQuery( async, @@ -267,7 +265,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_DayOfYear(bool async) + public override async Task Where_DateOnly_DayOfYear(bool async) { await AssertQuery( async, @@ -282,7 +280,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_DayOfWeek(bool async) + public override async Task Where_DateOnly_DayOfWeek(bool async) { await AssertQuery( async, @@ -297,7 +295,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_AddYears(bool async) + public override async Task Where_DateOnly_AddYears(bool async) { await AssertQuery( async, @@ -312,7 +310,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_AddMonths(bool async) + public override async Task Where_DateOnly_AddMonths(bool async) { await AssertQuery( async, @@ -327,7 +325,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_DateOnly_AddDays(bool async) + public override async Task Where_DateOnly_AddDays(bool async) { await AssertQuery( async, @@ -346,7 +344,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_Hour(bool async) + public override async Task Where_TimeOnly_Hour(bool async) { await AssertQuery( async, @@ -361,7 +359,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_Minute(bool async) + public override async Task Where_TimeOnly_Minute(bool async) { await AssertQuery( async, @@ -376,7 +374,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_Second(bool async) + public override async Task Where_TimeOnly_Second(bool async) { await AssertQuery( async, @@ -389,21 +387,12 @@ await AssertQuery( WHERE date_part('second', m.""Time"")::INT = 50"); } - // [ConditionalTheory] - // [MemberData(nameof(IsAsyncData))] - // public virtual Task Where_TimeOnly_Millisecond(bool async) - // { - // return Task.CompletedTask; - // // SQL translation not implemented, too annoying - // // await AssertQuery( - // // async, - // // ss => ss.Set().Where(m => m.Time.Millisecond == 500).AsTracking(), - // // entryCount: 1); - // } + public override Task Where_TimeOnly_Millisecond(bool async) + => Task.CompletedTask; // Translation not implemented [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_AddHours(bool async) + public override async Task Where_TimeOnly_AddHours(bool async) { await AssertQuery( async, @@ -418,7 +407,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_AddMinutes(bool async) + public override async Task Where_TimeOnly_AddMinutes(bool async) { await AssertQuery( async, @@ -433,7 +422,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_Add_TimeSpan(bool async) + public override async Task Where_TimeOnly_Add_TimeSpan(bool async) { await AssertQuery( async, @@ -448,7 +437,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_IsBetween(bool async) + public override async Task Where_TimeOnly_IsBetween(bool async) { await AssertQuery( async, @@ -463,7 +452,7 @@ await AssertQuery( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Where_TimeOnly_subtract_TimeOnly(bool async) + public override async Task Where_TimeOnly_subtract_TimeOnly(bool async) { await AssertQuery( async, @@ -477,8 +466,7 @@ await AssertQuery( } #endregion TimeOnly -#endif -#endif + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } } diff --git a/test/EFCore.PG.FunctionalTests/Query/NorthwindFunctionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NorthwindFunctionsQueryNpgsqlTest.cs index 623f2de69..132aeba07 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NorthwindFunctionsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NorthwindFunctionsQueryNpgsqlTest.cs @@ -34,6 +34,12 @@ public override async Task IsNullOrWhiteSpace_in_predicate(bool async) public override Task Where_math_log_new_base(bool async) => Task.CompletedTask; // PostgreSQL only has log(x, base) over numeric, may be possible to cast back and forth though + public override Task Where_mathf_log_new_base(bool async) + => Task.CompletedTask; // PostgreSQL only has log(x, base) over numeric, may be possible to cast back and forth though + + public override Task Where_mathf_round2(bool async) + => Task.CompletedTask; // PostgreSQL only has round(v, s) over numeric, may be possible to cast back and forth though + public override Task Convert_ToString(bool async) => Task.CompletedTask; // Convert on DateTime not yet supported diff --git a/test/EFCore.PG.FunctionalTests/Query/TPTGearsOfWarQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/TPTGearsOfWarQueryNpgsqlTest.cs index ff5c3d88d..404e60771 100644 --- a/test/EFCore.PG.FunctionalTests/Query/TPTGearsOfWarQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/TPTGearsOfWarQueryNpgsqlTest.cs @@ -54,5 +54,8 @@ public TPTGearsOfWarQueryNpgsqlTest(TPTGearsOfWarQueryNpgsqlFixture fixture, ITe // Test runs successfully, but some time difference and precision issues and fail the assertion public override Task Where_TimeSpan_Hours(bool async) => Task.CompletedTask; + + public override Task Where_TimeOnly_Millisecond(bool async) + => Task.CompletedTask; // Translation not implemented } } diff --git a/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj b/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj index 532db6243..63eb0f592 100644 --- a/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj +++ b/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/EFCore.PG.Tests/Scaffolding/NpgsqlCodeGeneratorTest.cs b/test/EFCore.PG.Tests/Scaffolding/NpgsqlCodeGeneratorTest.cs index bd2c22620..0e1a88224 100644 --- a/test/EFCore.PG.Tests/Scaffolding/NpgsqlCodeGeneratorTest.cs +++ b/test/EFCore.PG.Tests/Scaffolding/NpgsqlCodeGeneratorTest.cs @@ -44,7 +44,7 @@ public virtual void Use_provider_method_is_generated_correctly_with_options() var nestedClosure = Assert.IsType(a); Assert.Equal("x", nestedClosure.Parameter); - Assert.Same(providerOptions, nestedClosure.MethodCall); + Assert.Same(providerOptions, nestedClosure.MethodCalls[0]); }); Assert.Null(result.ChainedCall); } diff --git a/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs b/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs index ed840486d..4aca193f0 100644 --- a/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs +++ b/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs @@ -29,11 +29,9 @@ public void GenerateSqlLiteral_returns_date_literal() "DATE '2015-03-12'", GetMapping("date").GenerateSqlLiteral(new DateTime(2015, 3, 12))); -#if NET6_0_OR_GREATER Assert.Equal( "DATE '2015-03-12'", GetMapping("date").GenerateSqlLiteral(new DateOnly(2015, 3, 12))); -#endif } [Fact] @@ -92,7 +90,6 @@ public void GenerateSqlLiteral_returns_time_literal() Assert.Equal("TIME '04:05:06.123'", mapping.GenerateSqlLiteral(new TimeSpan(0, 4, 5, 6, 123))); Assert.Equal("TIME '04:05:06'", mapping.GenerateSqlLiteral(new TimeSpan(4, 5, 6))); -#if NET6_0_OR_GREATER Assert.Equal("TIME '04:05:06.123456'", mapping.GenerateSqlLiteral(new TimeOnly(4, 5, 6, 123).Add(TimeSpan.FromTicks(4560)))); Assert.Equal("TIME '04:05:06.000123'", @@ -100,7 +97,6 @@ public void GenerateSqlLiteral_returns_time_literal() Assert.Equal("TIME '04:05:06.123'", mapping.GenerateSqlLiteral(new TimeOnly(4, 5, 6, 123))); Assert.Equal("TIME '04:05:06'", mapping.GenerateSqlLiteral(new TimeOnly(4, 5, 6))); Assert.Equal("TIME '13:05:06'", mapping.GenerateSqlLiteral(new TimeOnly(13, 5, 6))); -#endif } [Fact] diff --git a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs index b7ab3b778..f38c26e86 100644 --- a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs +++ b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchFactoryTest.cs @@ -49,8 +49,8 @@ public void Uses_MaxBatchSize_specified_in_NpgsqlOptionsExtension() var batch = factory.Create(); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); - Assert.False(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); + Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + Assert.False(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); } [Fact] @@ -88,8 +88,8 @@ public void MaxBatchSize_is_optional() var batch = factory.Create(); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); - Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); + Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); + Assert.True(batch.AddCommand(new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); } private class FakeDbContext : DbContext diff --git a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs index fac06663a..e25141c88 100644 --- a/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs +++ b/test/EFCore.PG.Tests/Update/NpgsqlModificationCommandBatchTest.cs @@ -50,10 +50,10 @@ public void AddCommand_returns_false_when_max_batch_size_is_reached() Assert.True( batch.AddCommand( - new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); + new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); Assert.False( batch.AddCommand( - new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null))); + new ModificationCommand("T1", null, new ParameterNameGenerator().GenerateNext, false, null, null))); } private class FakeDbContext : DbContext