From 10ab24fc0e73aae4d056a19482ed605f962b66e4 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Wed, 29 Nov 2023 19:49:00 -0600 Subject: [PATCH] Feeling good about duplicated value array fields. Closes GH-2768 --- .../Acceptance/Support/DefaultQueryFixture.cs | 3 +- .../Acceptance/child_collection_queries.cs | 8 ++- .../Linq/Members/DuplicatedArrayField.cs | 58 ++++++++++++++++++- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/LinqTests/Acceptance/Support/DefaultQueryFixture.cs b/src/LinqTests/Acceptance/Support/DefaultQueryFixture.cs index bbcfedc6d1..778e80dfa8 100644 --- a/src/LinqTests/Acceptance/Support/DefaultQueryFixture.cs +++ b/src/LinqTests/Acceptance/Support/DefaultQueryFixture.cs @@ -20,7 +20,8 @@ public DefaultQueryFixture() .Duplicate(x => x.Date) .Duplicate(x => x.Double) .Duplicate(x => x.Flag) - .Duplicate(x => x.Color); + .Duplicate(x => x.Color) + .Duplicate(x => x.NumberArray); }); } diff --git a/src/LinqTests/Acceptance/child_collection_queries.cs b/src/LinqTests/Acceptance/child_collection_queries.cs index 536017422b..581ab481ed 100644 --- a/src/LinqTests/Acceptance/child_collection_queries.cs +++ b/src/LinqTests/Acceptance/child_collection_queries.cs @@ -74,7 +74,13 @@ public Task run_query(string description) return assertTestCase(description, Fixture.Store); } - // TODO -- make NumberArray and StringArray be duplicated fields + + [Theory] + [MemberData(nameof(GetDescriptions))] + public Task with_duplicated_fields(string description) + { + return assertTestCase(description, Fixture.DuplicatedFieldStore); + } diff --git a/src/Marten/Linq/Members/DuplicatedArrayField.cs b/src/Marten/Linq/Members/DuplicatedArrayField.cs index fb80fbf36b..6ca208bf65 100644 --- a/src/Marten/Linq/Members/DuplicatedArrayField.cs +++ b/src/Marten/Linq/Members/DuplicatedArrayField.cs @@ -37,8 +37,8 @@ public DuplicatedArrayField(EnumStorage enumStorage, QueryableMember innerMember _count = new CollectionLengthMember(this); - IsEmpty = new WhereFragment($"({RawLocator} is null or jsonb_array_length({JSONBLocator}) = 0)"); - NotEmpty = new WhereFragment($"({RawLocator} is not null and jsonb_array_length({JSONBLocator}) > 0)"); + IsEmpty = new ArrayIsEmptyFilter(this); + NotEmpty = new ArrayIsNotEmptyFilter(this); } private readonly WholeDataMember _wholeDataMember; @@ -128,3 +128,57 @@ public IEnumerator GetEnumerator() throw new NotSupportedException(); } } + +internal class ArrayIsEmptyFilter: IReversibleWhereFragment +{ + private readonly DuplicatedArrayField _member; + private readonly string _text; + + public ArrayIsEmptyFilter(DuplicatedArrayField member) + { + _member = member; + _text = $"({member.RawLocator} is null or coalesce(array_length({member.RawLocator}, 1), 0) = 0)"; + } + + public void Apply(CommandBuilder builder) + { + builder.Append(_text); + } + + public bool Contains(string sqlText) + { + return false; + } + + public ISqlFragment Reverse() + { + return _member.NotEmpty; + } +} + +internal class ArrayIsNotEmptyFilter: IReversibleWhereFragment +{ + private readonly string _text; + private readonly DuplicatedArrayField _member; + + public ArrayIsNotEmptyFilter(DuplicatedArrayField member) + { + _text = $"coalesce(array_length({member.RawLocator}, 1), 0) > 0"; + _member = member; + } + + public void Apply(CommandBuilder builder) + { + builder.Append(_text); + } + + public bool Contains(string sqlText) + { + return false; + } + + public ISqlFragment Reverse() + { + return _member.IsEmpty; + } +}