Пример #1
0
        public ContainmentWhereFragment(ISerializer serializer, BinaryExpression binary)
        {
            _serializer = serializer;

            var visitor = new FindMembers();
            visitor.Visit(binary.Left);

            var members = visitor.Members;

            if (members.Count > 1)
            {
                var dict = new Dictionary<string, object>();
                var member = members.Last();
                var value = MartenExpressionParser.Value(binary.Right);
                dict.Add(member.Name, value);

                members.Reverse().Skip(1).Each(m =>
                {
                    dict = new Dictionary<string, object> { { m.Name, dict}};
                });

                _dictionary = dict;
            }
            else
            {
                _dictionary = new Dictionary<string, object>();

                var member = members.Single();
                var value = MartenExpressionParser.Value(binary.Right);
                _dictionary.Add(member.Name, value);

            }
        }
Пример #2
0
        private DuplicatedField duplicateField(Expression<Func<IEvent, object>> property, string columnName)
        {
            var finder = new FindMembers();
            finder.Visit(property);

            return DuplicateField(finder.Members.ToArray(), columnName: columnName);
        }
Пример #3
0
        public static IWhereFragment SimpleArrayContains(ISerializer serializer, QueryModel queryModel, ContainsResultOperator contains)
        {
            var from = queryModel.MainFromClause.FromExpression;
            var visitor = new FindMembers();
            visitor.Visit(from);

            var members = visitor.Members;

            var constant = contains.Item as ConstantExpression;

            if (constant != null)
            {
                var array = Array.CreateInstance(constant.Type, 1);
                array.SetValue(constant.Value, 0);

                var dict = new Dictionary<string, object>();
                dict.Add(members.Last().Name, array);

                members.Reverse().Skip(1).Each(m =>
                {
                    dict = new Dictionary<string, object>() { {m.Name, dict} };
                });

                return new ContainmentWhereFragment(serializer, dict);
            }

            throw new NotSupportedException();
        }
Пример #4
0
        public static void CreateDictionaryForSearch(BinaryExpression binary, IDictionary<string, object> dict)
        {
            var visitor = new FindMembers();
            visitor.Visit(binary.Left);

            var members = visitor.Members;

            if (members.Count > 1)
            {
                var temp = new Dictionary<string, object>();
                var member = members.Last();
                var value = MartenExpressionParser.Value(binary.Right);
                temp.Add(member.Name, value);

                members.Reverse().Skip(1).Each(m => { temp = new Dictionary<string, object> {{m.Name, temp}}; });

                var topMemberName = members.First().Name;
                dict.Add(topMemberName, temp[topMemberName]);
            }
            else
            {
                var member = members.Single();
                var value = MartenExpressionParser.Value(binary.Right);
                dict.Add(member.Name, value);
            }

        }
Пример #5
0
        public static void CreateDictionaryForSearch(IDictionary<string, object> dict, Expression memberExpression, object expressionValue)
        {
            var visitor = new FindMembers();
            visitor.Visit(memberExpression);

            var members = visitor.Members;

            if (members.Count > 1)
            {
                var temp = new Dictionary<string, object>();
                var member = members.Last();
                var value = expressionValue;
                temp.Add(member.Name, value);

                members.Reverse().Skip(1).Each(m => { temp = new Dictionary<string, object> {{m.Name, temp}}; });

                var topMemberName = members.First().Name;
                dict.Add(topMemberName, temp[topMemberName]);
            }
            else
            {
                var member = members.Single();
                var value = expressionValue;
                dict.Add(member.Name, value);
            }
        }
Пример #6
0
        public static void CreateDictionaryForSearch(IDictionary <string, object> dict, Expression memberExpression,
                                                     object expressionValue)
        {
            var visitor = new FindMembers();

            visitor.Visit(memberExpression);

            var members = visitor.Members;

            if (members.Count > 1)
            {
                var temp   = new Dictionary <string, object>();
                var member = members.Last();
                var value  = expressionValue;
                temp.Add(member.Name, value);

                members.Reverse().Skip(1).Each(m => { temp = new Dictionary <string, object> {
                                                          { m.Name, temp }
                                                      }; });

                var topMemberName = members.First().Name;
                dict.Add(topMemberName, temp[topMemberName]);
            }
            else
            {
                var member = members.Single();
                var value  = expressionValue;
                dict.Add(member.Name, value);
            }
        }
