Skip to content

Commit

Permalink
New Query Pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
smitpatel committed Mar 22, 2019
1 parent 4958d11 commit cabd484
Show file tree
Hide file tree
Showing 322 changed files with 12,798 additions and 5,770 deletions.
7 changes: 4 additions & 3 deletions src/EFCore.Cosmos/Query/Internal/EntityShaper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ var materializationContextParameter
var materializer
= _entityMaterializerSource
.CreateMaterializeExpression(
firstEntityType, materializationContextParameter);
firstEntityType, "instance", materializationContextParameter);

if (concreteEntityTypes.Count == 1)
{
Expand Down Expand Up @@ -145,7 +145,8 @@ var blockExpressions
.CreateReadValueExpression(
Expression.Call(materializationContextParameter, MaterializationContext.GetValueBufferMethod),
discriminatorProperty.ClrType,
indexMap[discriminatorProperty.GetIndex()])),
indexMap[discriminatorProperty.GetIndex()],
discriminatorProperty)),
Expression.IfThenElse(
Expression.Equal(discriminatorValueVariable, firstDiscriminatorValue),
Expression.Return(returnLabelTarget, materializer),
Expand Down Expand Up @@ -196,7 +197,7 @@ var discriminatorValue
materializer
= _entityMaterializerSource
.CreateMaterializeExpression(
concreteEntityType, materializationContextParameter);
concreteEntityType, "instance", materializationContextParameter);

blockExpressions[1]
= Expression.IfThenElse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Diagnostics;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
using Microsoft.EntityFrameworkCore.InMemory.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.InMemory.Query.ExpressionVisitors.Internal;
using Microsoft.EntityFrameworkCore.InMemory.Query.Internal;
using Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline;
using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal;
using Microsoft.EntityFrameworkCore.InMemory.ValueGeneration.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors;
using Microsoft.EntityFrameworkCore.Query.Pipeline;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.EntityFrameworkCore.ValueGeneration;
Expand Down Expand Up @@ -70,6 +72,13 @@ public static IServiceCollection AddEntityFrameworkInMemoryDatabase([NotNull] th
.TryAdd<IQueryContextFactory, InMemoryQueryContextFactory>()
.TryAdd<IEntityQueryModelVisitorFactory, InMemoryQueryModelVisitorFactory>()
.TryAdd<IEntityQueryableExpressionVisitorFactory, InMemoryEntityQueryableExpressionVisitorFactory>()

// New Query pipeline
.TryAdd<IShapedQueryCompilingExpressionVisitorFactory, InMemoryShapedQueryCompilingExpressionVisitorFactory>()
.TryAdd<IQueryableMethodTranslatingExpressionVisitorFactory, InMemoryQueryableMethodTranslatingExpressionVisitorFactory>()
.TryAdd<IEntityQueryableTranslatorFactory, InMemoryEntityQueryableTranslatorFactory>()


.TryAdd<IConventionSetBuilder, InMemoryConventionSetBuilder>()
.TryAdd<ISingletonOptions, IInMemorySingletonOptions>(p => p.GetService<IInMemorySingletonOptions>())
.TryAdd<ITypeMappingSource, InMemoryTypeMappingSource>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var concreteEntityTypes
return Expression.Lambda<Func<IEntityType, MaterializationContext, object>>(
_entityMaterializerSource
.CreateMaterializeExpression(
concreteEntityTypes[0], materializationContextParameter),
concreteEntityTypes[0], "instance", materializationContextParameter),
entityTypeParameter,
materializationContextParameter);
}
Expand All @@ -71,7 +71,7 @@ var blockExpressions
returnLabelTarget,
_entityMaterializerSource
.CreateMaterializeExpression(
concreteEntityTypes[0], materializationContextParameter))),
concreteEntityTypes[0], "instance", materializationContextParameter))),
Expression.Label(
returnLabelTarget,
Expression.Default(returnLabelTarget.Type))
Expand All @@ -87,7 +87,7 @@ var blockExpressions
Expression.Return(
returnLabelTarget,
_entityMaterializerSource
.CreateMaterializeExpression(concreteEntityType, materializationContextParameter)),
.CreateMaterializeExpression(concreteEntityType, "instance", materializationContextParameter)),
blockExpressions[0]);
}

