public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments)
        {
            if (method == IPAddressParse)
            {
                return(_sqlExpressionFactory.Convert(arguments[0], typeof(IPAddress), _sqlExpressionFactory.FindMapping(typeof(IPAddress))));
            }

            if (method == PhysicalAddressParse)
            {
                return(_sqlExpressionFactory.Convert(arguments[0], typeof(PhysicalAddress), _sqlExpressionFactory.FindMapping(typeof(PhysicalAddress))));
            }

            if (method.DeclaringType != typeof(NpgsqlNetworkExtensions))
            {
                return(null);
            }

            return(method.Name switch
            {
                nameof(NpgsqlNetworkExtensions.LessThan) => _sqlExpressionFactory.LessThan(arguments[1], arguments[2]),
                nameof(NpgsqlNetworkExtensions.LessThanOrEqual) => _sqlExpressionFactory.LessThanOrEqual(arguments[1], arguments[2]),
                nameof(NpgsqlNetworkExtensions.GreaterThanOrEqual) => _sqlExpressionFactory.GreaterThanOrEqual(arguments[1], arguments[2]),
                nameof(NpgsqlNetworkExtensions.GreaterThan) => _sqlExpressionFactory.GreaterThan(arguments[1], arguments[2]),

                nameof(NpgsqlNetworkExtensions.ContainedBy) => BoolReturningOnTwoNetworkTypes("<<"),
                nameof(NpgsqlNetworkExtensions.ContainedByOrEqual) => BoolReturningOnTwoNetworkTypes("<<="),
                nameof(NpgsqlNetworkExtensions.Contains) => BoolReturningOnTwoNetworkTypes(">>"),
                nameof(NpgsqlNetworkExtensions.ContainsOrEqual) => BoolReturningOnTwoNetworkTypes(">>="),
                nameof(NpgsqlNetworkExtensions.ContainsOrContainedBy) => BoolReturningOnTwoNetworkTypes("&&"),

                // TODO: Hack, see #1118
                nameof(NpgsqlNetworkExtensions.BitwiseNot) => new SqlUnaryExpression(ExpressionType.Negate,
                                                                                     arguments[1],
                                                                                     arguments[1].Type,
                                                                                     arguments[1].TypeMapping),

                nameof(NpgsqlNetworkExtensions.BitwiseAnd) => _sqlExpressionFactory.And(arguments[1], arguments[2]),
                nameof(NpgsqlNetworkExtensions.BitwiseOr) => _sqlExpressionFactory.Or(arguments[1], arguments[2]),

                // Add/Subtract accept inet + int, so we can't use the default type mapping inference logic which assumes
                // same-typed operands
                nameof(NpgsqlNetworkExtensions.Add)
                => new SqlBinaryExpression(
                    ExpressionType.Add,
                    _sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[1]),
                    _sqlExpressionFactory.ApplyDefaultTypeMapping(arguments[2]),
                    arguments[1].Type,
                    arguments[1].TypeMapping),

                nameof(NpgsqlNetworkExtensions.Subtract) when arguments[2].Type == typeof(int)
Example #2
0
        /// <summary>
        ///     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.
        /// </summary>
        public virtual SqlExpression?Translate(
            SqlExpression?instance,
            MethodInfo method,
            IReadOnlyList <SqlExpression> arguments,
            IDiagnosticsLogger <DbLoggerCategory.Query> logger)
        {
            Check.NotNull(method, nameof(method));
            Check.NotNull(arguments, nameof(arguments));
            Check.NotNull(logger, nameof(logger));

            if (method.ReturnType == typeof(int))
            {
                SqlExpression?left  = null;
                SqlExpression?right = null;
                if (method.Name == nameof(string.Compare) &&
                    arguments.Count == 2 &&
                    arguments[0].Type == arguments[1].Type)
                {
                    left  = arguments[0];
                    right = arguments[1];
                }
                else if (method.Name == nameof(string.CompareTo) &&
                         arguments.Count == 1 &&
                         instance != null &&
                         instance.Type == arguments[0].Type)
                {
                    left  = instance;
                    right = arguments[0];
                }

                if (left != null &&
                    right != null)
                {
                    return(_sqlExpressionFactory.Case(
                               new[]
                    {
                        new CaseWhenClause(
                            _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1))
                    },
                               null));
                }
            }

            return(null);
        }
        public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList <SqlExpression> arguments)
        {
            if (method.ReturnType == typeof(int))
            {
                SqlExpression left  = null;
                SqlExpression right = null;
                if (method.Name == nameof(string.Compare) &&
                    arguments.Count == 2 &&
                    arguments[0].Type.UnwrapNullableType() == arguments[1].Type.UnwrapNullableType())
                {
                    left  = arguments[0];
                    right = arguments[1];
                }
                else if (method.Name == nameof(string.CompareTo) &&
                         arguments.Count == 1 &&
                         instance != null &&
                         instance.Type.UnwrapNullableType() == arguments[0].Type.UnwrapNullableType())
                {
                    left  = instance;
                    right = arguments[0];
                }

                if (left != null &&
                    right != null)
                {
                    return(_sqlExpressionFactory.Case(
                               new[]
                    {
                        new CaseWhenClause(
                            _sqlExpressionFactory.Equal(left, right), _sqlExpressionFactory.Constant(0)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.GreaterThan(left, right), _sqlExpressionFactory.Constant(1)),
                        new CaseWhenClause(
                            _sqlExpressionFactory.LessThan(left, right), _sqlExpressionFactory.Constant(-1))
                    },
                               null));
                }
            }

            return(null);
        }