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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public class JetTimeOnlyMethodTranslator : IMethodCallTranslator
nameof(TimeOnly.AddMinutes), new[] { typeof(double) })!;
private static readonly MethodInfo IsBetweenMethod = typeof(TimeOnly).GetRuntimeMethod(
nameof(TimeOnly.IsBetween), new[] { typeof(TimeOnly), typeof(TimeOnly) })!;
private static readonly MethodInfo FromDateTime = typeof(TimeOnly).GetRuntimeMethod(
nameof(TimeOnly.FromDateTime), [typeof(DateTime)])!;

private static readonly MethodInfo FromTimeSpan = typeof(TimeOnly).GetRuntimeMethod(
nameof(TimeOnly.FromTimeSpan), [typeof(TimeSpan)])!;

private readonly ISqlExpressionFactory _sqlExpressionFactory;

Expand All @@ -52,7 +57,19 @@ public JetTimeOnlyMethodTranslator(ISqlExpressionFactory sqlExpressionFactory)
IReadOnlyList<SqlExpression> arguments,
IDiagnosticsLogger<DbLoggerCategory.Query> logger)
{
if (method.DeclaringType != typeof(TimeOnly) || instance is null)
if (method.DeclaringType != typeof(TimeOnly))
{
return null;
}

if ((method == FromDateTime || method == FromTimeSpan)
&& instance is null
&& arguments.Count == 1)
{
return _sqlExpressionFactory.Convert(arguments[0], typeof(TimeOnly));
}

if (instance is null)
{
return null;
}
Expand Down
11 changes: 10 additions & 1 deletion src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class JetQuerySqlGenerator : QuerySqlGenerator, IJetExpressionVisitor
{ nameof(Double), "CDBL" },
{ nameof(Decimal), "CDEC" },
{ nameof(DateTime), "CDATE" },
{ nameof(TimeOnly), "TIMEVALUE" },
};

private readonly ITypeMappingSource _typeMappingSource;
Expand Down Expand Up @@ -510,6 +511,14 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
Sql.Append(")");
return sqlParameterExpression;
}
if (sqlParameterExpression.Type == typeof(TimeOnly) && sqlParameterExpression.TypeMapping is JetTimeOnlyTypeMapping)
{
Sql.Append("TIMEVALUE(");
base.VisitSqlParameter(sqlParameterExpression);
Sql.Append(")");
return sqlParameterExpression;
}


//GroupBy_param_Select_Sum_Min_Key_Max_Avg
//Subquery has parameter as a projection with alias
Expand Down Expand Up @@ -742,7 +751,7 @@ protected Expression VisitJetConvertExpression(SqlUnaryExpression convertExpress
return convertExpression;
}

