Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Projection left joins now support nullable #2545

Merged
merged 9 commits into from
Nov 9, 2020
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using HotChocolate.Execution.Processing;
using HotChocolate.Types;
using static HotChocolate.Data.Projections.Expressions.ProjectionExpressionBuilder;

namespace HotChocolate.Data.Projections.Expressions.Handlers
{
Expand Down Expand Up @@ -81,16 +83,30 @@ public class QueryableProjectionFieldHandler

Queue<MemberAssignment> members = queryableScope.Level.Pop();
MemberInitExpression memberInit =
ProjectionExpressionBuilder.CreateMemberInit(queryableScope.RuntimeType, members);
CreateMemberInit(queryableScope.RuntimeType, members);

if (!context.TryGetQueryableScope(out QueryableProjectionScope? parentScope))
{
throw new InvalidOperationException();
}

Expression nestedProperty;
if (field.Member is PropertyInfo propertyInfo)
{
nestedProperty = Expression.Property(context.GetInstance(), propertyInfo);
}
else if (field.Member is MethodInfo methodInfo)
{
nestedProperty = Expression.Call(context.GetInstance(), methodInfo);
}
else
{
throw new InvalidOperationException();
}

parentScope.Level.Peek()
.Enqueue(
Expression.Bind(field.Member, memberInit));
Expression.Bind(field.Member, NotNullAndAlso(nestedProperty, memberInit)));

action = SelectionVisitor.Continue;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,28 @@ namespace HotChocolate.Data.Projections.Expressions
{
internal static class ProjectionExpressionBuilder
{
private static readonly ConstantExpression _null =
Expression.Constant(null, typeof(object));

public static MemberInitExpression CreateMemberInit(
Type type,
IEnumerable<MemberBinding> expressions)
{
NewExpression ctor = Expression.New(type);
return Expression.MemberInit(ctor, expressions);
}

public static Expression NotNull(Expression expression)
{
return Expression.NotEqual(expression, _null);
}

public static Expression NotNullAndAlso(Expression property, Expression condition)
{
return Expression.Condition(
NotNull(property),
condition,
Expression.Default(property.Type));
}
}
}