Problem
The provider translates no DateTime members and no DateTime methods. Only a direct comparison works.
EF Core's base RelationalMemberTranslatorProvider registers no built-in translators. It adds plugins only (RelationalMemberTranslatorProvider.cs:22). ClickHouseMemberTranslatorProvider adds ClickHouseArrayMethodTranslator and ClickHouseStringMethodTranslator only. No date/time translator exists.
Measured behaviour
Tested against a real ClickHouse server, on a DateTime property with column type DateTime64(6, 'UTC'):
| Expression |
Result |
.Year .Month .Day .Hour .Minute |
InvalidOperationException: The LINQ expression ... could not be translated |
.Date .DayOfWeek .DayOfYear .TimeOfDay |
same |
.AddDays(1) .AddMonths(1) |
same |
DateTime.UtcNow / DateTime.Now / DateTime.Today |
same |
dt - dt (result is TimeSpan) |
InvalidCastException: Unable to cast object of type 'System.TimeSpan' to type 'System.DateTime' |
ts > new DateTime(2020, 1, 1) |
works: WHERE `d`.`ts` > '2020-01-01 00:00:00.000000' |
The dt - dt result is different from the others. It gives an InvalidCastException instead of a clear "could not be translated" message. This looks like a defect, not only a missing feature.
Suggested work
Add one shared date/time member translator. Give it the CLR type as a parameter so that it serves DateTime, DateOnly, and DateTimeOffset from the same class. Npgsql uses this shape (NpgsqlDateTimeMemberTranslator).
ClickHouse functions to map:
| Member |
ClickHouse function |
.Year |
toYear |
.Month |
toMonth |
.Day |
toDayOfMonth |
.Hour |
toHour |
.Minute |
toMinute |
.Second |
toSecond |
.DayOfYear |
toDayOfYear |
.DayOfWeek |
toDayOfWeek (note: ClickHouse counts Monday as 1, .NET counts Sunday as 0) |
.Date |
toStartOfDay |
.AddDays / .AddMonths / .AddYears |
date_add |
DateTime.UtcNow |
now64 |
Also translate the DateTime difference to date_diff, or give a clear "not supported" message.
Take care with two ClickHouse behaviours:
toDayOfWeek starts at Monday = 1. .NET DayOfWeek starts at Sunday = 0. The translation must adjust the value, in the same way the string translators adjust the 0-based to 1-based index.
- These functions read the column timezone. For a
DateTimeOffset property the result must stay consistent with the UTC instant that the column holds.
Notes
Found while I investigated #53. DateTimeOffset needs the same translators, so one shared class is better than a DateTimeOffset-only class. #53 itself needs comparison support only, which already works.
Problem
The provider translates no
DateTimemembers and noDateTimemethods. Only a direct comparison works.EF Core's base
RelationalMemberTranslatorProviderregisters no built-in translators. It adds plugins only (RelationalMemberTranslatorProvider.cs:22).ClickHouseMemberTranslatorProvideraddsClickHouseArrayMethodTranslatorandClickHouseStringMethodTranslatoronly. No date/time translator exists.Measured behaviour
Tested against a real ClickHouse server, on a
DateTimeproperty with column typeDateTime64(6, 'UTC'):.Year.Month.Day.Hour.MinuteInvalidOperationException: The LINQ expression ... could not be translated.Date.DayOfWeek.DayOfYear.TimeOfDay.AddDays(1).AddMonths(1)DateTime.UtcNow/DateTime.Now/DateTime.Todaydt - dt(result isTimeSpan)InvalidCastException: Unable to cast object of type 'System.TimeSpan' to type 'System.DateTime'ts > new DateTime(2020, 1, 1)WHERE `d`.`ts` > '2020-01-01 00:00:00.000000'The
dt - dtresult is different from the others. It gives anInvalidCastExceptioninstead of a clear "could not be translated" message. This looks like a defect, not only a missing feature.Suggested work
Add one shared date/time member translator. Give it the CLR type as a parameter so that it serves
DateTime,DateOnly, andDateTimeOffsetfrom the same class. Npgsql uses this shape (NpgsqlDateTimeMemberTranslator).ClickHouse functions to map:
.YeartoYear.MonthtoMonth.DaytoDayOfMonth.HourtoHour.MinutetoMinute.SecondtoSecond.DayOfYeartoDayOfYear.DayOfWeektoDayOfWeek(note: ClickHouse counts Monday as 1, .NET counts Sunday as 0).DatetoStartOfDay.AddDays/.AddMonths/.AddYearsdate_addDateTime.UtcNownow64Also translate the
DateTimedifference todate_diff, or give a clear "not supported" message.Take care with two ClickHouse behaviours:
toDayOfWeekstarts at Monday = 1. .NETDayOfWeekstarts at Sunday = 0. The translation must adjust the value, in the same way the string translators adjust the 0-based to 1-based index.DateTimeOffsetproperty the result must stay consistent with the UTC instant that the column holds.Notes
Found while I investigated #53.
DateTimeOffsetneeds the same translators, so one shared class is better than aDateTimeOffset-only class. #53 itself needs comparison support only, which already works.