예제 #1
0
        private static IField GetField(IQueryableDocument mapping, MethodCallExpression expression)
        {
            IField GetField(Expression e)
            {
                var visitor = new FindMembers();

                visitor.Visit(e);

                var field = mapping.FieldFor(visitor.Members);

                return(field);
            }

            if (!expression.Method.IsStatic && expression.Object != null && expression.Object.NodeType != ExpressionType.Constant)
            {
                // x.member.Equals(...)
                return(GetField(expression.Object));
            }
            if (expression.Arguments[0].NodeType == ExpressionType.Constant)
            {
                // type.Equals("value", x.member) [decimal]
                return(GetField(expression.Arguments[1]));
            }
            // type.Equals(x.member, "value") [decimal]
            return(GetField(expression.Arguments[0]));
        }
예제 #2
0
        public static MemberInfo[] Determine(Expression expression)
        {
            var visitor = new FindMembers();

            if (expression is SubQueryExpression subquery)
            {
                visitor.Visit(subquery.QueryModel.MainFromClause.FromExpression);
                if (subquery.QueryModel.ResultOperators.FirstOrDefault() is CountResultOperator)
                {
                    visitor.Members.Add(LinqConstants.ArrayLength);
                }
                else
                {
                    throw new BadLinqExpressionException($"FindMembers does not understand expression '{expression}'");
                }
            }
            else
            {
                visitor.Visit(expression);
            }



            return(visitor.Members.ToArray());
        }
예제 #3
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var members = FindMembers.Determine(expression);

            var field = mapping.FieldFor(members);

            return(new WhereFragment($"({field.SelectionLocator} is null or jsonb_array_length({field.SelectionLocator}) = 0)"));
        }
예제 #4
0
        public static MemberInfo Member <T>(Expression <Func <T, object> > expression)
        {
            var finder = new FindMembers();

            finder.Visit(expression);

            return(finder.Members.LastOrDefault());
        }
예제 #5
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var members = FindMembers.Determine(expression);

            var locator = mapping.FieldFor(members).SqlLocator;
            var value   = expression.Arguments.Last().Value();

            return(new WhereFragment($"{locator} ~~* ?", value.As <string>()));
        }
예제 #6
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, BinaryExpression expression)
        {
            var isValueExpressionOnRight = expression.Right.IsValueExpression();
            var jsonLocatorExpression    = isValueExpressionOnRight ? expression.Left : expression.Right;
            var valueExpression          = isValueExpressionOnRight ? expression.Right : expression.Left;

            var members = FindMembers.Determine(jsonLocatorExpression);

            var field = mapping.FieldFor(members);


            var value       = field.GetValue(valueExpression);
            var jsonLocator = field.SqlLocator;

            var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator();

            var isDuplicated = (mapping.FieldFor(members) is DuplicatedField);

            if (useContainment &&
                expression.NodeType == ExpressionType.Equal && value != null && !isDuplicated)
            {
                return(new ContainmentWhereFragment(serializer, expression, _wherePrefix));
            }


            if (value == null)
            {
                var sql = expression.NodeType == ExpressionType.NotEqual
                    ? $"({jsonLocator}) is not null"
                    : $"({jsonLocator}) {_isOperator} null";

                return(new WhereFragment(sql));
            }

            var op = _operators[expression.NodeType];

            if (jsonLocatorExpression.NodeType == ExpressionType.Modulo)
            {
                var byValue      = moduloByValue((isValueExpressionOnRight ? expression.Left : expression.Right) as BinaryExpression);
                var moduloFormat = isValueExpressionOnRight ? "{0} % {1} {2} ?" : "? {2} {0} % {1}";
                return(new WhereFragment(moduloFormat.ToFormat(jsonLocator, byValue, op), value));
            }

            // ! == -> <>

            if (expression.Left.NodeType == ExpressionType.Not && expression.NodeType == ExpressionType.Equal)
            {
                op = _operators[ExpressionType.NotEqual];
            }

            var whereFormat = isValueExpressionOnRight ? "{0} {1} ?" : "? {1} {0}";

            return(new WhereFragment($"{_wherePrefix}{whereFormat.ToFormat(jsonLocator, op)}", value));


            return(value == null ? new WhereFragment($"({jsonLocator}) {_isOperator} null") : new WhereFragment($"{_wherePrefix}({jsonLocator}) {op} ?", value));
        }
예제 #7
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            MemberInfo[] members = FindMembers.Determine(expression);

            string locator = mapping.FieldFor(members).SqlLocator;
            object values  = expression.Arguments.Last().Value();

            string json = serializer.ToJson(values);

            return(new CustomizableWhereFragment($"{locator} @> ?", "?", Tuple.Create <object, NpgsqlDbType?>(json, NpgsqlDbType.Jsonb)));
        }
예제 #8
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var finder = new FindMembers();

            finder.Visit(expression);

            var members = finder.Members;

            var locator = mapping.FieldFor(members).SqlLocator;
            var values  = expression.Object.Value();

            return(new WhereFragment($"{locator} = ANY(?)", values));
        }
