Skip to content

Commit

Permalink
stub
Browse files Browse the repository at this point in the history
  • Loading branch information
smitpatel committed Apr 9, 2019
1 parent 9470468 commit 5c1f8e9
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,45 @@ protected override ShapedQueryExpression TranslateFirstOrDefault(ShapedQueryExpr

protected override ShapedQueryExpression TranslateGroupJoin(ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector)
{
var outerSelectExpression = (SelectExpression)outer.QueryExpression;
if (outerSelectExpression.Limit != null
|| outerSelectExpression.Offset != null
|| outerSelectExpression.IsDistinct)
{
outerSelectExpression.PushdownIntoSubQuery();
}

var innerSelectExpression = (SelectExpression)inner.QueryExpression;
if (innerSelectExpression.Orderings.Any()
|| innerSelectExpression.Limit != null
|| innerSelectExpression.Offset != null
|| innerSelectExpression.IsDistinct
|| innerSelectExpression.Predicate != null)
{
innerSelectExpression.PushdownIntoSubQuery();
}

var joinPredicate = CreateJoinPredicate(outer, outerKeySelector, inner, innerKeySelector);
if (joinPredicate != null)
{
outer = TranslateThenBy(outer, outerKeySelector, true);

var innerTransparentIdentifierType = CreateTransparentIdentifierType(
resultSelector.Parameters[0].Type,
resultSelector.Parameters[1].Type.TryGetSequenceType());

outerSelectExpression.AddLeftJoin(
innerSelectExpression, joinPredicate, innerTransparentIdentifierType);

return TranslateResultSelectorForGroupJoin(
outer,
inner.ShaperExpression,
outerKeySelector,
innerKeySelector,
resultSelector,
innerTransparentIdentifierType);
}

throw new NotImplementedException();
}

Expand Down
42 changes: 42 additions & 0 deletions src/EFCore/Query/PipeLine/EntityShaperExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Metadata;

Expand Down Expand Up @@ -37,4 +38,45 @@ public EntityShaperExpression Update(ProjectionBindingExpression valueBufferExpr
public override Type Type => EntityType.ClrType;
public override ExpressionType NodeType => ExpressionType.Extension;
}

public class CollectionShaperExpression : Expression
{
public CollectionShaperExpression(
Expression parent,
Expression innerShaper,
Expression outerKey,
Expression innerKey)
{
Parent = parent;
InnerShaper = innerShaper;
OuterKey = outerKey;
InnerKey = innerKey;
}


protected override Expression VisitChildren(ExpressionVisitor visitor)
{
var parent = visitor.Visit(Parent);
var innerShaper = visitor.Visit(InnerShaper);
var outerKey = visitor.Visit(OuterKey);
var innerKey = visitor.Visit(InnerKey);

return parent != Parent || innerShaper != InnerShaper || outerKey != OuterKey || innerKey != InnerKey
? new CollectionShaperExpression(parent, innerShaper, outerKey, innerKey)
: this;
}


public override ExpressionType NodeType => ExpressionType.Extension;

public override Type Type => typeof(IEnumerable<>).MakeGenericType(InnerShaper.Type);

public Expression Parent { get; }

public Expression InnerShaper { get; }

public Expression OuterKey { get; }

public Expression InnerKey { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,55 @@ protected ShapedQueryExpression TranslateResultSelectorForJoin(
return TranslateSelect(outer, newResultSelector);
}

protected ShapedQueryExpression TranslateResultSelectorForGroupJoin(
ShapedQueryExpression outer,
LambdaExpression innerShaper,
LambdaExpression outerKeySelector,
LambdaExpression innerKeySelector,
LambdaExpression resultSelector,
Type transparentIdentifierType)
{
innerShaper = Expression.Lambda(
new EntityShaperNullableMarkingExpressionVisitor().Visit(innerShaper.Body),
innerShaper.Parameters);

var shaperExpression = CombineShapers(
outer.QueryExpression,
outer.ShaperExpression,
innerShaper,
transparentIdentifierType);

var transparentIdentifierParameter = Expression.Parameter(transparentIdentifierType);
var outerAccess = AccessOuterTransparentField(transparentIdentifierType, transparentIdentifierParameter);
var innerAccess = AccessInnerTransparentField(transparentIdentifierType, transparentIdentifierParameter);

var outerKey = ReplacingExpressionVisitor.Replace(
outerKeySelector.Parameters[0],
outerAccess,
outerKeySelector.Body);

var innerKey = ReplacingExpressionVisitor.Replace(
innerKeySelector.Parameters[0],
innerAccess,
innerKeySelector.Body);

var replacements = new Dictionary<Expression, Expression>
{
{ resultSelector.Parameters[0], outerAccess },
{ resultSelector.Parameters[1], new CollectionShaperExpression(outerAccess, innerAccess, outerKey, innerKey) },
};

var resultBody = new ReplacingExpressionVisitor(replacements).Visit(resultSelector.Body);
resultBody = ReplacingExpressionVisitor.Replace(
transparentIdentifierParameter,
shaperExpression.Body,
resultBody);

outer.ShaperExpression = Expression.Lambda(resultBody, shaperExpression.Parameters);

return outer;
}

private LambdaExpression CombineShapers(
Expression queryExpression,
LambdaExpression outerShaper,
Expand Down
23 changes: 23 additions & 0 deletions src/EFCore/Query/PipeLine/ShapedQueryExpressionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ protected virtual LambdaExpression InjectEntityMaterializer(

private class EntityMaterializerInjectingExpressionVisitor : ExpressionVisitor
{
private IDictionary<EntityShaperExpression, ParameterExpression> _entityCache
= new Dictionary<EntityShaperExpression, ParameterExpression>();

private static readonly ConstructorInfo _materializationContextConstructor
= typeof(MaterializationContext).GetConstructors().Single(ci => ci.GetParameters().Length == 2);

Expand Down Expand Up @@ -129,6 +132,11 @@ protected override Expression VisitExtension(Expression extensionExpression)
{
if (extensionExpression is EntityShaperExpression entityShaperExpression)
{
if (_entityCache.TryGetValue(entityShaperExpression, out var existingInstance))
{
return existingInstance;
}

_currentEntityIndex++;
var entityType = entityShaperExpression.EntityType;
var valueBuffer = entityShaperExpression.ValueBufferExpression;
Expand Down Expand Up @@ -204,9 +212,24 @@ protected override Expression VisitExtension(Expression extensionExpression)
MaterializeEntity(entityType, valueBuffer))));
}

_entityCache[entityShaperExpression] = result;

return result;
}

if (extensionExpression is CollectionShaperExpression collectionShaper)
{
var keyType = collectionShaper.OuterKey.Type;
var comparerType = typeof(EqualityComparer<>).MakeGenericType(keyType);
var comparer = Expression.Variable(comparerType, "comparer" + _currentEntityIndex);

_variables.Add(comparer);
Expression.Assign(
comparer,
Expression.MakeMemberAccess(null, comparerType.GetProperty(nameof(EqualityComparer<int>.Default))));
var parent = Visit(collectionShaper.Parent);
}

if (extensionExpression is ProjectionBindingExpression)
{
return extensionExpression;
Expand Down

0 comments on commit 5c1f8e9

Please sign in to comment.