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); } }
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(); }
private DuplicatedField duplicateField(Expression<Func<IEvent, object>> property, string columnName) { var finder = new FindMembers(); finder.Visit(property); return DuplicateField(finder.Members.ToArray(), columnName: columnName); }
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); } }
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); } }
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; }
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}'"; }
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); }
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(); }
// 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; }
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}"); }
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 = _mapping?.FieldFor(members).SqlLocator ?? $"CAST ({CommandBuilder.BuildJsonStringLocator("d.data", members.ToArray(), _serializer.Casing)} as jsonb)"; return($"{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}'"; }
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}"; }
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); }