Skip to content

Commit

Permalink
fix: filtering by guid on collections
Browse files Browse the repository at this point in the history
Fixes #51
  • Loading branch information
pdevito3 authored Jul 19, 2024
2 parents fbc4418 + 2203396 commit 4ff507c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 13 deletions.
21 changes: 21 additions & 0 deletions QueryKit.IntegrationTests/Tests/DatabaseFilteringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,27 @@ public async Task can_filter_within_collection_long()
recipes[0].Id.Should().Be(fakeRecipeOne.Id);
}

[Fact]
public async Task can_filter_by_guid_for_collection()
{
var testingServiceScope = new TestingServiceScope();
var fakeRecipeOne = new FakeRecipeBuilder().Build();
var ingredient = new FakeIngredientBuilder()
.Build();

fakeRecipeOne.AddIngredient(ingredient);

await testingServiceScope.InsertAsync(fakeRecipeOne);

var input = $""" Ingredients.Id == "{ingredient.Id}" """;
var queryableRecipes = testingServiceScope.DbContext().Recipes;
var appliedQueryable = queryableRecipes.ApplyQueryKitFilter(input);
var recipes = await appliedQueryable.ToListAsync();

recipes.Count.Should().Be(1);
recipes[0].Ingredients.First().Id.Should().Be(ingredient.Id);
}

[Fact(Skip = "Can not handle nested collections yet.")]
public async Task can_filter_by_string_for_nested_collection()
{
Expand Down
47 changes: 34 additions & 13 deletions QueryKit/FilterParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -430,20 +430,11 @@ private static Parser<Expression> ComparisonExprParser<T>(ParameterExpression pa
if (temp.leftExpr.Type == typeof(Guid) || temp.leftExpr.Type == typeof(Guid?))
{
var toStringMethod = typeof(Guid).GetMethod("ToString", Type.EmptyTypes);
Expression leftExpr = temp.leftExpr.Type == typeof(Guid?) ?
Expression.Condition(
Expression.Property(temp.leftExpr, "HasValue"),
Expression.Call(Expression.Property(temp.leftExpr, "Value"), toStringMethod!),
Expression.Constant(null, typeof(string))
) :
Expression.Call(temp.leftExpr, toStringMethod!);
return temp.op.GetExpression<T>(leftExpr, CreateRightExpr(temp.leftExpr, temp.right, temp.op), config?.DbContextType);
var guidStringExpr = HandleGuidConversion(temp.leftExpr, temp.leftExpr.Type);
return temp.op.GetExpression<T>(guidStringExpr, CreateRightExpr(temp.leftExpr, temp.right, temp.op),
config?.DbContextType);
}
var rightExpr = CreateRightExpr(temp.leftExpr, temp.right, temp.op);
return temp.op.GetExpression<T>(temp.leftExpr, rightExpr, config?.DbContextType);
});
Expand Down Expand Up @@ -495,8 +486,9 @@ private static Parser<Expression> ComparisonExprParser<T>(ParameterExpression pa
var propertyInfoForMethod = GetPropertyInfo(genericArgType, propName);
var lambdaBody = Expression.PropertyOrField(innerParameter, propertyInfoForMethod.Name);
var selectLambda = Expression.Lambda(lambdaBody, innerParameter);
var selectResult = Expression.Call(null, selectMethod, member, selectLambda);
return Expression.Call(null, selectMethod, member, selectLambda);
return HandleGuidConversion(selectResult, propertyType, "Select");
}
}
}
Expand Down Expand Up @@ -582,6 +574,35 @@ private static Parser<Expression> OrExprParser<T>(ParameterExpression parameter,
AndExprParser<T>(parameter, config),
(op, left, right) => op.GetExpression<T>(left, right)
);

private static Expression GetGuidToStringExpression(Expression leftExpr)
{
var toStringMethod = typeof(Guid).GetMethod("ToString", Type.EmptyTypes);

return leftExpr.Type == typeof(Guid?) ?
Expression.Condition(
Expression.Property(leftExpr, "HasValue"),
Expression.Call(Expression.Property(leftExpr, "Value"), toStringMethod!),
Expression.Constant(null, typeof(string))
) :
Expression.Call(leftExpr, toStringMethod!);
}

private static Expression HandleGuidConversion(Expression expression, Type propertyType, string? selectMethodName = null)
{
if (propertyType != typeof(Guid) && propertyType != typeof(Guid?)) return expression;

if (string.IsNullOrWhiteSpace(selectMethodName)) return GetGuidToStringExpression(expression);

var selectMethod = typeof(Enumerable).GetMethods()
.First(m => m.Name == selectMethodName && m.GetParameters().Length == 2)
.MakeGenericMethod(propertyType, typeof(string));

var param = Expression.Parameter(propertyType, "g");
var toStringLambda = Expression.Lambda(GetGuidToStringExpression(param), param);

return Expression.Call(selectMethod, expression, toStringLambda);
}
}


0 comments on commit 4ff507c

Please sign in to comment.