public NpgsqlStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory, NpgsqlTypeMappingSource npgsqlTypeMappingSource)
 {
     _sqlExpressionFactory = sqlExpressionFactory;
     _whitespace           = _sqlExpressionFactory.Constant(
         @" \t\n\r",  // TODO: Complete this
         npgsqlTypeMappingSource.EStringTypeMapping);
     _textTypeMapping = _sqlExpressionFactory.FindMapping(typeof(string));
 }
        protected override Expression VisitUnary(UnaryExpression unaryExpression)
        {
            var operand = Visit(unaryExpression.Operand);

            if (TranslationFailed(unaryExpression.Operand, operand))
            {
                return(null);
            }

            var sqlOperand = (SqlExpression)operand;

            switch (unaryExpression.NodeType)
            {
            case ExpressionType.Not:
                return(_sqlExpressionFactory.Not(sqlOperand));

            case ExpressionType.Negate:
                return(_sqlExpressionFactory.Negate(sqlOperand));

            case ExpressionType.Convert:
                // Object convert needs to be converted to explicit cast when mismatching types
                if (operand.Type.IsInterface &&
                    unaryExpression.Type.GetInterfaces().Any(e => e == operand.Type) ||
                    unaryExpression.Type.UnwrapNullableType() == operand.Type ||
                    unaryExpression.Type.UnwrapNullableType() == typeof(Enum))
                {
                    return(sqlOperand);
                }

                // Introduce explicit cast only if the target type is mapped else we need to client eval
                if (unaryExpression.Type == typeof(object) ||
                    _sqlExpressionFactory.FindMapping(unaryExpression.Type) != null)
                {
                    sqlOperand = _sqlExpressionFactory.ApplyDefaultTypeMapping(sqlOperand);

                    return(_sqlExpressionFactory.Convert(sqlOperand, unaryExpression.Type));
                }

                break;
            }

            return(null);
        }
        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)
예제 #4
0
 public NpgsqlRangeTranslator(ISqlExpressionFactory sqlExpressionFactory)
 {
     _sqlExpressionFactory = sqlExpressionFactory;
     _boolMapping          = sqlExpressionFactory.FindMapping(typeof(bool));
 }
        public virtual SqlExpression Translate(SqlExpression instance, MemberInfo member, Type returnType)
        {
            Check.NotNull(member, nameof(member));
            Check.NotNull(returnType, nameof(returnType));

            var declaringType = member.DeclaringType;

            if (declaringType == typeof(DateTime) ||
                declaringType == typeof(DateTimeOffset))
            {
                var memberName = member.Name;

                if (_datePartMapping.TryGetValue(memberName, out var datePart))
                {
                    return(_sqlExpressionFactory.Function(
                               "DATEPART",
                               new[] { _sqlExpressionFactory.Fragment(datePart), instance },
                               returnType));
                }

                switch (memberName)
                {
                case nameof(DateTime.Date):
                    return(_sqlExpressionFactory.Function(
                               "CONVERT",
                               new[] { _sqlExpressionFactory.Fragment("date"), instance },
                               returnType,
                               declaringType == typeof(DateTime)
                                ? instance.TypeMapping
                                : _sqlExpressionFactory.FindMapping(typeof(DateTime))));

                case nameof(DateTime.TimeOfDay):
                    return(_sqlExpressionFactory.Convert(instance, returnType));

                case nameof(DateTime.Now):
                    return(_sqlExpressionFactory.Function(
                               declaringType == typeof(DateTime) ? "GETDATE" : "SYSDATETIMEOFFSET",
                               Array.Empty <SqlExpression>(),
                               returnType));

                case nameof(DateTime.UtcNow):
                    var serverTranslation = _sqlExpressionFactory.Function(
                        declaringType == typeof(DateTime) ? "GETUTCDATE" : "SYSUTCDATETIME",
                        Array.Empty <SqlExpression>(),
                        returnType);

                    return(declaringType == typeof(DateTime)
                            ? (SqlExpression)serverTranslation
                            : _sqlExpressionFactory.Convert(serverTranslation, returnType));

                case nameof(DateTime.Today):
                    return(_sqlExpressionFactory.Function(
                               "CONVERT",
                               new SqlExpression[]
                    {
                        _sqlExpressionFactory.Fragment("date"),
                        _sqlExpressionFactory.Function(
                            "GETDATE",
                            Array.Empty <SqlExpression>(),
                            typeof(DateTime))
                    },
                               returnType));
                }
            }

            return(null);
        }