Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ public override Expression HandleOperation(
object? parsedValue)
{
var property = context.GetInstance();

if (parsedValue is bool boolValue && property.Type == typeof(bool))
{
return boolValue
? property
: FilterExpressionBuilder.Not(property);
}

return FilterExpressionBuilder.Equals(property, parsedValue);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ public override Expression HandleOperation(
object? parsedValue)
{
var property = context.GetInstance();

if (parsedValue is bool boolValue && property.Type == typeof(bool))
{
return boolValue
? FilterExpressionBuilder.Not(property)
: property;
}

return FilterExpressionBuilder.NotEquals(property, parsedValue);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ true Result:

true SQL:
---------------
.param set @__p_0 1

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" = @__p_0
WHERE "d"."Bar"
---------------

false Result:
Expand All @@ -35,9 +33,7 @@ false Result:

false SQL:
---------------
.param set @__p_0 0

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" = @__p_0
WHERE NOT ("d"."Bar")
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ true Result:

true SQL:
---------------
.param set @p 1

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" = @p
WHERE "d"."Bar"
---------------

false Result:
Expand All @@ -35,9 +33,7 @@ false Result:

false SQL:
---------------
.param set @p 0

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" = @p
WHERE NOT ("d"."Bar")
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ true Result:

true SQL:
---------------
.param set @__p_0 1

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" <> @__p_0
WHERE NOT ("d"."Bar")
---------------

false Result:
Expand All @@ -35,9 +33,7 @@ false Result:

false SQL:
---------------
.param set @__p_0 0

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" <> @__p_0
WHERE "d"."Bar"
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ true Result:

true SQL:
---------------
.param set @p 1

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" <> @p
WHERE NOT ("d"."Bar")
---------------

false Result:
Expand All @@ -35,9 +33,7 @@ false Result:

false SQL:
---------------
.param set @p 0

SELECT "d"."Id", "d"."Bar"
FROM "Data" AS "d"
WHERE "d"."Bar" <> @p
WHERE "d"."Bar"
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,10 @@ true Result:

true SQL:
---------------
.param set @__p_0 1

SELECT "d"."Id", "d"."FooId"
FROM "Data" AS "d"
INNER JOIN "Foo" AS "f" ON "d"."FooId" = "f"."Id"
WHERE "f"."BarBool" = @__p_0
WHERE "f"."BarBool"
---------------

false Result:
Expand All @@ -55,10 +53,8 @@ false Result:

false SQL:
---------------
.param set @__p_0 0

SELECT "d"."Id", "d"."FooId"
FROM "Data" AS "d"
INNER JOIN "Foo" AS "f" ON "d"."FooId" = "f"."Id"
WHERE "f"."BarBool" = @__p_0
WHERE NOT ("f"."BarBool")
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,10 @@ true Result:

true SQL:
---------------
.param set @p 1

SELECT "d"."Id", "d"."FooId"
FROM "Data" AS "d"
INNER JOIN "Foo" AS "f" ON "d"."FooId" = "f"."Id"
WHERE "f"."BarBool" = @p
WHERE "f"."BarBool"
---------------

false Result:
Expand All @@ -55,10 +53,8 @@ false Result:

false SQL:
---------------
.param set @p 0

SELECT "d"."Id", "d"."FooId"
FROM "Data" AS "d"
INNER JOIN "Foo" AS "f" ON "d"."FooId" = "f"."Id"
WHERE "f"."BarBool" = @p
WHERE NOT ("f"."BarBool")
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public ExecutorBuilder(IFilterInputType inputType)
}

public Func<T, bool> Build<T>(IValueNode filter)
{
return BuildExpression<T>(filter).Compile();
}

public Expression<Func<T, bool>> BuildExpression<T>(IValueNode filter)
{
var visitorContext = new QueryableFilterContext(_inputType, true);
var visitor = new FilterVisitor<QueryableFilterContext, Expression>(
Expand All @@ -22,7 +27,7 @@ public Func<T, bool> Build<T>(IValueNode filter)

if (visitorContext.TryCreateLambda(out Expression<Func<T, bool>>? where))
{
return where.Compile();
return where;
}

throw new InvalidOperationException();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Linq.Expressions;
using HotChocolate.Language;

namespace HotChocolate.Data.Filters.Expressions;
Expand Down Expand Up @@ -40,6 +41,93 @@ public void Create_BooleanNotEqual_Expression()
Assert.False(func(b));
}

[Fact]
public void Create_BooleanEqual_Expression_True_Uses_Direct_Property()
{
// arrange
var value = Utf8GraphQLParser.Syntax.ParseValueLiteral("{ bar: { eq: true }}");
var tester = CreateProviderTester(new FooFilterInput());

// act
var expr = tester.BuildExpression<Foo>(value);

// assert - the in-memory context wraps with NotNullAndAlso(x, condition),
// so the body is AndAlso(x != null, condition). The right side should be
// a direct property access (MemberExpression), not an Equal comparison.
var andAlso = Assert.IsAssignableFrom<BinaryExpression>(expr.Body);
Assert.Equal(ExpressionType.AndAlso, andAlso.NodeType);
Assert.IsAssignableFrom<MemberExpression>(andAlso.Right);
}

[Fact]
public void Create_BooleanEqual_Expression_False_Uses_Not()
{
// arrange
var value = Utf8GraphQLParser.Syntax.ParseValueLiteral("{ bar: { eq: false }}");
var tester = CreateProviderTester(new FooFilterInput());

// act
var expr = tester.BuildExpression<Foo>(value);

// assert - right side of AndAlso should be Not(property)
var andAlso = Assert.IsAssignableFrom<BinaryExpression>(expr.Body);
Assert.Equal(ExpressionType.AndAlso, andAlso.NodeType);
var not = Assert.IsType<UnaryExpression>(andAlso.Right);
Assert.Equal(ExpressionType.Not, not.NodeType);
Assert.IsAssignableFrom<MemberExpression>(not.Operand);
}

[Fact]
public void Create_BooleanNotEqual_Expression_True_Uses_Not()
{
// arrange
var value = Utf8GraphQLParser.Syntax.ParseValueLiteral("{ bar: { neq: true }}");
var tester = CreateProviderTester(new FooFilterInput());

// act
var expr = tester.BuildExpression<Foo>(value);

// assert - right side of AndAlso should be Not(property)
var andAlso = Assert.IsAssignableFrom<BinaryExpression>(expr.Body);
Assert.Equal(ExpressionType.AndAlso, andAlso.NodeType);
var not = Assert.IsType<UnaryExpression>(andAlso.Right);
Assert.Equal(ExpressionType.Not, not.NodeType);
Assert.IsAssignableFrom<MemberExpression>(not.Operand);
}

[Fact]
public void Create_BooleanNotEqual_Expression_False_Uses_Direct_Property()
{
// arrange
var value = Utf8GraphQLParser.Syntax.ParseValueLiteral("{ bar: { neq: false }}");
var tester = CreateProviderTester(new FooFilterInput());

// act
var expr = tester.BuildExpression<Foo>(value);

// assert - right side of AndAlso should be direct property access
var andAlso = Assert.IsAssignableFrom<BinaryExpression>(expr.Body);
Assert.Equal(ExpressionType.AndAlso, andAlso.NodeType);
Assert.IsAssignableFrom<MemberExpression>(andAlso.Right);
}

[Fact]
public void Create_NullableBooleanEqual_Expression_Uses_Equality()
{
// arrange
var value = Utf8GraphQLParser.Syntax.ParseValueLiteral("{ bar: { eq: true }}");
var tester = CreateProviderTester(new FooNullableFilterInput());

// act
var expr = tester.BuildExpression<FooNullable>(value);

// assert - nullable bool should still use Equal (not optimized).
// The body is AndAlso(x != null, condition) where condition is Equal.
var andAlso = Assert.IsAssignableFrom<BinaryExpression>(expr.Body);
Assert.Equal(ExpressionType.AndAlso, andAlso.NodeType);
Assert.Equal(ExpressionType.Equal, andAlso.Right.NodeType);
}

[Fact]
public void Create_NullableBooleanEqual_Expression()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ true Result:

true SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where CAST(d.data ->> 'Bar' as boolean) = :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where (d.data ->> 'Bar' is not null and CAST(d.data ->> 'Bar' as boolean) = True);
---------------

false Result:
Expand All @@ -31,5 +31,5 @@ false Result:

false SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where CAST(d.data ->> 'Bar' as boolean) = :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where (d.data ->> 'Bar' is null or CAST(d.data ->> 'Bar' as boolean) = False);
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ true Result:

true SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where CAST(d.data ->> 'Bar' as boolean) != :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where (d.data ->> 'Bar' is null or CAST(d.data ->> 'Bar' as boolean) = False);
---------------

false Result:
Expand All @@ -31,5 +31,5 @@ false Result:

false SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where CAST(d.data ->> 'Bar' as boolean) != :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorbooleantests_foo as d where (d.data ->> 'Bar' is not null and CAST(d.data ->> 'Bar' as boolean) = True);
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ true Result:

true SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorobjecttests_bar as d where CAST(d.data -> 'Foo' ->> 'BarBool' as boolean) = :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorobjecttests_bar as d where (d.data -> 'Foo' ->> 'BarBool' is not null and CAST(d.data -> 'Foo' ->> 'BarBool' as boolean) = True);
---------------

false Result:
Expand All @@ -40,5 +40,5 @@ false Result:

false SQL:
---------------
select d.id, d.data from public.mt_doc_queryablefiltervisitorobjecttests_bar as d where CAST(d.data -> 'Foo' ->> 'BarBool' as boolean) = :p0;
select d.id, d.data from public.mt_doc_queryablefiltervisitorobjecttests_bar as d where (d.data -> 'Foo' ->> 'BarBool' is null or CAST(d.data -> 'Foo' ->> 'BarBool' as boolean) = False);
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ true Result:

true SQL:
---------------
from 'Foos' where Bar != $p0
from 'Foos' where Bar = $p0
---------------

false Result:
Expand All @@ -31,5 +31,5 @@ false Result:

false SQL:
---------------
from 'Foos' where Bar != $p0
from 'Foos' where Bar = $p0
---------------
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ true Result:

true SQL:
---------------
from 'Foos' where Bar != $p0
from 'Foos' where Bar = $p0
---------------

false Result:
Expand All @@ -31,5 +31,5 @@ false Result:

false SQL:
---------------
from 'Foos' where Bar != $p0
from 'Foos' where Bar = $p0
---------------
Loading