public virtual Expression Translate(MethodCallExpression methodCallExpression)
        {
            if (!methodCallExpression.Method.Equals(_methodInfo))
            {
                return(null);
            }

            var argument0 = methodCallExpression.Arguments[0];

            // If Contains() is being invoked on a citext, ensure that the string argument is explicitly cast into a
            // citext (instead of the default text for a CLR string) as otherwise PostgreSQL prefers the text variant of
            // the ambiguous call STRPOS(citext, text) and the search will be case-sensitive. See #384.
            if (argument0 != null &&
                methodCallExpression.Object?.FindProperty(typeof(string))?.GetConfiguredColumnType() == "citext")
            {
                argument0 = new ExplicitStoreTypeCastExpression(argument0, typeof(string), "citext");
            }

            return(Expression.GreaterThan(
                       new SqlFunctionExpression("STRPOS", typeof(int), new[]
            {
                methodCallExpression.Object,
                argument0
            }),
                       Expression.Constant(0)
                       ));
        }
Esempio n. 2
0
        public virtual Expression Translate(MethodCallExpression e)
        {
            if (!e.Method.Equals(_methodInfo) || e.Object == null)
            {
                return(null);
            }

            var constantPatternExpr = e.Arguments[0] as ConstantExpression;

            if (constantPatternExpr != null)
            {
                // The pattern is constant. Escape all special characters (%, _, \) in C# and send
                // a simple LIKE
                return(new LikeExpression(
                           e.Object,
                           Expression.Constant(Regex.Replace((string)constantPatternExpr.Value, @"([%_\\])", @"\$1") + '%')
                           ));
            }

            // The pattern isn't a constant (i.e. parameter, database column...).
            // First run LIKE against the *unescaped* pattern (which will efficiently use indices),
            // but then add another test to filter out false positives.
            var pattern = e.Arguments[0];

            Expression leftExpr = new SqlFunctionExpression("LEFT", typeof(string), new[]
            {
                e.Object,
                new SqlFunctionExpression("LENGTH", typeof(int), new[] { pattern }),
            });

            // If StartsWith is being invoked on a citext, the LEFT() function above will return a reglar text
            // and the comparison will be case-sensitive. So we need to explicitly cast LEFT()'s return type
            // to citext. See #319.
            if (e.Object.FindProperty(typeof(string))?.GetConfiguredColumnType() == "citext")
            {
                leftExpr = new ExplicitStoreTypeCastExpression(leftExpr, typeof(string), "citext");
            }

            return(Expression.AndAlso(
                       new LikeExpression(e.Object, Expression.Add(pattern, Expression.Constant("%"), _concat)),
                       Expression.Equal(
                           leftExpr,
                           pattern
                           )
                       ));
        }