protected override string GetOperator([JetBrains.Annotations.NotNull] SqlBinaryExpression binaryExpression)
protected override string GetOperator(SqlBinaryExpression binaryExpression)
=> binaryExpression.OperatorType switch
{
ExpressionType.Add when binaryExpression.Type == typeof(string) => " & ",
Expand Down
24 changes: 24 additions & 0 deletions test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13114,6 +13114,14 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeO
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_AddHours(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_IsBetween(async: False)
Expand Down Expand Up @@ -20188,6 +20196,14 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_Ti
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_AddHours(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_IsBetween(async: False)
Expand Down Expand Up @@ -22021,6 +22037,14 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_Ti
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_AddHours(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_AddMinutes(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_constant(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromDateTime_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_FromTimeSpan_compared_to_property(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_Hour(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_IsBetween(async: False)
Expand Down
36 changes: 18 additions & 18 deletions test/EFCore.Jet.FunctionalTests/Query/GearsOfWarQueryJetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8925,11 +8925,11 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_property(bool
await base.Where_TimeOnly_FromDateTime_compared_to_property(async);

AssertSql(
"""
SELECT [t].[Id] AS [TagId], [m].[Id] AS [MissionId]
FROM [Tags] AS [t]
CROSS JOIN [Missions] AS [m]
WHERE CAST([t].[IssueDate] AS time) = [m].[Time]
"""
SELECT `t`.`Id` AS `TagId`, `m`.`Id` AS `MissionId`
FROM `Tags` AS `t`,
`Missions` AS `m`
WHERE TIMEVALUE(`t`.`IssueDate`) = `m`.`Time`
""");
}

Expand All @@ -8953,10 +8953,10 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_constant(bool
await base.Where_TimeOnly_FromDateTime_compared_to_constant(async);

AssertSql(
"""
SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note]
FROM [Tags] AS [t]
WHERE CAST(DATEADD(hour, CAST(CAST(CAST(LEN([t].[Note]) AS int) AS float) AS int), [t].[IssueDate]) AS time) > '09:00:00'
"""
SELECT `t`.`Id`, `t`.`GearNickName`, `t`.`GearSquadId`, `t`.`IssueDate`, `t`.`Note`
FROM `Tags` AS `t`
WHERE IIF(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`) IS NULL, NULL, TIMEVALUE(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`))) > TIMEVALUE('09:00:00')
""");
}

Expand All @@ -8965,10 +8965,10 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_property(bool
await base.Where_TimeOnly_FromTimeSpan_compared_to_property(async);

AssertSql(
"""
SELECT [m].[Id], [m].[BriefingDocument], [m].[BriefingDocumentFileExtension], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) < [m].[Time]
"""
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) < `m`.`Time`
""");
}

Expand All @@ -8977,12 +8977,12 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_parameter(boo
await base.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async);

AssertSql(
"""
@__time_0='01:02' (DbType = Time)
"""
@__time_0='01:02:03'

SELECT [m].[Id], [m].[BriefingDocument], [m].[BriefingDocumentFileExtension], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) = @__time_0
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) = TIMEVALUE(@__time_0)
""");
}

Expand Down
36 changes: 18 additions & 18 deletions test/EFCore.Jet.FunctionalTests/Query/TPCGearsOfWarQueryJetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11821,11 +11821,11 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_property(bool
await base.Where_TimeOnly_FromDateTime_compared_to_property(async);

AssertSql(
"""
SELECT [t].[Id] AS [TagId], [m].[Id] AS [MissionId]
FROM [Tags] AS [t]
CROSS JOIN [Missions] AS [m]
WHERE CAST([t].[IssueDate] AS time) = [m].[Time]
"""
SELECT `t`.`Id` AS `TagId`, `m`.`Id` AS `MissionId`
FROM `Tags` AS `t`,
`Missions` AS `m`
WHERE TIMEVALUE(`t`.`IssueDate`) = `m`.`Time`
""");
}

Expand Down Expand Up @@ -11855,10 +11855,10 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_constant(bool
await base.Where_TimeOnly_FromDateTime_compared_to_constant(async);

AssertSql(
"""
SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note]
FROM [Tags] AS [t]
WHERE CAST(DATEADD(hour, CAST(CAST(CAST(LEN([t].[Note]) AS int) AS float) AS int), [t].[IssueDate]) AS time) > '09:00:00'
"""
SELECT `t`.`Id`, `t`.`GearNickName`, `t`.`GearSquadId`, `t`.`IssueDate`, `t`.`Note`
FROM `Tags` AS `t`
WHERE IIF(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`) IS NULL, NULL, TIMEVALUE(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`))) > TIMEVALUE('09:00:00')
""");
}

Expand All @@ -11867,10 +11867,10 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_property(bool
await base.Where_TimeOnly_FromTimeSpan_compared_to_property(async);

AssertSql(
"""
SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) < [m].[Time]
"""
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) < `m`.`Time`
""");
}

Expand All @@ -11879,12 +11879,12 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_parameter(boo
await base.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async);

AssertSql(
"""
@__time_0='01:02' (DbType = Time)
"""
@__time_0='01:02:03'

SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) = @__time_0
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) = TIMEVALUE(@__time_0)
""");
}

Expand Down
36 changes: 18 additions & 18 deletions test/EFCore.Jet.FunctionalTests/Query/TPTGearsOfWarQueryJetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9522,11 +9522,11 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_property(bool
await base.Where_TimeOnly_FromDateTime_compared_to_property(async);

AssertSql(
"""
SELECT [t].[Id] AS [TagId], [m].[Id] AS [MissionId]
FROM [Tags] AS [t]
CROSS JOIN [Missions] AS [m]
WHERE CAST([t].[IssueDate] AS time) = [m].[Time]
"""
SELECT `t`.`Id` AS `TagId`, `m`.`Id` AS `MissionId`
FROM `Tags` AS `t`,
`Missions` AS `m`
WHERE TIMEVALUE(`t`.`IssueDate`) = `m`.`Time`
""");
}

Expand All @@ -9553,10 +9553,10 @@ public override async Task Where_TimeOnly_FromDateTime_compared_to_constant(bool
await base.Where_TimeOnly_FromDateTime_compared_to_constant(async);

AssertSql(
"""
SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note]
FROM [Tags] AS [t]
WHERE CAST(DATEADD(hour, CAST(CAST(CAST(LEN([t].[Note]) AS int) AS float) AS int), [t].[IssueDate]) AS time) > '09:00:00'
"""
SELECT `t`.`Id`, `t`.`GearNickName`, `t`.`GearSquadId`, `t`.`IssueDate`, `t`.`Note`
FROM `Tags` AS `t`
WHERE IIF(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`) IS NULL, NULL, TIMEVALUE(DATEADD('h', CDBL(IIF(LEN(`t`.`Note`) IS NULL, NULL, CLNG(LEN(`t`.`Note`)))), `t`.`IssueDate`))) > TIMEVALUE('09:00:00')
""");
}

Expand All @@ -9565,10 +9565,10 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_property(bool
await base.Where_TimeOnly_FromTimeSpan_compared_to_property(async);

AssertSql(
"""
SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) < [m].[Time]
"""
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) < `m`.`Time`
""");
}

Expand All @@ -9577,12 +9577,12 @@ public override async Task Where_TimeOnly_FromTimeSpan_compared_to_parameter(boo
await base.Where_TimeOnly_FromTimeSpan_compared_to_parameter(async);

AssertSql(
"""
@__time_0='01:02' (DbType = Time)
"""
@__time_0='01:02:03'

SELECT [m].[Id], [m].[CodeName], [m].[Date], [m].[Difficulty], [m].[Duration], [m].[Rating], [m].[Time], [m].[Timeline]
FROM [Missions] AS [m]
WHERE CAST([m].[Duration] AS time) = @__time_0
SELECT `m`.`Id`, `m`.`CodeName`, `m`.`Date`, `m`.`Difficulty`, `m`.`Duration`, `m`.`Rating`, `m`.`Time`, `m`.`Timeline`
FROM `Missions` AS `m`
WHERE TIMEVALUE(`m`.`Duration`) = TIMEVALUE(@__time_0)
""");
}

Expand Down