Пример #7
0
        public static IWhereFragment SimpleArrayContains(ISerializer serializer, Expression from,
                                                         object value)
        {
            var visitor = new FindMembers();

            visitor.Visit(from);

            var members = visitor.Members;

            if (value != null)
            {
                var array = Array.CreateInstance(value.GetType(), 1);
                array.SetValue(value, 0);

                var dict = new Dictionary <string, object>();
                dict.Add(members.Last().Name, array);

                members.Reverse().Skip(1).Each(m => { dict = new Dictionary <string, object> {
                                                          { m.Name, dict }
                                                      }; });

                return(new ContainmentWhereFragment(serializer, dict));
            }


            throw new NotSupportedException();
        }
Пример #8
0
        public static MemberInfo Member <T>(Expression <Func <T, object> > expression)
        {
            var finder = new FindMembers();

            finder.Visit(expression);

            return(finder.Members.LastOrDefault());
        }
Пример #9
0
        public static MemberInfo[] Determine(Expression expression)
        {
            var visitor = new FindMembers();

            visitor.Visit(expression);

            return(visitor.Members.ToArray());
        }
        private string buildSubQuery(SubQueryExpression subQuery, CommandBuilder command)
        {
            var contains = subQuery.QueryModel.ResultOperators.OfType<ContainsResultOperator>().FirstOrDefault();
            if (contains == null)
            {
                throw new NotSupportedException("Only the Contains() operator is supported on subqueries within Collection.Any() searches");
            }

            // build rhs of ?|
            var from = subQuery.QueryModel.MainFromClause.FromExpression as ConstantExpression;
            if (from == null || !supportedTypes.Any(supp => isListOrArrayOf(from.Type, supp)))
            {
                throwNotSupportedContains();
            }

            //TODO: this won't work for enumeration types. Only works with strings, so we have
            // to exactly map the ToString() like the underlying serializer would. Blech.
            var values = new List<string>();
            
            var enumerable = ((System.Collections.IEnumerable)from.Value);

            foreach (var obj in enumerable)
            {
                values.Add(obj.ToString());
            }

            var fromParam = command.AddParameter(values.ToArray());
            fromParam.NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Text;

            // check/build lhs of ?|
            var item = contains.Item as QuerySourceReferenceExpression;
            if (item == null)
            {
                throwNotSupportedContains();
            }
            if (!supportedTypes.Any(supp => supp == item.ReferencedQuerySource.ItemType))
            {
                throwNotSupportedContains();
            }
            var itemSource = item.ReferencedQuerySource as MainFromClause;
            if (itemSource == null)
            {
                throwNotSupportedContains();
            }
            var member = itemSource.FromExpression as MemberExpression;
            if (member == null)
            {
                throwNotSupportedContains();
            }
            var visitor = new FindMembers();
            visitor.Visit(member);
            var members = visitor.Members;
            if (!members.Any())
                throwNotSupportedContains();
            var path = members.Select(m => m.Name).Join("'->'");
            return $"d.data->'{path}' ?| :{fromParam.ParameterName}";
        }
Пример #11
0
        public static string JsonLocator(this IDocumentMapping mapping, Expression expression)
        {
            var visitor = new FindMembers();
            visitor.Visit(expression);

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

            return field.SqlLocator;
        }
        private string buildSubQuery(SubQueryExpression subQuery, CommandBuilder command)
        {
            var contains = subQuery.QueryModel.ResultOperators.OfType <ContainsResultOperator>().FirstOrDefault();

            if (contains == null)
            {
                throw new NotSupportedException("Only the Contains() operator is supported on subqueries within Collection.Any() searches");
            }

            // build rhs of ?|
            var from = subQuery.QueryModel.MainFromClause.FromExpression as ConstantExpression;

            if (from == null || !supportedTypes.Any(supp => isListOrArrayOf(from.Type, supp)))
            {
                throwNotSupportedContains();
            }
            var fromParam = command.AddParameter(from.Value);

            fromParam.NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Text;

            // check/build lhs of ?|
            var item = contains.Item as QuerySourceReferenceExpression;

            if (item == null)
            {
                throwNotSupportedContains();
            }
            if (!supportedTypes.Any(supp => supp == item.ReferencedQuerySource.ItemType))
            {
                throwNotSupportedContains();
            }
            var itemSource = item.ReferencedQuerySource as MainFromClause;

            if (itemSource == null)
            {
                throwNotSupportedContains();
            }
            var member = itemSource.FromExpression as MemberExpression;

            if (member == null)
            {
                throwNotSupportedContains();
            }
            var visitor = new FindMembers();

            visitor.Visit(member);
            var members = visitor.Members;

            if (!members.Any())
            {
                throwNotSupportedContains();
            }
            var path = members.Select(m => m.Name).Join("'->'");

            return($"data->'{path}' ?| :{fromParam.ParameterName}");
        }
