private SqlExpression OptimizeCompareTo(
            SqlBinaryExpression sqlBinaryExpression,
            int intValue,
            CaseExpression caseExpression)
        {
            var testLeft     = ((SqlBinaryExpression)caseExpression.WhenClauses[0].Test).Left;
            var testRight    = ((SqlBinaryExpression)caseExpression.WhenClauses[0].Test).Right;
            var operatorType = sqlBinaryExpression.Right is SqlConstantExpression
                ? sqlBinaryExpression.OperatorType
                : sqlBinaryExpression.OperatorType switch
            {
                ExpressionType.GreaterThan => ExpressionType.LessThan,
                ExpressionType.GreaterThanOrEqual => ExpressionType.LessThanOrEqual,
                ExpressionType.LessThan => ExpressionType.GreaterThan,
                ExpressionType.LessThanOrEqual => ExpressionType.GreaterThanOrEqual,
                _ => sqlBinaryExpression.OperatorType
            };

            switch (operatorType)
            {
            // CompareTo(a, b) != 0 -> a != b
            // CompareTo(a, b) != 1 -> a <= b
            // CompareTo(a, b) != -1 -> a >= b
            case ExpressionType.NotEqual:
                return((SqlExpression)Visit(intValue switch
                {
                    0 => _sqlExpressionFactory.NotEqual(testLeft, testRight),
                    1 => _sqlExpressionFactory.LessThanOrEqual(testLeft, testRight),
                    _ => _sqlExpressionFactory.GreaterThanOrEqual(testLeft, testRight),
                }));
        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)
        /// <inheritdoc/>
        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 (_methodInfoDatePartMapping.TryGetValue(method, out var value))
            {
                var start = _sqlExpressionFactory.GreaterThanOrEqual(arguments[0], arguments[1]);
                var end   = _sqlExpressionFactory.LessThanOrEqual(arguments[0], arguments[2]);
                return(_sqlExpressionFactory.AndAlso(start, end));
            }

            return(null);
        }