Expand Down
21 changes: 21 additions & 0 deletions src/EFCore.InMemory/Query/PipeLine/EntityValuesExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

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

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public class EntityValuesExpression : Expression
{
public EntityValuesExpression(IEntityType entityType, int startIndex)
{
EntityType = entityType;
StartIndex = startIndex;
}

public IEntityType EntityType { get; }
public int StartIndex { get; }
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Query.Pipeline;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public class InMemoryEntityQueryableExpressionVisitor2 : EntityQueryableExpressionVisitor2
{
private readonly IModel _model;

public InMemoryEntityQueryableExpressionVisitor2(IModel model)
{
_model = model;
}

protected override ShapedQueryExpression CreateShapedQueryExpression(Type elementType)
{
return new InMemoryShapedQueryExpression(_model.FindEntityType(elementType));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Query.Pipeline;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public class InMemoryEntityQueryableTranslatorFactory : EntityQueryableTranslatorFactory
{
private readonly IModel _model;

public InMemoryEntityQueryableTranslatorFactory(IModel model)
{
_model = model;
}

public override EntityQueryableTranslator Create(QueryCompilationContext2 queryCompilationContext)
{
return new InMemoryEntityQueryableTranslator(_model);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

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

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public class InMemoryEntityQueryableTranslator : EntityQueryableTranslator
{
private readonly IModel _model;

public InMemoryEntityQueryableTranslator(IModel model)
{
_model = model;
}

public override Expression Visit(Expression query)
{
return new InMemoryEntityQueryableExpressionVisitor2(_model).Visit(query);
}
}
}
67 changes: 67 additions & 0 deletions src/EFCore.InMemory/Query/PipeLine/InMemoryLinqOperatorProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public static class InMemoryLinqOperatorProvider
{
private static MethodInfo GetMethod(string name, int parameterCount = 0)
=> GetMethods(name, parameterCount).Single();

private static IEnumerable<MethodInfo> GetMethods(string name, int parameterCount = 0)
=> typeof(Enumerable).GetTypeInfo().GetDeclaredMethods(name)
.Where(mi => mi.GetParameters().Length == parameterCount + 1);

public static MethodInfo Where = GetMethods(nameof(Enumerable.Where), 1)
.Single(mi => mi.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);
public static MethodInfo Select = GetMethods(nameof(Enumerable.Select), 1)
.Single(mi => mi.GetParameters()[1].ParameterType.GetGenericArguments().Length == 2);

public static MethodInfo Join = GetMethod(nameof(Enumerable.Join), 4);
public static MethodInfo Contains = GetMethod(nameof(Enumerable.Contains), 1);

public static MethodInfo OrderBy = GetMethod(nameof(Enumerable.OrderBy), 1);
public static MethodInfo OrderByDescending = GetMethod(nameof(Enumerable.OrderByDescending), 1);
public static MethodInfo ThenBy = GetMethod(nameof(Enumerable.ThenBy), 1);
public static MethodInfo ThenByDescending = GetMethod(nameof(Enumerable.ThenByDescending), 1);
public static MethodInfo All = GetMethod(nameof(Enumerable.All), 1);
public static MethodInfo Any = GetMethod(nameof(Enumerable.Any));
public static MethodInfo AnyPredicate = GetMethod(nameof(Enumerable.Any), 1);
public static MethodInfo Count = GetMethod(nameof(Enumerable.Count));
public static MethodInfo LongCount = GetMethod(nameof(Enumerable.LongCount));
public static MethodInfo CountPredicate = GetMethod(nameof(Enumerable.Count), 1);
public static MethodInfo LongCountPredicate = GetMethod(nameof(Enumerable.LongCount), 1);
public static MethodInfo Distinct = GetMethod(nameof(Enumerable.Distinct));
public static MethodInfo Take = GetMethod(nameof(Enumerable.Take), 1);
public static MethodInfo Skip = GetMethod(nameof(Enumerable.Skip), 1);

public static MethodInfo FirstPredicate = GetMethod(nameof(Enumerable.First), 1);
public static MethodInfo FirstOrDefaultPredicate = GetMethod(nameof(Enumerable.FirstOrDefault), 1);
public static MethodInfo LastPredicate = GetMethod(nameof(Enumerable.Last), 1);
public static MethodInfo LastOrDefaultPredicate = GetMethod(nameof(Enumerable.LastOrDefault), 1);
public static MethodInfo SinglePredicate = GetMethod(nameof(Enumerable.Single), 1);
public static MethodInfo SingleOrDefaultPredicate = GetMethod(nameof(Enumerable.SingleOrDefault), 1);

public static MethodInfo GetAggregateMethod(string methodName, Type elementType, int parameterCount = 0)
{
Check.NotEmpty(methodName, nameof(methodName));
Check.NotNull(elementType, nameof(elementType));

var aggregateMethods = GetMethods(methodName, parameterCount).ToList();

return
aggregateMethods
.Single(
mi => mi.GetParameters().Last().ParameterType.GetGenericArguments().Last() == elementType);
//?? aggregateMethods.Single(mi => mi.IsGenericMethod)
// .MakeGenericMethod(elementType);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Query.Pipeline;
using Microsoft.EntityFrameworkCore.Storage;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Pipeline
{
public class InMemoryProjectionBindingExpressionVisitor : ExpressionVisitor
{
private InMemoryQueryExpression _queryExpression;
private readonly IDictionary<ProjectionMember, Expression> _projectionMapping
= new Dictionary<ProjectionMember, Expression>();

private readonly Stack<ProjectionMember> _projectionMembers = new Stack<ProjectionMember>();
private readonly InMemoryExpressionTranslatingExpressionVisitor _expressionTranslatingExpressionVisitor;

public InMemoryProjectionBindingExpressionVisitor(
InMemoryExpressionTranslatingExpressionVisitor expressionTranslatingExpressionVisitor)
{
_expressionTranslatingExpressionVisitor = expressionTranslatingExpressionVisitor;
}

public Expression Translate(InMemoryQueryExpression queryExpression, Expression expression)
{
_queryExpression = queryExpression;

_projectionMembers.Push(new ProjectionMember());

var result = Visit(expression);

_queryExpression.ApplyProjection(_projectionMapping);

_queryExpression = null;
_projectionMapping.Clear();
_projectionMembers.Clear();

return result;
}

public override Expression Visit(Expression expression)
{
if (expression == null)
{
return null;
}

if (!(expression is NewExpression
|| expression is MemberInitExpression
|| expression is EntityShaperExpression))
{
var translation = _expressionTranslatingExpressionVisitor.Translate(_queryExpression, expression);

_projectionMapping[_projectionMembers.Peek()] = translation;

return new ProjectionBindingExpression(_queryExpression, _projectionMembers.Peek(), expression.Type);
}

return base.Visit(expression);
}

protected override Expression VisitExtension(Expression extensionExpression)
{
if (extensionExpression is EntityShaperExpression entityShaperExpression)
{
_projectionMapping[_projectionMembers.Peek()]
= _queryExpression.GetProjectionExpression(
entityShaperExpression.ValueBufferExpression.ProjectionMember);

return entityShaperExpression.Update(
new ProjectionBindingExpression(_queryExpression, _projectionMembers.Peek(), typeof(ValueBuffer)));
}

throw new InvalidOperationException();
}

protected override Expression VisitNew(NewExpression newExpression)
{
var newArguments = new Expression[newExpression.Arguments.Count];
for (var i = 0; i < newExpression.Arguments.Count; i++)
{
// TODO: Members can be null????
var projectionMember = _projectionMembers.Peek().AddMember(newExpression.Members[i]);
_projectionMembers.Push(projectionMember);

newArguments[i] = Visit(newExpression.Arguments[i]);
_projectionMembers.Pop();
}

return newExpression.Update(newArguments);
}

protected override Expression VisitMemberInit(MemberInitExpression memberInitExpression)
{
var newExpression = (NewExpression)Visit(memberInitExpression.NewExpression);
var newBindings = new MemberAssignment[memberInitExpression.Bindings.Count];
for (var i = 0; i < newBindings.Length; i++)
{
// TODO: Members can be null????
var memberAssignment = (MemberAssignment)memberInitExpression.Bindings[i];

var projectionMember = _projectionMembers.Peek().AddMember(memberAssignment.Member);
_projectionMembers.Push(projectionMember);

newBindings[i] = memberAssignment.Update(Visit(memberAssignment.Expression));
_projectionMembers.Pop();
}

return memberInitExpression.Update(newExpression, newBindings);
}
}
}
Loading

0 comments on commit cabd484

Please sign in to comment.