Пример #13
0
        // TODO -- use the mapping off of DocumentQuery later
        public string JsonLocator(IDocumentMapping mapping, Expression expression)
        {
            var visitor = new FindMembers();

            visitor.Visit(expression);


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

            return(field.SqlLocator);
        }
Пример #14
0
        // TODO -- pull this out somewhere else
        private IWhereFragment buildSimpleWhereClause(IQueryableDocument mapping, BinaryExpression binary)
        {
            var isValueExpressionOnRight = binary.Right.IsValueExpression();
            var jsonLocatorExpression    = isValueExpressionOnRight ? binary.Left : binary.Right;
            var valueExpression          = isValueExpressionOnRight ? binary.Right : binary.Left;

            var op = _operators[binary.NodeType];

            var isSubQuery = isValueExpressionOnRight
                ? binary.Left is SubQueryExpression
                : binary.Right is SubQueryExpression;

            if (isSubQuery)
            {
                return(buildChildCollectionQuery(mapping, jsonLocatorExpression.As <SubQueryExpression>().QueryModel, valueExpression, op));
            }

            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 &&
                binary.NodeType == ExpressionType.Equal && value != null && !isDuplicated)
            {
                return(new ContainmentWhereFragment(_serializer, binary));
            }



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

                return(new WhereFragment(sql));
            }
            if (jsonLocatorExpression.NodeType == ExpressionType.Modulo)
            {
                var moduloByValue = MartenExpressionParser.moduloByValue(binary);
                return(new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value));
            }


            return(new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value));
        }
Пример #15
0
        // TODO -- use the mapping off of DocumentQuery later
        public string JsonLocator(DocumentMapping mapping, Expression expression)
        {
            var visitor = new FindMembers();

            visitor.Visit(expression);

            //return new JsonLocatorField(visitor.Members.ToArray()).SqlLocator;

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

            _query.RegisterField(field);

            return(field.SqlLocator);
        }
Пример #16
0
        private IWhereFragment buildChildCollectionQuery(IQueryableDocument mapping, QueryModel query, Expression valueExpression, string op)
        {
            var members = FindMembers.Determine(query.MainFromClause.FromExpression);
            var field   = mapping.FieldFor(members);

            if (query.HasOperator <CountResultOperator>())
            {
                var value = field.GetValue(valueExpression);

                return(new WhereFragment($"jsonb_array_length({field.SqlLocator}) {op} ?", value));
            }

            throw new NotSupportedException("Marten does not yet support this type of Linq query against child collections");
        }
Пример #17
0
        public void Parse()
        {
            var invalidOperators = _query.ResultOperators.Where(x => !ValidOperators.Contains(x.GetType()))
                                   .ToArray();

            if (invalidOperators.Any())
            {
                var names = invalidOperators.Select(x => x.GetType().Name).Join(", ");
                throw new NotSupportedException($"Marten does not yet support {names} operators in child collection queries");
            }

            var members     = FindMembers.Determine(_query.MainFromClause.FromExpression);
            var queryType   = _query.SourceType();
            var isPrimitive = TypeMappings.HasTypeMapping(queryType);



            Visit(_expression);

            // Simple types

            if (isPrimitive)
            {
                var contains = _query.ResultOperators.OfType <ContainsResultOperator>().FirstOrDefault();
                if (contains != null)
                {
                    var @where = ContainmentWhereFragment.SimpleArrayContains(members, _serializer, _query.MainFromClause.FromExpression, contains.Item.Value());
                    _registerFilter(@where);

                    return;
                }
            }

            if (_query.ResultOperators.Any(x => x is AnyResultOperator))
            {
                // Any() without predicate
                if (!_query.BodyClauses.Any())
                {
                    var @where_any_nopredicate = new CollectionAnyNoPredicateWhereFragment(members, _expression);

                    _registerFilter(@where_any_nopredicate);

                    return;
                }

                var @where = new CollectionAnyContainmentWhereFragment(members, _serializer, _expression);
                _registerFilter(@where);
            }
        }
