Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DATEFROMPARTS function to SqlServer #19400

Merged
merged 11 commits into from
Jan 8, 2020
112 changes: 112 additions & 0 deletions src/EFCore.SqlServer/Extensions/SqlServerDbFunctionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,5 +1007,117 @@ public static DateTime DateTimeFromParts(
int second,
int millisecond)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTimeFromParts)));

/// <summary>
/// Initializes a new instance of the <see cref="DateTime" /> structure to the specified year, month, day.
/// Corresponds to the SQL Server's DATEFROMPARTS(year, month, day).
/// </summary>
/// <param name="_">The DbFunctions instance.</param>
/// <param name="year">The year (1753 through 9999).</param>
/// <param name="month">The month (1 through 12).</param>
/// <param name="day">The day (1 through the number of days in month).</param>
/// <returns>New instance of the <see cref="DateTime" /> structure to the specified year, month, day.</returns>
public static DateTime DateFromParts(
[CanBeNull] this DbFunctions _,
int year,
int month,
int day)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateFromParts)));

/// <summary>
/// Initializes a new instance of the <see cref="DateTime" /> structure to the specified year, month, day, hour, minute, second, fractions, and precision.
/// Corresponds to the SQL Server's DATETIME2FROMPARTS (year, month, day, hour, minute, seconds, fractions, precision).
/// </summary>
/// <param name="_">The DbFunctions instance.</param>
/// <param name="year">The year (1753 through 9999).</param>
/// <param name="month">The month (1 through 12).</param>
/// <param name="day">The day (1 through the number of days in month).</param>
/// <param name="hour">The hours (0 through 23).</param>
/// <param name="minute">The minutes (0 through 59).</param>
/// <param name="second">The seconds (0 through 59).</param>
/// <param name="fractions">The fractional seconds (0 through 9999999).</param>
/// <param name="precision">The precision of the datetime2 value (0 through 7).</param>
/// <returns>New instance of the <see cref="DateTime" /> structure to the specified year, month, day, hour, minute, second, fractions, and precision.</returns>
public static DateTime DateTime2FromParts(
[CanBeNull] this DbFunctions _,
int year,
int month,
int day,
int hour,
int minute,
int second,
int fractions,
int precision)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTime2FromParts)));

/// <summary>
/// Initializes a new instance of the <see cref="DateTimeOffset" /> structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision.
/// Corresponds to the SQL Server's DATETIMEOFFSETFROMPARTS (year, month, day, hour, minute, seconds, fractions, hour_offset, minute_offset, precision).
/// </summary>
/// <param name="_">The DbFunctions instance.</param>
/// <param name="year">The year (1753 through 9999).</param>
/// <param name="month">The month (1 through 12).</param>
/// <param name="day">The day (1 through the number of days in month).</param>
/// <param name="hour">The hours (0 through 23).</param>
/// <param name="minute">The minutes (0 through 59).</param>
/// <param name="second">The seconds (0 through 59).</param>
/// <param name="fractions">The fractional seconds (0 through 9999999).</param>
/// <param name="hourOffset">The hour portion of the time zone offset (-14 through +14).</param>
/// <param name="minuteOffset">The minute portion of the time zone offset (0 or 30).</param>
/// <param name="precision">The precision of the datetimeoffset value (0 through 7).</param>
/// <returns>New instance of the <see cref="DateTimeOffset" /> structure to the specified year, month, day, hour, minute, second, fractions, hourOffset, minuteOffset and precision.</returns>
public static DateTimeOffset DateTimeOffsetFromParts(
[CanBeNull] this DbFunctions _,
int year,
int month,
int day,
int hour,
int minute,
int second,
int fractions,
int hourOffset,
int minuteOffset,
int precision)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(DateTimeOffsetFromParts)));

/// <summary>
/// Initializes a new instance of the <see cref="DateTime" /> structure to the specified year, month, day, hour and minute.
/// Corresponds to the SQL Server's SMALLDATETIMEFROMPARTS (year, month, day, hour, minute).
/// </summary>
/// <param name="_">The DbFunctions instance.</param>
/// <param name="year">The year (1753 through 9999).</param>
/// <param name="month">The month (1 through 12).</param>
/// <param name="day">The day (1 through the number of days in month).</param>
/// <param name="hour">The hours (0 through 23).</param>
/// <param name="minute">The minutes (0 through 59).</param>
/// <returns>New instance of the <see cref="DateTime" /> structure to the specified year, month, day, hour and minute.</returns>
public static DateTime SmallDateTimeFromParts(
[CanBeNull] this DbFunctions _,
int year,
int month,
int day,
int hour,
int minute)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(SmallDateTimeFromParts)));

