diff --git a/src/Marten.Testing/Linq/invoking_queryable_any_nopredicate_Tests.cs b/src/Marten.Testing/Linq/invoking_queryable_any_nopredicate_Tests.cs new file mode 100644 index 0000000000..dfc1e141cf --- /dev/null +++ b/src/Marten.Testing/Linq/invoking_queryable_any_nopredicate_Tests.cs @@ -0,0 +1,30 @@ +using System.Linq; +using Marten.Services; +using Shouldly; +using Xunit; + +namespace Marten.Testing.Linq +{ + public class invoking_queryable_any_nopredicate_Tests : DocumentSessionFixture + { + + [Fact] + public void naked_any_hit() + { + var targetithchildren = new Target {Number = 1}; + targetithchildren.Children = new[] {new Target(),}; + var nochildrennullarray = new Target { Number = 2 }; + var nochildrenemptyarray = new Target { Number = 3 }; + nochildrenemptyarray.Children = new Target[] {}; + theSession.Store(nochildrennullarray); + theSession.Store(nochildrenemptyarray); + theSession.Store(targetithchildren); + theSession.SaveChanges(); + + var items = theSession.Query().Where(x => x.Children.Any()).ToList(); + + items.Count.ShouldBe(1); + } + + } +} \ No newline at end of file diff --git a/src/Marten/Linq/CollectionAnyNoPredicateWhereFragment.cs b/src/Marten/Linq/CollectionAnyNoPredicateWhereFragment.cs new file mode 100644 index 0000000000..0d7b3ecc97 --- /dev/null +++ b/src/Marten/Linq/CollectionAnyNoPredicateWhereFragment.cs @@ -0,0 +1,35 @@ +using System.Linq; +using Baseline; +using Npgsql; +using Remotion.Linq.Clauses.Expressions; + +namespace Marten.Linq +{ + /// + /// Handle Any() with JSONB_ARRAY_LENGTH introduced in PostgreSQL 9.4 + /// + public class CollectionAnyNoPredicateWhereFragment : IWhereFragment + { + private readonly SubQueryExpression _expression; + + public CollectionAnyNoPredicateWhereFragment(SubQueryExpression expression) + { + _expression = expression; + } + + public string ToSql(NpgsqlCommand command) + { + var visitor = new FindMembers(); + visitor.Visit(_expression.QueryModel.MainFromClause.FromExpression); + var path = visitor.Members.Select(m => m.Name).Join("'->'"); + + var query = $"JSONB_ARRAY_LENGTH(COALESCE(case when data->>'{path}' is not null then data->'{path}' else '[]' end)) > 0"; + return query; + } + + public bool Contains(string sqlText) + { + return false; + } + } +} \ No newline at end of file diff --git a/src/Marten/Linq/WhereClauseVisitor.cs b/src/Marten/Linq/WhereClauseVisitor.cs index 7da193dcec..94eba55add 100644 --- a/src/Marten/Linq/WhereClauseVisitor.cs +++ b/src/Marten/Linq/WhereClauseVisitor.cs @@ -163,6 +163,14 @@ protected override Expression VisitSubQuery(SubQueryExpression expression) if (expression.QueryModel.ResultOperators.Any(x => x is AnyResultOperator)) { + // Any() without predicate + if (!expression.QueryModel.BodyClauses.Any()) + { + var @where_any_nopredicate = new CollectionAnyNoPredicateWhereFragment(expression); + + _register.Peek()(@where_any_nopredicate); + return null; + } var @where = new CollectionAnyContainmentWhereFragment(_parent._serializer, expression); _register.Peek()(@where);