Пример #18
0
        public void can_build_getter_for_deep_expression()
        {
            Expression<Func<Target, int>> expression = t => t.Inner.Number;

            var visitor = new FindMembers();
            visitor.Visit(expression);

            var members = visitor.Members.ToArray();

            var getter = LambdaBuilder.Getter<Target, int>(EnumStorage.AsInteger, members);

            var target = Target.Random(true);

            getter(target).ShouldBe(target.Inner.Number);
        }
        public string ToSql(NpgsqlCommand command)
        {
            var wheres = _expression
                .QueryModel
                .BodyClauses
                .OfType<WhereClause>()
                .Select(x => x.Predicate)
                .ToArray();

            if (!wheres.All(x => x is BinaryExpression))
            {
                throw new NotImplementedException();
            }

            var search = new Dictionary<string, object>();
            wheres.OfType<BinaryExpression>()
                .Each(x =>
                {
                    gatherSearch(x, search);
                    
                });

            var visitor = new FindMembers();
            visitor.Visit(_expression.QueryModel.MainFromClause.FromExpression);

            var members = visitor.Members;
            var dictionary = new Dictionary<string, object>();

            if (members.Count == 1)
            {
                dictionary.Add(members.Single().Name, new[] {search});
            }
            else
            {
                throw new NotImplementedException();
            }


            var json = _serializer.ToCleanJson(dictionary);

            return $"data @> '{json}'";
        }
Пример #20
0
        public IMartenQueryable <T> Include <TInclude>(Expression <Func <T, object> > idSource, Action <TInclude> callback,
                                                       JoinType joinType = JoinType.Inner)
        {
            var executor = Provider.As <MartenQueryProvider>().Executor.As <MartenQueryExecutor>();
            var tenant   = executor.Tenant;

            tenant.EnsureStorageExists(typeof(TInclude));

            var mapping  = tenant.MappingFor(typeof(T)).ToQueryableDocument();
            var included = tenant.MappingFor(typeof(TInclude)).ToQueryableDocument();

            var visitor = new FindMembers();

            visitor.Visit(idSource);
            var members = visitor.Members.ToArray();

            var include = mapping.JoinToInclude(joinType, included, members, callback);

            executor.AddInclude(include);

            return(this);
        }
Пример #21
0
        public static IWhereFragment SimpleArrayContains(ISerializer serializer, Expression from,
            object value)
        {
            var visitor = new FindMembers();
            visitor.Visit(from);

            var members = visitor.Members;

            if (value != null)
            {
                var array = Array.CreateInstance(value.GetType(), 1);
                array.SetValue(value, 0);

                var dict = new Dictionary<string, object>();
                dict.Add(members.Last().Name, array);

                members.Reverse().Skip(1).Each(m => { dict = new Dictionary<string, object> {{m.Name, dict}}; });

                return new ContainmentWhereFragment(serializer, dict);
            }


            throw new NotSupportedException();
        }