/// <summary>
/// Initializes a new instance of the <see cref="TimeSpan" /> structure to the specified hour, minute, second, fractions, and precision.
/// Corresponds to the SQL Server's TIMEFROMPARTS (hour, minute, seconds, fractions, precision).
/// </summary>
/// <param name="_">The DbFunctions instance.</param>
/// <param name="hour">The hours (0 through 23).</param>
/// <param name="minute">The minutes (0 through 59).</param>
/// <param name="second">The seconds (0 through 59).</param>
/// <param name="fractions">The fractional seconds (0 through 9999999).</param>
/// <param name="precision">The precision of the time value (0 through 7).</param>
/// <returns>New instance of the <see cref="TimeSpan" /> structure to the specified hour, minute, second, fractions, and precision.</returns>
public static TimeSpan TimeFromParts(
[CanBeNull] this DbFunctions _,
int hour,
int minute,
int second,
int fractions,
int precision)
=> throw new InvalidOperationException(SqlServerStrings.FunctionOnClient(nameof(TimeFromParts)));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Storage;

namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal
{
public class SqlServerFromPartsFunctionTranslator : IMethodCallTranslator
{
private readonly ISqlExpressionFactory _sqlExpressionFactory;
private readonly IRelationalTypeMappingSource _typeMappingSource;

private static readonly MethodInfo _dateFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int) });

private static readonly MethodInfo _dateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });

private static readonly MethodInfo _dateTime2FromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTime2FromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });

private static readonly MethodInfo _dateTimeOffsetFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.DateTimeOffsetFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });

private static readonly MethodInfo _smallDateTimeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.SmallDateTimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });

private static readonly MethodInfo _timeFromPartsMethodInfo = typeof(SqlServerDbFunctionsExtensions)
.GetRuntimeMethod(nameof(SqlServerDbFunctionsExtensions.TimeFromParts), new[] { typeof(DbFunctions), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int) });

public SqlServerFromPartsFunctionTranslator(
[NotNull] ISqlExpressionFactory sqlExpressionFactory,
[NotNull] IRelationalTypeMappingSource typeMappingSource)
{
_sqlExpressionFactory = sqlExpressionFactory;
_typeMappingSource = typeMappingSource;
}

public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments)
{
if (_dateFromPartsMethodInfo.Equals(method))
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor to set function name and return server type using case block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Should I create a new PR for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do it. I may have small clean up tasks in other unrelated PRs too.

return _sqlExpressionFactory.Function(
"DATEFROMPARTS",
arguments.Skip(1),
_dateFromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(DateTime), "date"));
}

if (_dateTimeFromPartsMethodInfo.Equals(method))
{
return _sqlExpressionFactory.Function(
"DATETIMEFROMPARTS",
arguments.Skip(1),
_dateTimeFromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(DateTime), "datetime"));
}

if (_dateTime2FromPartsMethodInfo.Equals(method))
{
return _sqlExpressionFactory.Function(
"DATETIME2FROMPARTS",
arguments.Skip(1),
_dateTime2FromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(DateTime), "datetime2"));
}

if (_dateTimeOffsetFromPartsMethodInfo.Equals(method))
{
return _sqlExpressionFactory.Function(
"DATETIMEOFFSETFROMPARTS",
arguments.Skip(1),
_dateTimeOffsetFromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(DateTimeOffset), "datetimeoffset"));
}

if (_smallDateTimeFromPartsMethodInfo.Equals(method))
{
return _sqlExpressionFactory.Function(
"SMALLDATETIMEFROMPARTS",
arguments.Skip(1),
_smallDateTimeFromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(DateTime), "smalldatetime"));
}

if (_timeFromPartsMethodInfo.Equals(method))
{
return _sqlExpressionFactory.Function(
"TIMEFROMPARTS",
arguments.Skip(1),
_timeFromPartsMethodInfo.ReturnType,
_typeMappingSource.FindMapping(typeof(TimeSpan), "time"));
}

return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;

namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal
{
Expand All @@ -20,14 +19,14 @@ public SqlServerMethodCallTranslatorProvider([NotNull] RelationalMethodCallTrans
new SqlServerByteArrayMethodTranslator(sqlExpressionFactory),
new SqlServerConvertTranslator(sqlExpressionFactory),
new SqlServerDateDiffFunctionsTranslator(sqlExpressionFactory),
new SqlServerDateTimeFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource),
new SqlServerDateTimeMethodTranslator(sqlExpressionFactory),
new SqlServerFromPartsFunctionTranslator(sqlExpressionFactory, typeMappingSource),
new SqlServerFullTextSearchFunctionsTranslator(sqlExpressionFactory),
new SqlServerIsDateFunctionTranslator(sqlExpressionFactory),
new SqlServerMathTranslator(sqlExpressionFactory),
new SqlServerNewGuidTranslator(sqlExpressionFactory),
new SqlServerObjectToStringTranslator(sqlExpressionFactory),
new SqlServerStringMethodTranslator(sqlExpressionFactory)
new SqlServerStringMethodTranslator(sqlExpressionFactory),
});
}
}
Expand Down
Loading