// 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)); }
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"); }
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); } }