Пример #22
0
        // TODO -- use the mapping off of DocumentQuery later
        public string JsonLocator(DocumentMapping mapping, Expression expression)
        {
            var visitor = new FindMembers();
            visitor.Visit(expression);

            //return new JsonLocatorField(visitor.Members.ToArray()).SqlLocator;

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

            _query.RegisterField(field);

            return field.SqlLocator;
        }
        private string buildSubQuery(SubQueryExpression subQuery, NpgsqlCommand command)
        {
            var contains = subQuery.QueryModel.ResultOperators.OfType<ContainsResultOperator>().FirstOrDefault();
            if (contains == null)
            {
                throw new NotSupportedException("Only the Contains() operator is supported on subqueries within Collection.Any() searches");
            }

            // build rhs of ?|
            var from = subQuery.QueryModel.MainFromClause.FromExpression as ConstantExpression;
            if (from == null || !supportedTypes.Any(supp => isListOrArrayOf(from.Type, supp)))
            {
                throwNotSupportedContains();
            }
            var fromParam = command.AddParameter(from.Value);
            fromParam.NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Text;

            // check/build lhs of ?|
            var item = contains.Item as QuerySourceReferenceExpression;
            if (item == null)
            {
                throwNotSupportedContains();
            }
            if (!supportedTypes.Any(supp => supp == item.ReferencedQuerySource.ItemType))
            {
                throwNotSupportedContains();
            }
            var itemSource = item.ReferencedQuerySource as MainFromClause;
            if (itemSource == null)
            {
                throwNotSupportedContains();
            }
            var member = itemSource.FromExpression as MemberExpression;
            if (member == null)
            {
                throwNotSupportedContains();
            }
            var visitor = new FindMembers();
            visitor.Visit(member);
            var members = visitor.Members;
            if (!members.Any())
                throwNotSupportedContains();
            var path = members.Select(m => m.Name).Join("'->'");
            return $"data->'{path}' ?| :{fromParam.ParameterName}";
        }
        public string ToSql(NpgsqlCommand command)
        {
            var wheres = _expression
                .QueryModel
                .BodyClauses
                .OfType<WhereClause>()
                .Select(x => x.Predicate)
                .ToArray();

            if (!wheres.All(x => x is BinaryExpression))
            {
                throw new NotImplementedException();
            }


            var visitor = new FindMembers();
            visitor.Visit(_expression.QueryModel.MainFromClause.FromExpression);

            var members = visitor.Members;
            var binaryExpressions = wheres.OfType<BinaryExpression>().ToArray();
            var dictionary = new Dictionary<string, object>();

            // Are we querying directly againt the elements as you would for primitive types?
            if (binaryExpressions.All(x => x.Left is QuerySourceReferenceExpression && x.Right is ConstantExpression))
            {
                if (binaryExpressions.Any(x => x.NodeType != ExpressionType.Equal))
                {
                    throw new NotSupportedException("Only the equality operator is supported on Collection.Any(x => x) searches directly against the element");
                }

                var values = binaryExpressions.Select(x => MartenExpressionParser.Value(x.Right)).ToArray();
                if (members.Count == 1)
                {
                    dictionary.Add(members.Single().Name, values);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            else
            {
                var search = new Dictionary<string, object>();
                binaryExpressions.Each(x => gatherSearch(x, search));


                if (members.Count == 1)
                {
                    dictionary.Add(members.Single().Name, new[] { search });
                }
                else
                {
                    throw new NotImplementedException();
                }
            }




            var json = _serializer.ToCleanJson(dictionary);

            return $"data @> '{json}'";
        }
Пример #25
0
        private IWhereFragment buildSimpleWhereClause(IQueryableDocument mapping, BinaryExpression binary)
        {
            var isValueExpressionOnRight = binary.Right.IsValueExpression();
            var jsonLocatorExpression = isValueExpressionOnRight ? binary.Left : binary.Right;
            var valueExpression = isValueExpressionOnRight ? binary.Right : binary.Left;

            var op = _operators[binary.NodeType];

            var visitor = new FindMembers();
            visitor.Visit(jsonLocatorExpression);
            var members = visitor.Members;

            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 &&
                binary.NodeType == ExpressionType.Equal && value != null && !isDuplicated)
            {
                return new ContainmentWhereFragment(_serializer, binary);
            }

            

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

                return new WhereFragment(sql);
            }
            if (jsonLocatorExpression.NodeType == ExpressionType.Modulo)
            {
                var moduloByValue = MartenExpressionParser.moduloByValue(binary);
                return new WhereFragment("{0} % {1} {2} ?".ToFormat(jsonLocator, moduloByValue, op), value);
            }


            return new WhereFragment("{0} {1} ?".ToFormat(jsonLocator, op), value);
        }
        public string ToSql(NpgsqlCommand command)
        {
            var wheres = _expression
                         .QueryModel
                         .BodyClauses
                         .OfType <WhereClause>()
                         .Select(x => x.Predicate)
                         .ToArray();

            if (!wheres.All(x => x is BinaryExpression))
            {
                throw new NotImplementedException();
            }


            var visitor = new FindMembers();

            visitor.Visit(_expression.QueryModel.MainFromClause.FromExpression);

            var members           = visitor.Members;
            var binaryExpressions = wheres.OfType <BinaryExpression>().ToArray();
            var dictionary        = new Dictionary <string, object>();

            // Are we querying directly againt the elements as you would for primitive types?
            if (binaryExpressions.All(x => x.Left is QuerySourceReferenceExpression && x.Right is ConstantExpression))
            {
                if (binaryExpressions.Any(x => x.NodeType != ExpressionType.Equal))
                {
                    throw new NotSupportedException("Only the equality operator is supported on Collection.Any(x => x) searches directly against the element");
                }

                var values = binaryExpressions.Select(x => x.Right.Value()).ToArray();
                if (members.Count == 1)
                {
                    dictionary.Add(members.Single().Name, values);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            else
            {
                var search = new Dictionary <string, object>();
                binaryExpressions.Each(x => gatherSearch(x, search));


                if (members.Count == 1)
                {
                    dictionary.Add(members.Single().Name, new[] { search });
                }
                else
                {
                    throw new NotImplementedException();
                }
            }



            var json  = _serializer.ToCleanJson(dictionary);
            var param = command.AddParameter(json);

            param.NpgsqlDbType = NpgsqlDbType.Jsonb;


            return($"d.data @> :{param.ParameterName}");
        }