예제 #1
0
        /// <summary>
        ///     Translates the given method call expression.
        /// </summary>
        /// <param name="methodCallExpression">The method call expression.</param>
        /// <param name="logger"> The logger. </param>
        /// <returns>
        ///     A SQL expression representing the translated MethodCallExpression.
        /// </returns>
        public virtual Expression Translate(
            MethodCallExpression methodCallExpression,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            var method = methodCallExpression.Method;

            Expression modifier = null;

            if (Equals(method, _addMilliseconds))
            {
                modifier = Expression.Add(
                    new ExplicitCastExpression(
                        Expression.Divide(
                            methodCallExpression.Arguments[0],
                            Expression.Convert(
                                Expression.Constant(1000),
                                typeof(double))),
                        typeof(string)),
                    Expression.Constant(" seconds"),
                    _concat);
            }
            else if (Equals(method, _addTicks))
            {
                modifier = Expression.Add(
                    new ExplicitCastExpression(
                        Expression.Divide(
                            Expression.Convert(
                                methodCallExpression.Arguments[0],
                                typeof(double)),
                            Expression.Constant((double)TimeSpan.TicksPerSecond)),
                        typeof(string)),
                    Expression.Constant(" seconds"),
                    _concat);
            }
            else if (_methodInfoToUnitSuffix.TryGetValue(method, out var unitSuffix))
            {
                modifier = Expression.Add(
                    new ExplicitCastExpression(
                        methodCallExpression.Arguments[0],
                        typeof(string)),
                    Expression.Constant(unitSuffix),
                    _concat);
            }
            else
            {
                return(null);
            }

            Debug.Assert(modifier != null);

            return(new SqlFunctionExpression(
                       "rtrim",
                       typeof(DateTime),
                       new Expression[]
            {
                new SqlFunctionExpression(
                    "rtrim",
                    typeof(DateTime),
                    new Expression[]
                {
                    SqliteExpression.Strftime(
                        typeof(DateTime),
                        "%Y-%m-%d %H:%M:%f",
                        methodCallExpression.Object,
                        new[] { modifier }),
                    Expression.Constant("0")
                }),
                Expression.Constant(".")
            }));
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual Expression Translate(MemberExpression memberExpression)
        {
            if (memberExpression.Member.DeclaringType != typeof(DateTime))
            {
                return(null);
            }

            var memberName = memberExpression.Member.Name;

            if (memberName == nameof(DateTime.Millisecond))
            {
                return(Expression.Modulo(
                           Expression.Convert(
                               Expression.Multiply(
                                   new ExplicitCastExpression(
                                       SqliteExpression.Strftime(
                                           typeof(string),
                                           "%f",
                                           memberExpression.Expression),
                                       typeof(double)),
                                   Expression.Convert(
                                       Expression.Constant(1000),
                                       typeof(double))),
                               typeof(int)),
                           Expression.Constant(1000)));
            }

            if (memberName == nameof(DateTime.Ticks))
            {
                return(new ExplicitCastExpression(
                           Expression.Multiply(
                               Expression.Subtract(
                                   new SqlFunctionExpression(
                                       "julianday",
                                       typeof(double),
                                       new[] { memberExpression.Expression }),
                                   Expression.Constant(1721425.5)), // NB: Result of julianday('0001-01-01 00:00:00')
                               Expression.Convert(
                                   Expression.Constant(TimeSpan.TicksPerDay),
                                   typeof(double))),
                           typeof(long)));
            }

            if (_datePartMapping.TryGetValue(memberName, out var datePart))
            {
                return(new ExplicitCastExpression(
                           SqliteExpression.Strftime(
                               typeof(string),
                               datePart,
                               memberExpression.Expression),
                           memberExpression.Type));
            }

            string     format     = null;
            Expression timestring = null;
            var        modifiers  = new List <Expression>();

            var datetimeFormat = "%Y-%m-%d %H:%M:%f";

            switch (memberName)
            {
            case nameof(DateTime.Now):
                format     = datetimeFormat;
                timestring = Expression.Constant("now");
                modifiers.Add(Expression.Constant("localtime"));
                break;

            case nameof(DateTime.UtcNow):
                format     = datetimeFormat;
                timestring = Expression.Constant("now");
                break;

            case nameof(DateTime.Date):
                format     = datetimeFormat;
                timestring = memberExpression.Expression;
                modifiers.Add(Expression.Constant("start of day"));
                break;

            case nameof(DateTime.Today):
                format     = datetimeFormat;
                timestring = Expression.Constant("now");
                modifiers.Add(Expression.Constant("localtime"));
                modifiers.Add(Expression.Constant("start of day"));
                break;

            case nameof(DateTime.TimeOfDay):
                format     = "%H:%M:%f";
                timestring = memberExpression.Expression;
                break;

            default:
                return(null);
            }

            Debug.Assert(format != null);
            Debug.Assert(timestring != null);

            return(new SqlFunctionExpression(
                       "rtrim",
                       memberExpression.Type,
                       new Expression[]
            {
                new SqlFunctionExpression(
                    "rtrim",
                    memberExpression.Type,
                    new Expression[]
                {
                    SqliteExpression.Strftime(
                        memberExpression.Type,
                        format,
                        timestring,
                        modifiers),
                    Expression.Constant("0")
                }),
                Expression.Constant(".")
            }));
        }