Skip to content

Commit

Permalink
Ability to use custom value types as parameters in compiled queries. C…
Browse files Browse the repository at this point in the history
…loses GH-3491
  • Loading branch information
jeremydmiller committed Oct 18, 2024
1 parent 5c40cf3 commit bacf648
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/Marten/Internal/CompiledQueries/QueryCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static CompiledQueryPlan BuildQueryPlan<TDoc, TOut>(QuerySession session,

var plan = new CompiledQueryPlan(query.GetType(), typeof(TOut)){TenantId = session.TenantId};

assertValidityOfQueryType(plan, query.GetType());
assertValidityOfQueryType(plan, query.GetType(), session.Options);

// This *could* throw
var queryTemplate = plan.CreateQueryTemplate(query);
Expand Down Expand Up @@ -211,10 +211,21 @@ private static void eliminateStringNulls(object query)
}


private static void assertValidityOfQueryType(CompiledQueryPlan plan, Type type)
private static void assertValidityOfQueryType(CompiledQueryPlan plan, Type type, StoreOptions options)
{
if (plan.InvalidMembers.Any())
{
// Remove any value types here!
foreach (var member in plan.InvalidMembers.Where(x => !x.GetRawMemberType().IsNullable()).ToArray())
{
if (options.TryFindValueType(member.GetMemberType()) != null)
{
plan.InvalidMembers.Remove(member);
}
}

if (!plan.InvalidMembers.Any()) return;

var members = plan.InvalidMembers.Select(x => $"{x.GetRawMemberType().NameInCode()} {x.Name}")
.Join(", ");
var message = $"Members {members} cannot be used as parameters to a compiled query";
Expand Down
31 changes: 31 additions & 0 deletions src/ValueTypeTests/linq_querying_with_value_types.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Marten;
using Marten.Linq;
using Marten.Testing.Harness;
using Vogen;

Expand Down Expand Up @@ -69,6 +72,34 @@ public async Task store_several_and_query_by()

ordered.ShouldHaveTheSameElementsAs(doc4.Id);
}

[Fact]
public async Task use_value_type_as_parameter_in_compiled_query()
{
var doc1 = new LimitedDoc { Lower = LowerLimit.From(1), Upper = UpperLimit.From(20) };
var doc2 = new LimitedDoc { Lower = LowerLimit.From(5), Upper = UpperLimit.From(25) };
var doc3 = new LimitedDoc { Lower = LowerLimit.From(4), Upper = UpperLimit.From(15) };
var doc4 = new LimitedDoc { Lower = LowerLimit.From(3), Upper = UpperLimit.From(10) };

theSession.Store(doc1, doc2, doc3, doc4);
await theSession.SaveChangesAsync();

var raw = await theSession.QueryAsync(new LimitedDocQuery());
var ordered = raw.Select(x => x.Id).ToArray();

ordered.ShouldHaveTheSameElementsAs(doc4.Id);
}
}

public class LimitedDocQuery: ICompiledListQuery<LimitedDoc>
{
public Expression<Func<IMartenQueryable<LimitedDoc>, IEnumerable<LimitedDoc>>> QueryIs()
{
return query => query.OrderBy(x => x.Lower)
.Where(x => x.Upper == Upper);
}

public UpperLimit Upper { get; set; } = UpperLimit.From(10);
}

#region sample_limited_doc
Expand Down

0 comments on commit bacf648

Please sign in to comment.