diff --git a/src/EFCore.Jet.Data/JetDataReader.cs b/src/EFCore.Jet.Data/JetDataReader.cs
index 8a1e43f..79f728b 100644
--- a/src/EFCore.Jet.Data/JetDataReader.cs
+++ b/src/EFCore.Jet.Data/JetDataReader.cs
@@ -176,7 +176,16 @@ namespace EntityFrameworkCore.Jet.Data
return (DateTime)value;
}
- return (DateTime)value;
+ public DateOnly GetDateOnly(int ordinal)
+ {
+ var value = GetDateTime(ordinal);
+ return DateOnly.FromDateTime(value);
+ }
+
+ public TimeOnly GetTimeOnly(int ordinal)
+ {
+ var value = GetDateTime(ordinal);
+ return TimeOnly.FromDateTime(value);
}
public virtual TimeSpan GetTimeSpan(int ordinal)
@@ -472,6 +481,14 @@ namespace EntityFrameworkCore.Jet.Data
{
return (T)(object)GetDateTime(ordinal);
}
+ if (typeof(T) == typeof(DateOnly))
+ {
+ return (T)(object)GetDateOnly(ordinal);
+ }
+ if (typeof(T) == typeof(TimeOnly))
+ {
+ return (T)(object)GetTimeOnly(ordinal);
+ }
if (typeof(T) == typeof(TimeSpan))
{
return (T)(object)GetTimeSpan(ordinal);
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMemberTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMemberTranslator.cs
new file mode 100644
index 0000000..1f1379f
--- /dev/null
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMemberTranslator.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Query;
+using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
+
+namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal;
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public class JetDateOnlyMemberTranslator : IMemberTranslator
+{
+ private static readonly Dictionary DatePartMapping
+ = new()
+ {
+ { nameof(DateTime.Year), "yyyy" },
+ { nameof(DateTime.Month), "m" },
+ { nameof(DateTime.DayOfYear), "y" },
+ { nameof(DateTime.Day), "d" }
+ };
+
+ private readonly ISqlExpressionFactory _sqlExpressionFactory;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public JetDateOnlyMemberTranslator(ISqlExpressionFactory sqlExpressionFactory)
+ {
+ _sqlExpressionFactory = sqlExpressionFactory;
+ }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual SqlExpression? Translate(
+ SqlExpression? instance,
+ MemberInfo member,
+ Type returnType,
+ IDiagnosticsLogger logger)
+ => member.DeclaringType == typeof(DateOnly) && DatePartMapping.TryGetValue(member.Name, out var datePart)
+ ? _sqlExpressionFactory.Function(
+ "DATEPART",
+ new[] { _sqlExpressionFactory.Constant(datePart), instance! },
+ nullable: true,
+ argumentsPropagateNullability: new[] { false, true },
+ returnType)
+ : null;
+}
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMethodTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMethodTranslator.cs
new file mode 100644
index 0000000..e51c188
--- /dev/null
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetDateOnlyMethodTranslator.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Query;
+using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
+
+namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal;
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public class JetDateOnlyMethodTranslator : IMethodCallTranslator
+{
+ private readonly Dictionary _methodInfoDatePartMapping = new()
+ {
+ { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddYears), new[] { typeof(int) })!, "yyyy" },
+ { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddMonths), new[] { typeof(int) })!, "m" },
+ { typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddDays), new[] { typeof(int) })!, "d" }
+ };
+
+ private readonly ISqlExpressionFactory _sqlExpressionFactory;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public JetDateOnlyMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
+ {
+ _sqlExpressionFactory = sqlExpressionFactory;
+ }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual SqlExpression? Translate(
+ SqlExpression? instance,
+ MethodInfo method,
+ IReadOnlyList arguments,
+ IDiagnosticsLogger logger)
+ {
+ if (_methodInfoDatePartMapping.TryGetValue(method, out var datePart)
+ && instance != null)
+ {
+ instance = _sqlExpressionFactory.ApplyDefaultTypeMapping(instance);
+
+ return _sqlExpressionFactory.Function(
+ "DATEADD",
+ new[] { _sqlExpressionFactory.Constant(datePart), _sqlExpressionFactory.Convert(arguments[0], typeof(int)), instance },
+ nullable: true,
+ argumentsPropagateNullability: new[] { false, true, true },
+ instance.Type,
+ instance.TypeMapping);
+ }
+
+ if (method.DeclaringType == typeof(DateOnly)
+ && method.Name == nameof(DateOnly.FromDateTime)
+ && arguments.Count == 1)
+ {
+ return _sqlExpressionFactory.Convert(arguments[0], typeof(DateOnly));
+ }
+
+ return null;
+ }
+}
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMemberTranslatorProvider.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMemberTranslatorProvider.cs
index 9ad36af..4e00771 100644
--- a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMemberTranslatorProvider.cs
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMemberTranslatorProvider.cs
@@ -23,9 +23,11 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal
// ReSharper disable once VirtualMemberCallInConstructor
AddTranslators(new IMemberTranslator[]
{
- new JetStringMemberTranslator(sqlExpressionFactory),
+ new JetDateOnlyMemberTranslator(sqlExpressionFactory),
new JetDateTimeMemberTranslator(sqlExpressionFactory),
- new JetTimeSpanMemberTranslator(sqlExpressionFactory)
+ new JetStringMemberTranslator(sqlExpressionFactory),
+ new JetTimeSpanMemberTranslator(sqlExpressionFactory),
+ new JetTimeOnlyMemberTranslator(sqlExpressionFactory)
});
}
}
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMethodCallTranslatorProvider.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMethodCallTranslatorProvider.cs
index 5096512..07a424d 100644
--- a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMethodCallTranslatorProvider.cs
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetMethodCallTranslatorProvider.cs
@@ -28,6 +28,7 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal
new JetByteArrayMethodTranslator(sqlExpressionFactory),
new JetConvertTranslator(sqlExpressionFactory),
new JetDateDiffFunctionsTranslator(sqlExpressionFactory),
+ new JetDateOnlyMethodTranslator(sqlExpressionFactory),
new JetDateTimeMethodTranslator(sqlExpressionFactory),
new JetIsDateFunctionTranslator(sqlExpressionFactory),
new JetMathTranslator(sqlExpressionFactory),
@@ -35,6 +36,7 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal
new JetObjectToStringTranslator(sqlExpressionFactory),
new JetStringMethodTranslator(sqlExpressionFactory),
new JetRandomTranslator(sqlExpressionFactory),
+ new JetTimeOnlyMethodTranslator(sqlExpressionFactory)
});
}
}
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMemberTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMemberTranslator.cs
new file mode 100644
index 0000000..1db98dc
--- /dev/null
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMemberTranslator.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Query;
+using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
+
+namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal;
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public class JetTimeOnlyMemberTranslator : IMemberTranslator
+{
+ private static readonly Dictionary DatePartMappings = new()
+ {
+ { nameof(TimeOnly.Hour), "h" },
+ { nameof(TimeOnly.Minute), "n" },
+ { nameof(TimeOnly.Second), "s" },
+ { nameof(TimeOnly.Millisecond), "millisecond" }
+ };
+
+ private readonly ISqlExpressionFactory _sqlExpressionFactory;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public JetTimeOnlyMemberTranslator(ISqlExpressionFactory sqlExpressionFactory)
+ {
+ _sqlExpressionFactory = sqlExpressionFactory;
+ }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual SqlExpression? Translate(
+ SqlExpression? instance,
+ MemberInfo member,
+ Type returnType,
+ IDiagnosticsLogger logger)
+ {
+ if (member.DeclaringType == typeof(TimeOnly) && DatePartMappings.TryGetValue(member.Name, out var value))
+ {
+ return _sqlExpressionFactory.Function(
+ "DATEPART", new[] { _sqlExpressionFactory.Constant(value), instance! },
+ nullable: true,
+ argumentsPropagateNullability: new[] { false, true },
+ returnType);
+ }
+
+ return null;
+ }
+}
diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMethodTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMethodTranslator.cs
new file mode 100644
index 0000000..81eec0e
--- /dev/null
+++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetTimeOnlyMethodTranslator.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Diagnostics;
+using Microsoft.EntityFrameworkCore.Query;
+using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
+using ExpressionExtensions = Microsoft.EntityFrameworkCore.Query.ExpressionExtensions;
+
+namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal;
+
+///
+/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+/// the same compatibility standards as public APIs. It may be changed or removed without notice in
+/// any release. You should only use it directly in your code with extreme caution and knowing that
+/// doing so can result in application failures when updating to a new Entity Framework Core release.
+///
+public class JetTimeOnlyMethodTranslator : IMethodCallTranslator
+{
+ private static readonly MethodInfo AddHoursMethod = typeof(TimeOnly).GetRuntimeMethod(
+ nameof(TimeOnly.AddHours), new[] { typeof(double) })!;
+ private static readonly MethodInfo AddMinutesMethod = typeof(TimeOnly).GetRuntimeMethod(
+ nameof(TimeOnly.AddMinutes), new[] { typeof(double) })!;
+ private static readonly MethodInfo IsBetweenMethod = typeof(TimeOnly).GetRuntimeMethod(
+ nameof(TimeOnly.IsBetween), new[] { typeof(TimeOnly), typeof(TimeOnly) })!;
+
+ private readonly ISqlExpressionFactory _sqlExpressionFactory;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public JetTimeOnlyMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
+ {
+ _sqlExpressionFactory = sqlExpressionFactory;
+ }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public virtual SqlExpression? Translate(
+ SqlExpression? instance,
+ MethodInfo method,
+ IReadOnlyList arguments,
+ IDiagnosticsLogger logger)
+ {
+ if (method.DeclaringType != typeof(TimeOnly) || instance is null)
+ {
+ return null;
+ }
+
+ if (method == AddHoursMethod || method == AddMinutesMethod)
+ {
+ var datePart = method == AddHoursMethod ? "h" : "n";
+
+ // Some Add methods accept a double, and SQL Server DateAdd does not accept number argument outside of int range
+ if (arguments[0] is SqlConstantExpression { Value: double and (<= int.MinValue or >= int.MaxValue) })
+ {
+ return null;
+ }
+
+ instance = _sqlExpressionFactory.ApplyDefaultTypeMapping(instance);
+
+ var dadd = _sqlExpressionFactory.Function(
+ "DATEADD",
+ new[] { _sqlExpressionFactory.Constant(datePart), _sqlExpressionFactory.Convert(arguments[0], typeof(int)), instance },
+ nullable: true,
+ argumentsPropagateNullability: new[] { false, true, true },
+ instance.Type,
+ instance.TypeMapping);
+
+ return _sqlExpressionFactory.Function("TIMEVALUE", new[] { dadd }, true,
+ argumentsPropagateNullability: new[] { true }, instance.Type, instance.TypeMapping);
+ }
+
+ // Translate TimeOnly.IsBetween to a >= b AND a < c.
+ // Since a is evaluated multiple times, only translate for simple constructs (i.e. avoid duplicating complex subqueries).
+ if (method == IsBetweenMethod
+ && instance is ColumnExpression or SqlConstantExpression or SqlParameterExpression)
+ {
+ var typeMapping = ExpressionExtensions.InferTypeMapping(instance, arguments[0], arguments[1]);
+ instance = _sqlExpressionFactory.ApplyTypeMapping(instance, typeMapping);
+
+ return _sqlExpressionFactory.And(
+ _sqlExpressionFactory.GreaterThanOrEqual(
+ instance,
+ _sqlExpressionFactory.ApplyTypeMapping(arguments[0], typeMapping)),
+ _sqlExpressionFactory.LessThan(
+ instance,
+ _sqlExpressionFactory.ApplyTypeMapping(arguments[1], typeMapping)));
+ }
+
+ return null;
+ }
+}
diff --git a/src/EFCore.Jet/Storage/Internal/JetDateOnlyTypeMapping.cs b/src/EFCore.Jet/Storage/Internal/JetDateOnlyTypeMapping.cs
new file mode 100644
index 0000000..d9a33c3
--- /dev/null
+++ b/src/EFCore.Jet/Storage/Internal/JetDateOnlyTypeMapping.cs
@@ -0,0 +1,94 @@
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Data;
+using System.Data.Common;
+using System.Globalization;
+using System.Reflection.Metadata;
+using System.Text;
+using EntityFrameworkCore.Jet.Data;
+using EntityFrameworkCore.Jet.Infrastructure.Internal;
+using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Storage;
+
+namespace EntityFrameworkCore.Jet.Storage.Internal
+{
+ public class JetDateOnlyTypeMapping : DateOnlyTypeMapping
+ {
+ private readonly IJetOptions _options;
+
+ public JetDateOnlyTypeMapping(
+ [NotNull] string storeType,
+ [NotNull] IJetOptions options,
+ DbType? dbType = null)
+ : base(storeType, dbType ?? System.Data.DbType.DateTime)
+ {
+ _options = options;
+ }
+
+ protected JetDateOnlyTypeMapping(RelationalTypeMappingParameters parameters, IJetOptions options)
+ : base(parameters)
+ {
+ _options = options;
+ }
+
+ protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
+ => new JetDateOnlyTypeMapping(parameters, _options);
+
+ protected override void ConfigureParameter(DbParameter parameter)
+ {
+ base.ConfigureParameter(parameter);
+ if (parameter.Value != null)
+ {
+ ((DateOnly)parameter.Value).Deconstruct(out int year, out int month, out int day);
+ parameter.Value = new DateTime(year, month, day);
+ }
+ }
+
+ protected override string GenerateNonNullSqlLiteral(object value)
+ => GenerateNonNullSqlLiteral(value, false);
+
+ public virtual string GenerateNonNullSqlLiteral(object value, bool defaultClauseCompatible)
+ {
+ var dateTime = ConvertToDateTimeCompatibleValue(value);
+
+ dateTime = CheckDateTimeValue(dateTime);
+
+ var literal = new StringBuilder();
+
+ literal.Append(
+ defaultClauseCompatible
+ ? "'"
+ : "#");
+
+ literal.AppendFormat(CultureInfo.InvariantCulture, "{0:yyyy-MM-dd}", dateTime);
+ literal.Append(
+ defaultClauseCompatible
+ ? "'"
+ : "#");
+
+ return literal.ToString();
+ }
+
+ protected virtual DateTime ConvertToDateTimeCompatibleValue(object value)
+ {
+ ((DateOnly)value).Deconstruct(out int year, out int month, out int day);
+ return new DateTime(year, month, day);
+ }
+
+ private static DateTime CheckDateTimeValue(DateTime dateTime)
+ {
+ if (dateTime < JetConfiguration.TimeSpanOffset)
+ {
+ if (dateTime != default)
+ {
+ throw new InvalidOperationException($"The {nameof(DateTime)} value '{dateTime}' is smaller than the minimum supported value of '{JetConfiguration.TimeSpanOffset}'.");
+ }
+
+ dateTime = JetConfiguration.TimeSpanOffset;
+ }
+
+ return dateTime;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/EFCore.Jet/Storage/Internal/JetTimeOnlyTypeMapping.cs b/src/EFCore.Jet/Storage/Internal/JetTimeOnlyTypeMapping.cs
new file mode 100644
index 0000000..7273a25
--- /dev/null
+++ b/src/EFCore.Jet/Storage/Internal/JetTimeOnlyTypeMapping.cs
@@ -0,0 +1,58 @@
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Data;
+using System.Data.Common;
+using EntityFrameworkCore.Jet.Data;
+using EntityFrameworkCore.Jet.Infrastructure.Internal;
+using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Storage;
+
+namespace EntityFrameworkCore.Jet.Storage.Internal
+{
+ public class JetTimeOnlyTypeMapping : TimeOnlyTypeMapping
+ {
+ [NotNull] private readonly IJetOptions _options;
+
+ public JetTimeOnlyTypeMapping(
+ [NotNull] string storeType,
+ [NotNull] IJetOptions options)
+ : base(storeType, System.Data.DbType.DateTime)
+ {
+ _options = options;
+ }
+
+ protected JetTimeOnlyTypeMapping(RelationalTypeMappingParameters parameters, IJetOptions options)
+ : base(parameters)
+ {
+ _options = options;
+ }
+
+ protected override void ConfigureParameter(DbParameter parameter)
+ {
+ base.ConfigureParameter(parameter);
+ if (parameter.Value != null)
+ {
+ ((TimeOnly)parameter.Value).Deconstruct(out int hour, out int min, out int sec);
+ parameter.Value = JetConfiguration.TimeSpanOffset.Add(new TimeSpan(hour, min, sec));
+ }
+ }
+
+ protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
+ => new JetTimeOnlyTypeMapping(parameters, _options);
+
+ protected override string GenerateNonNullSqlLiteral(object value)
+ {
+ //Format time without any milliseconds
+ if (!_options.EnableMillisecondsSupport)
+ {
+ return FormattableString.Invariant($@"TIMEVALUE('{value:HH\:mm\:ss}')");
+ }
+ else
+ {
+ //TODO: Treat as double
+ return "";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs b/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs
index 4ab25bd..012d5f8 100644
--- a/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs
+++ b/src/EFCore.Jet/Storage/Internal/JetTypeMappingSource.cs
@@ -45,8 +45,9 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
private readonly JetDateTimeTypeMapping _datetime;
private readonly JetDateTimeOffsetTypeMapping _datetimeoffset;
- private readonly JetDateTimeTypeMapping _date;
- private readonly JetTimeSpanTypeMapping _time;
+ private readonly JetDateOnlyTypeMapping _dateonly;
+ private readonly JetTimeSpanTypeMapping _timespan;
+ private readonly JetTimeOnlyTypeMapping _timeonly;
private readonly JetStringTypeMapping _fixedLengthUnicodeString = new JetStringTypeMapping("char", unicode: true);
private readonly JetStringTypeMapping _variableLengthUnicodeString = new JetStringTypeMapping("varchar", unicode: true);
@@ -87,8 +88,9 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
_datetime = new JetDateTimeTypeMapping("datetime", options, dbType: DbType.DateTime);
_datetimeoffset = new JetDateTimeOffsetTypeMapping("datetime", options);
- _date = new JetDateTimeTypeMapping("datetime", options, dbType: DbType.Date);
- _time = new JetTimeSpanTypeMapping("datetime", options);
+ _dateonly = new JetDateOnlyTypeMapping("datetime", options, dbType: DbType.Date);
+ _timeonly = new JetTimeOnlyTypeMapping("datetime", options);
+ _timespan = new JetTimeSpanTypeMapping("datetime", options);
_storeTypeMappings
= new Dictionary(StringComparer.OrdinalIgnoreCase)
@@ -147,8 +149,8 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
{"money", _currency},
{"datetime", _datetime},
- {"date", _date},
- {"time", _time},
+ {"date", _dateonly},
+ {"time", _timeonly},
{"char", _fixedLengthUnicodeString},
{"alphanumeric", _fixedLengthUnicodeString},
@@ -195,8 +197,10 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
{typeof(double), _double},
{typeof(decimal), _decimal}, // CHECK: Is this supported or do we need to use CURRENCY?
{typeof(DateTime), _datetime},
+ {typeof(DateOnly), _dateonly},
{typeof(DateTimeOffset), _datetimeoffset},
- {typeof(TimeSpan), _time},
+ {typeof(TimeSpan), _timespan},
+ {typeof(TimeOnly), _timeonly},
{typeof(Guid), _guid},
};
diff --git a/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetFixture.cs b/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetFixture.cs
index 3424d36..8576224 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetFixture.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetFixture.cs
@@ -22,22 +22,11 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query
modelBuilder.Entity().Property(g => g.Location).HasColumnType("varchar(100)");
- /*modelBuilder.Entity(
- b =>
- {
- // Full-text binary search
- b.Property("BriefingDocument");
- b.Property("BriefingDocumentFileExtension").HasColumnType("nvarchar(16)");
- });*/
-
- // No support yet for DateOnly/TimeOnly (#24507)
modelBuilder.Entity(
b =>
{
- b.Ignore(m => m.Date);
- b.Ignore(m => m.Time);
//b.Ignore(m => m.Timeline);
- //b.Ignore(m => m.Duration);
+ // b.Ignore(m => m.Duration);
});
}
diff --git a/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetTest.cs
index 80519fb..6a6ba65 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetTest.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetTest.cs
@@ -6346,12 +6346,8 @@ FROM `Missions` AS `m`
WHERE (({AssertSqlHelper.Parameter("@__start_0")} <= CAST(CONVERT(date, `m`.`Timeline`) AS datetimeoffset)) AND (`m`.`Timeline` < {AssertSqlHelper.Parameter("@__end_1")})) AND `m`.`Timeline` IN ('1902-01-02T10:00:00.1234567+01:30')");
}
- public override async Task DateTimeOffsetNow_minus_timespan(bool async)
- {
- await base.DateTimeOffsetNow_minus_timespan(async);
-
- AssertSql();
- }
+ public override Task DateTimeOffsetNow_minus_timespan(bool async)
+ => AssertTranslationFailed(() => base.DateTimeOffsetNow_minus_timespan(async));
public override async Task Navigation_inside_interpolated_string_expanded(bool isAsync)
{
@@ -7477,7 +7473,7 @@ FROM `Missions` AS `m`
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 DATEPART('h', `m`.`Duration`) = 1
""");
@@ -7489,7 +7485,7 @@ WHERE DATEPART('h', `m`.`Duration`) = 1
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 DATEPART('n', `m`.`Duration`) = 1
""");
@@ -7501,7 +7497,7 @@ WHERE DATEPART('n', `m`.`Duration`) = 1
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 DATEPART('s', `m`.`Duration`) = 1
""");
@@ -7997,19 +7993,27 @@ ORDER BY `g`.`Nickname`, `g`.`SquadId`, `c`.`Name`
await base.FirstOrDefault_on_empty_collection_of_DateTime_in_subquery(async);
AssertSql(
- """
-SELECT `g`.`Nickname`, COALESCE((
- SELECT TOP(1) `t1`.`IssueDate`
- FROM `Tags` AS `t1`
- WHERE `t1`.`GearNickName` = `g`.`FullName`
- ORDER BY `t1`.`Id`), '0001-01-01T00:00:00.0000000') AS `invalidTagIssueDate`
+ """
+SELECT `g`.`Nickname`, IIF((
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t1`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t1`.`Id`)) AS `invalidTagIssueDate`
FROM `Gears` AS `g`
LEFT JOIN `Tags` AS `t` ON `g`.`Nickname` = `t`.`GearNickName` AND `g`.`SquadId` = `t`.`GearSquadId`
-WHERE `t`.`IssueDate` > COALESCE((
- SELECT TOP(1) `t0`.`IssueDate`
- FROM `Tags` AS `t0`
- WHERE `t0`.`GearNickName` = `g`.`FullName`
- ORDER BY `t0`.`Id`), '0001-01-01T00:00:00.0000000')
+WHERE `t`.`IssueDate` > IIF((
+ SELECT TOP 1 `t0`.`IssueDate`
+ FROM `Tags` AS `t0`
+ WHERE `t0`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t0`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t0`.`IssueDate`
+ FROM `Tags` AS `t0`
+ WHERE `t0`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t0`.`Id`))
""");
}
@@ -8506,39 +8510,54 @@ ORDER BY `t`.`Id`, `t1`.`Nickname`, `t1`.`FullName`, `t1`.`HasSoulPatch`
public override async Task Where_DateOnly_Year(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Year(async));
+ await base.Where_DateOnly_Year(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('yyyy', `m`.`Date`) = 1990
+""");
}
public override async Task Where_DateOnly_Month(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Month(async));
+ await base.Where_DateOnly_Month(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('m', `m`.`Date`) = 11
+""");
}
public override async Task Where_DateOnly_Day(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Day(async));
+ await base.Where_DateOnly_Day(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('d', `m`.`Date`) = 10
+""");
}
public override async Task Where_DateOnly_DayOfYear(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_DayOfYear(async));
+ await base.Where_DateOnly_DayOfYear(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('y', `m`.`Date`) = 314
+""");
}
public override async Task Where_DateOnly_DayOfWeek(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_DateOnly_DayOfWeek(async));
AssertSql();
@@ -8546,79 +8565,114 @@ ORDER BY `t`.`Id`, `t1`.`Nickname`, `t1`.`FullName`, `t1`.`HasSoulPatch`
public override async Task Where_DateOnly_AddYears(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddYears(async));
+ await base.Where_DateOnly_AddYears(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('yyyy', CLNG(3), `m`.`Date`) = #1993-11-10#
+""");
}
public override async Task Where_DateOnly_AddMonths(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddMonths(async));
+ await base.Where_DateOnly_AddMonths(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('m', CLNG(3), `m`.`Date`) = #1991-02-10#
+""");
}
public override async Task Where_DateOnly_AddDays(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddDays(async));
+ await base.Where_DateOnly_AddDays(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('d', CLNG(3), `m`.`Date`) = #1990-11-13#
+""");
}
public override async Task Where_TimeOnly_Hour(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Hour(async));
+ await base.Where_TimeOnly_Hour(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('h', `m`.`Time`) = 10
+""");
}
public override async Task Where_TimeOnly_Minute(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Minute(async));
+ await base.Where_TimeOnly_Minute(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('n', `m`.`Time`) = 15
+""");
}
public override async Task Where_TimeOnly_Second(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Second(async));
+ await base.Where_TimeOnly_Second(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('s', `m`.`Time`) = 50
+""");
}
public override async Task Where_TimeOnly_Millisecond(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Millisecond(async));
+ await base.Where_TimeOnly_Millisecond(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT [m].[Id], [m].[BriefingDocument], [m].[BriefingDocumentFileExtension], [m].[CodeName], [m].[Date], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
+FROM [Missions] AS [m]
+WHERE DATEPART(millisecond, [m].[Time]) = 500
+""");
}
public override async Task Where_TimeOnly_AddHours(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddHours(async));
+ await base.Where_TimeOnly_AddHours(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('h', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('13:15:50')
+""");
}
public override async Task Where_TimeOnly_AddMinutes(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddMinutes(async));
+ await base.Where_TimeOnly_AddMinutes(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('n', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('10:18:50')
+""");
}
public override async Task Where_TimeOnly_Add_TimeSpan(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_Add_TimeSpan(async));
AssertSql();
@@ -8626,15 +8680,18 @@ ORDER BY `t`.`Id`, `t1`.`Nickname`, `t1`.`FullName`, `t1`.`HasSoulPatch`
public override async Task Where_TimeOnly_IsBetween(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_IsBetween(async));
+ await base.Where_TimeOnly_IsBetween(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE (IIF(`m`.`Time` >= TIMEVALUE('10:00:00'), TRUE, FALSE) BAND IIF(`m`.`Time` < TIMEVALUE('11:00:00'), TRUE, FALSE)) = TRUE
+""");
}
public override async Task Where_TimeOnly_subtract_TimeOnly(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_subtract_TimeOnly(async));
AssertSql();
@@ -8898,8 +8955,8 @@ ORDER BY `f`.`Id`
await base.Where_equals_method_on_nullable_with_object_overload(async);
AssertSql(
- """
-SELECT `m`.`Id`, `m`.`BriefingDocument`, `m`.`BriefingDocumentFileExtension`, `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 `m`.`Rating` IS NULL
""");
diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs
index 8252ea6..ce78b04 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs
@@ -2318,9 +2318,9 @@ WHERE 0 = 1");
AssertSql(
"""
-SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate]
-FROM [Orders] AS [o]
-WHERE [o].[OrderDate] IS NOT NULL AND CAST([o].[OrderDate] AS date) = '1996-09-16'
+SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate`
+FROM `Orders` AS `o`
+WHERE `o`.`OrderDate` IS NOT NULL AND `o`.`OrderDate` = #1996-09-16#
""");
}
diff --git a/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetFixture.cs b/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetFixture.cs
index 59fd192..faf9202 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetFixture.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetFixture.cs
@@ -27,8 +27,8 @@ public class TPCGearsOfWarQueryJetFixture : TPCGearsOfWarQueryRelationalFixture
modelBuilder.Entity(
b =>
{
- b.Ignore(m => m.Date);
- b.Ignore(m => m.Time);
+ //b.Ignore(m => m.Date);
+ //b.Ignore(m => m.Time);
});
}
diff --git a/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetTest.cs
index e5dba37..69021da 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetTest.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetTest.cs
@@ -10302,10 +10302,10 @@ FROM [Missions] AS [m]
await base.Where_TimeSpan_Hours(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 DATEPART('s', `m`.`Duration`) = 1
+WHERE DATEPART('h', `m`.`Duration`) = 1
""");
}
@@ -10314,8 +10314,8 @@ WHERE DATEPART('s', `m`.`Duration`) = 1
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 DATEPART('n', `m`.`Duration`) = 1
""");
@@ -10326,8 +10326,8 @@ WHERE DATEPART('n', `m`.`Duration`) = 1
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 DATEPART('s', `m`.`Duration`) = 1
""");
@@ -11432,39 +11432,54 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_DateOnly_Year(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Year(async));
+ await base.Where_DateOnly_Year(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('yyyy', `m`.`Date`) = 1990
+""");
}
public override async Task Where_DateOnly_Month(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Month(async));
+ await base.Where_DateOnly_Month(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('m', `m`.`Date`) = 11
+""");
}
public override async Task Where_DateOnly_Day(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Day(async));
+ await base.Where_DateOnly_Day(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('d', `m`.`Date`) = 10
+""");
}
public override async Task Where_DateOnly_DayOfYear(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_DayOfYear(async));
+ await base.Where_DateOnly_DayOfYear(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('y', `m`.`Date`) = 314
+""");
}
public override async Task Where_DateOnly_DayOfWeek(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_DateOnly_DayOfWeek(async));
AssertSql();
@@ -11472,79 +11487,114 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_DateOnly_AddYears(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddYears(async));
+ await base.Where_DateOnly_AddYears(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('yyyy', CLNG(3), `m`.`Date`) = #1993-11-10#
+""");
}
public override async Task Where_DateOnly_AddMonths(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddMonths(async));
+ await base.Where_DateOnly_AddMonths(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('m', CLNG(3), `m`.`Date`) = #1991-02-10#
+""");
}
public override async Task Where_DateOnly_AddDays(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddDays(async));
+ await base.Where_DateOnly_AddDays(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('d', CLNG(3), `m`.`Date`) = #1990-11-13#
+""");
}
public override async Task Where_TimeOnly_Hour(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Hour(async));
+ await base.Where_TimeOnly_Hour(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('h', `m`.`Time`) = 10
+""");
}
public override async Task Where_TimeOnly_Minute(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Minute(async));
+ await base.Where_TimeOnly_Minute(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('n', `m`.`Time`) = 15
+""");
}
public override async Task Where_TimeOnly_Second(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Second(async));
+ await base.Where_TimeOnly_Second(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('s', `m`.`Time`) = 50
+""");
}
public override async Task Where_TimeOnly_Millisecond(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Millisecond(async));
+ await base.Where_TimeOnly_Millisecond(async);
- AssertSql();
+ AssertSql(
+"""
+SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
+FROM [Missions] AS [m]
+WHERE DATEPART(millisecond, [m].[Time]) = 500
+""");
}
public override async Task Where_TimeOnly_AddHours(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddHours(async));
+ await base.Where_TimeOnly_AddHours(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('h', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('13:15:50')
+""");
}
public override async Task Where_TimeOnly_AddMinutes(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddMinutes(async));
+ await base.Where_TimeOnly_AddMinutes(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('n', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('10:18:50')
+""");
}
public override async Task Where_TimeOnly_Add_TimeSpan(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_Add_TimeSpan(async));
AssertSql();
@@ -11552,15 +11602,18 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_TimeOnly_IsBetween(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_IsBetween(async));
+ await base.Where_TimeOnly_IsBetween(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE (IIF(`m`.`Time` >= TIMEVALUE('10:00:00'), TRUE, FALSE) BAND IIF(`m`.`Time` < TIMEVALUE('11:00:00'), TRUE, FALSE)) = TRUE
+""");
}
public override async Task Where_TimeOnly_subtract_TimeOnly(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_subtract_TimeOnly(async));
AssertSql();
@@ -11938,25 +11991,33 @@ WHERE `l`.`ServerAddress` = '127.0.0.1'
await base.FirstOrDefault_on_empty_collection_of_DateTime_in_subquery(async);
AssertSql(
-"""
-SELECT [t].[Nickname], COALESCE((
- SELECT TOP(1) [t2].[IssueDate]
- FROM [Tags] AS [t2]
- WHERE [t2].[GearNickName] = [t].[FullName]
- ORDER BY [t2].[Id]), '0001-01-01T00:00:00.0000000') AS [invalidTagIssueDate]
+ """
+SELECT `t`.`Nickname`, IIF((
+ SELECT TOP 1 `t2`.`IssueDate`
+ FROM `Tags` AS `t2`
+ WHERE `t2`.`GearNickName` = `t`.`FullName`
+ ORDER BY `t2`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t2`.`IssueDate`
+ FROM `Tags` AS `t2`
+ WHERE `t2`.`GearNickName` = `t`.`FullName`
+ ORDER BY `t2`.`Id`)) AS `invalidTagIssueDate`
FROM (
- SELECT [g].[Nickname], [g].[SquadId], [g].[FullName]
- FROM [Gears] AS [g]
+ SELECT `g`.`Nickname`, `g`.`SquadId`, `g`.`FullName`
+ FROM `Gears` AS `g`
UNION ALL
- SELECT [o].[Nickname], [o].[SquadId], [o].[FullName]
- FROM [Officers] AS [o]
-) AS [t]
-LEFT JOIN [Tags] AS [t0] ON [t].[Nickname] = [t0].[GearNickName] AND [t].[SquadId] = [t0].[GearSquadId]
-WHERE [t0].[IssueDate] > COALESCE((
- SELECT TOP(1) [t1].[IssueDate]
- FROM [Tags] AS [t1]
- WHERE [t1].[GearNickName] = [t].[FullName]
- ORDER BY [t1].[Id]), '0001-01-01T00:00:00.0000000')
+ SELECT `o`.`Nickname`, `o`.`SquadId`, `o`.`FullName`
+ FROM `Officers` AS `o`
+) AS `t`
+LEFT JOIN `Tags` AS `t0` ON `t`.`Nickname` = `t0`.`GearNickName` AND `t`.`SquadId` = `t0`.`GearSquadId`
+WHERE `t0`.`IssueDate` > IIF((
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `t`.`FullName`
+ ORDER BY `t1`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `t`.`FullName`
+ ORDER BY `t1`.`Id`))
""");
}
@@ -12101,10 +12162,10 @@ ORDER BY [t].[Nickname], [t].[SquadId]
await base.Where_equals_method_on_nullable_with_object_overload(async);
AssertSql(
-"""
-SELECT [m].[Id], [m].[CodeName], [m].[Duration], [m].[Rating], [m].[Timeline]
-FROM [Missions] AS [m]
-WHERE [m].[Rating] IS NULL
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE `m`.`Rating` IS NULL
""");
}
diff --git a/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetFixture.cs b/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetFixture.cs
index 11f5d4e..52ecd4b 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetFixture.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetFixture.cs
@@ -24,8 +24,8 @@ public class TPTGearsOfWarQueryJetFixture : TPTGearsOfWarQueryRelationalFixture
modelBuilder.Entity(
b =>
{
- b.Ignore(m => m.Date);
- b.Ignore(m => m.Time);
+ //b.Ignore(m => m.Date);
+ //b.Ignore(m => m.Time);
});
}
diff --git a/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetTest.cs
index f363ee8..befcd75 100644
--- a/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetTest.cs
+++ b/test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetTest.cs
@@ -8385,10 +8385,10 @@ FROM [Missions] AS [m]
await base.Where_TimeSpan_Hours(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 DATEPART('n', `m`.`Duration`) = 1
+WHERE DATEPART('h', `m`.`Duration`) = 1
""");
}
@@ -8398,7 +8398,7 @@ WHERE DATEPART('n', `m`.`Duration`) = 1
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 DATEPART('n', `m`.`Duration`) = 1
""");
@@ -8410,7 +8410,7 @@ WHERE DATEPART('n', `m`.`Duration`) = 1
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 DATEPART('s', `m`.`Duration`) = 1
""");
@@ -9259,39 +9259,54 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_DateOnly_Year(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Year(async));
+ await base.Where_DateOnly_Year(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('yyyy', `m`.`Date`) = 1990
+""");
}
public override async Task Where_DateOnly_Month(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Month(async));
+ await base.Where_DateOnly_Month(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('m', `m`.`Date`) = 11
+""");
}
public override async Task Where_DateOnly_Day(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_Day(async));
+ await base.Where_DateOnly_Day(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('d', `m`.`Date`) = 10
+""");
}
public override async Task Where_DateOnly_DayOfYear(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_DayOfYear(async));
+ await base.Where_DateOnly_DayOfYear(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('y', `m`.`Date`) = 314
+""");
}
public override async Task Where_DateOnly_DayOfWeek(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_DateOnly_DayOfWeek(async));
AssertSql();
@@ -9299,79 +9314,114 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_DateOnly_AddYears(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddYears(async));
+ await base.Where_DateOnly_AddYears(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('yyyy', CLNG(3), `m`.`Date`) = #1993-11-10#
+""");
}
public override async Task Where_DateOnly_AddMonths(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddMonths(async));
+ await base.Where_DateOnly_AddMonths(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('m', CLNG(3), `m`.`Date`) = #1991-02-10#
+""");
}
public override async Task Where_DateOnly_AddDays(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_DateOnly_AddDays(async));
+ await base.Where_DateOnly_AddDays(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEADD('d', CLNG(3), `m`.`Date`) = #1990-11-13#
+""");
}
public override async Task Where_TimeOnly_Hour(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Hour(async));
+ await base.Where_TimeOnly_Hour(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('h', `m`.`Time`) = 10
+""");
}
public override async Task Where_TimeOnly_Minute(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Minute(async));
+ await base.Where_TimeOnly_Minute(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('n', `m`.`Time`) = 15
+""");
}
public override async Task Where_TimeOnly_Second(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Second(async));
+ await base.Where_TimeOnly_Second(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE DATEPART('s', `m`.`Time`) = 50
+""");
}
public override async Task Where_TimeOnly_Millisecond(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_Millisecond(async));
+ await base.Where_TimeOnly_Millisecond(async);
- AssertSql();
+ AssertSql(
+"""
+SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
+FROM [Missions] AS [m]
+WHERE DATEPART(millisecond, [m].[Time]) = 500
+""");
}
public override async Task Where_TimeOnly_AddHours(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddHours(async));
+ await base.Where_TimeOnly_AddHours(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('h', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('13:15:50')
+""");
}
public override async Task Where_TimeOnly_AddMinutes(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_AddMinutes(async));
+ await base.Where_TimeOnly_AddMinutes(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE TIMEVALUE(DATEADD('n', CLNG(3.0), `m`.`Time`)) = TIMEVALUE('10:18:50')
+""");
}
public override async Task Where_TimeOnly_Add_TimeSpan(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_Add_TimeSpan(async));
AssertSql();
@@ -9379,15 +9429,18 @@ ORDER BY IIF(`t`.`GearNickName` IS NOT NULL, `t0`.`SquadId`, NULL), `t`.`Note`
public override async Task Where_TimeOnly_IsBetween(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
- await AssertTranslationFailed(() => base.Where_TimeOnly_IsBetween(async));
+ await base.Where_TimeOnly_IsBetween(async);
- AssertSql();
+ AssertSql(
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE (IIF(`m`.`Time` >= TIMEVALUE('10:00:00'), TRUE, FALSE) BAND IIF(`m`.`Time` < TIMEVALUE('11:00:00'), TRUE, FALSE)) = TRUE
+""");
}
public override async Task Where_TimeOnly_subtract_TimeOnly(bool async)
{
- // DateOnly and TimeOnly. Issue #24507.
await AssertTranslationFailed(() => base.Where_TimeOnly_subtract_TimeOnly(async));
AssertSql();
@@ -9674,19 +9727,27 @@ WHERE `f`.`ServerAddress` = '127.0.0.1'
await base.FirstOrDefault_on_empty_collection_of_DateTime_in_subquery(async);
AssertSql(
-"""
-SELECT [g].[Nickname], COALESCE((
- SELECT TOP(1) [t1].[IssueDate]
- FROM [Tags] AS [t1]
- WHERE [t1].[GearNickName] = [g].[FullName]
- ORDER BY [t1].[Id]), '0001-01-01T00:00:00.0000000') AS [invalidTagIssueDate]
-FROM [Gears] AS [g]
-LEFT JOIN [Tags] AS [t] ON [g].[Nickname] = [t].[GearNickName] AND [g].[SquadId] = [t].[GearSquadId]
-WHERE [t].[IssueDate] > COALESCE((
- SELECT TOP(1) [t0].[IssueDate]
- FROM [Tags] AS [t0]
- WHERE [t0].[GearNickName] = [g].[FullName]
- ORDER BY [t0].[Id]), '0001-01-01T00:00:00.0000000')
+ """
+SELECT `g`.`Nickname`, IIF((
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t1`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t1`.`IssueDate`
+ FROM `Tags` AS `t1`
+ WHERE `t1`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t1`.`Id`)) AS `invalidTagIssueDate`
+FROM `Gears` AS `g`
+LEFT JOIN `Tags` AS `t` ON `g`.`Nickname` = `t`.`GearNickName` AND `g`.`SquadId` = `t`.`GearSquadId`
+WHERE `t`.`IssueDate` > IIF((
+ SELECT TOP 1 `t0`.`IssueDate`
+ FROM `Tags` AS `t0`
+ WHERE `t0`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t0`.`Id`) IS NULL, #1899-12-30#, (
+ SELECT TOP 1 `t0`.`IssueDate`
+ FROM `Tags` AS `t0`
+ WHERE `t0`.`GearNickName` = `g`.`FullName`
+ ORDER BY `t0`.`Id`))
""");
}
@@ -9825,10 +9886,10 @@ ORDER BY [g].[Nickname], [g].[SquadId]
await base.Where_equals_method_on_nullable_with_object_overload(async);
AssertSql(
-"""
-SELECT [m].[Id], [m].[CodeName], [m].[Duration], [m].[Rating], [m].[Timeline]
-FROM [Missions] AS [m]
-WHERE [m].[Rating] IS NULL
+ """
+SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
+FROM `Missions` AS `m`
+WHERE `m`.`Rating` IS NULL
""");
}