예제 #9
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var members = FindMembers.Determine(expression);

            var locator = mapping.FieldFor(members).SqlLocator;
            var values  = expression.Arguments.Last().Value();

            if (members.Last().GetMemberType().IsEnum)
            {
                return(new EnumIsNotOneOfWhereFragment(values, serializer.EnumStorage, locator));
            }

            return(new WhereFragment($"NOT({locator} = ANY(?))", values));
        }
예제 #10
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var finder = new FindMembers();

            finder.Visit(expression);

            var members = finder.Members;

            var locator = mapping.FieldFor(members).SqlLocator;
            var values  = expression.Arguments.Last().Value();

            if (members.Last().GetMemberType().GetTypeInfo().IsEnum)
            {
                return(new EnumIsOneOfWhereFragment(values, serializer.EnumStorage, locator));
            }

            return(new WhereFragment($"{locator} = ANY(?)", values));
        }
예제 #11
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var finder = new FindMembers();

            finder.Visit(expression);
            var members      = finder.Members;
            var fieldlocator = mapping.FieldFor(members).SqlLocator;

            if (IsCollectionContainsWithStringKey(expression.Method))
            {
                return(QueryFromICollectionContains(expression, fieldlocator, serializer));
            }
            else if (IsDictionaryContainsKey(expression.Method))
            {
                return(QueryFromDictionaryContainsKey(expression, fieldlocator));
            }
            else
            {
                throw new NotImplementedException("Could not understand the format of the dictionary access");
            }
        }
예제 #12
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, BinaryExpression expression)
        {
            var areBothMemberExpressions = !expression.Left.IsValueExpression() && !expression.Right.IsValueExpression();
            var isValueExpressionOnRight = areBothMemberExpressions || expression.Right.IsValueExpression();
            var jsonLocatorExpression    = isValueExpressionOnRight ? expression.Left : expression.Right;
            var valueExpression          = isValueExpressionOnRight ? expression.Right : expression.Left;

            var members = FindMembers.Determine(jsonLocatorExpression);

            var field = mapping.FieldFor(members);

            object value;

            if (valueExpression is MemberExpression memberAccess)
            {
                var membersOther = FindMembers.Determine(memberAccess);
                var fieldOther   = mapping.FieldFor(membersOther);
                value = fieldOther.SqlLocator;
            }
            else
            {
                memberAccess = null;
                value        = field.GetValue(valueExpression);
            }

            var jsonLocator = field.SqlLocator;

            var useContainment = mapping.PropertySearching == PropertySearching.ContainmentOperator || field.ShouldUseContainmentOperator();

            var isDuplicated = (mapping.FieldFor(members) is DuplicatedField);
            var isEnumString = field.MemberType.GetTypeInfo().IsEnum&& serializer.EnumStorage == EnumStorage.AsString;

            if (useContainment &&
                expression.NodeType == ExpressionType.Equal && value != null && !isDuplicated && !isEnumString)
            {
                return(new ContainmentWhereFragment(serializer, expression, _wherePrefix));
            }

            if (value == null)
            {
                var sql = expression.NodeType == ExpressionType.NotEqual
                    ? $"({jsonLocator}) is not null"
                    : $"({jsonLocator}) {_isOperator} null";

                return(new WhereFragment(sql));
            }

            var op = _operators[expression.NodeType];

            if (jsonLocatorExpression.NodeType == ExpressionType.Modulo)
            {
                var byValue      = moduloByValue((isValueExpressionOnRight ? expression.Left : expression.Right) as BinaryExpression);
                var moduloFormat = isValueExpressionOnRight ? "{0} % {1} {2} ?" : "? {2} {0} % {1}";
                return(new WhereFragment(moduloFormat.ToFormat(jsonLocator, byValue, op), value));
            }

            // ! == -> <>

            if (expression.Left.NodeType == ExpressionType.Not && expression.NodeType == ExpressionType.Equal)
            {
                op = _operators[ExpressionType.NotEqual];
            }

            if (memberAccess != null)
            {
                return(new WhereFragment($"{_wherePrefix}{jsonLocator} {op} {value}"));
            }
            var whereFormat = isValueExpressionOnRight ? "{0} {1} ?" : "? {1} {0}";

            return(new WhereFragment($"{_wherePrefix}{whereFormat.ToFormat(jsonLocator, op)}", value));

            //return value == null ? new WhereFragment($"({jsonLocator}) {_isOperator} null") : new WhereFragment($"{_wherePrefix}({jsonLocator}) {op} ?", value);
        }
예제 #13
0
        public IWhereFragment Parse(IQueryableDocument mapping, ISerializer serializer, MethodCallExpression expression)
        {
            var value = expression.Arguments.Single().Value();

            return(ContainmentWhereFragment.SimpleArrayContains(FindMembers.Determine(expression.Object), serializer, expression.Object, value));
        }