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

InMemory: Set operations #17446

Merged
merged 1 commit into from
Aug 27, 2019
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 @@ -59,6 +59,11 @@ private static IEnumerable<MethodInfo> GetMethods(string name, int parameterCoun
public static MethodInfo Single = GetMethod(nameof(Enumerable.Single), 0);
public static MethodInfo SingleOrDefault = GetMethod(nameof(Enumerable.SingleOrDefault), 0);

public static MethodInfo Concat = GetMethod(nameof(Enumerable.Concat), 1);
public static MethodInfo Except = GetMethod(nameof(Enumerable.Except), 1);
public static MethodInfo Intersect = GetMethod(nameof(Enumerable.Intersect), 1);
public static MethodInfo Union = GetMethod(nameof(Enumerable.Union), 1);

public static MethodInfo GetAggregateMethod(string methodName, Type elementType, int parameterCount = 0)
{
Check.NotEmpty(methodName, nameof(methodName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou
}

protected override ShapedQueryExpression TranslateConcat(ShapedQueryExpression source1, ShapedQueryExpression source2)
=> null;
=> TranslateSetOperation(InMemoryLinqOperatorProvider.Concat, source1, source2);

protected override ShapedQueryExpression TranslateContains(ShapedQueryExpression source, Expression item)
{
Expand Down Expand Up @@ -203,7 +203,7 @@ protected override ShapedQueryExpression TranslateElementAtOrDefault(ShapedQuery
=> null;

protected override ShapedQueryExpression TranslateExcept(ShapedQueryExpression source1, ShapedQueryExpression source2)
=> null;
=> TranslateSetOperation(InMemoryLinqOperatorProvider.Except, source1, source2);

protected override ShapedQueryExpression TranslateFirstOrDefault(ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault)
{
Expand All @@ -223,7 +223,7 @@ protected override ShapedQueryExpression TranslateGroupJoin(ShapedQueryExpressio
=> null;

protected override ShapedQueryExpression TranslateIntersect(ShapedQueryExpression source1, ShapedQueryExpression source2)
=> null;
=> TranslateSetOperation(InMemoryLinqOperatorProvider.Intersect, source1, source2);

protected override ShapedQueryExpression TranslateJoin(ShapedQueryExpression outer, ShapedQueryExpression inner, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector)
{
Expand Down Expand Up @@ -582,7 +582,7 @@ protected override ShapedQueryExpression TranslateThenBy(ShapedQueryExpression s
}

protected override ShapedQueryExpression TranslateUnion(ShapedQueryExpression source1, ShapedQueryExpression source2)
=> null;
=> TranslateSetOperation(InMemoryLinqOperatorProvider.Union, source1, source2);

protected override ShapedQueryExpression TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate)
{
Expand Down Expand Up @@ -681,5 +681,26 @@ private ShapedQueryExpression TranslateSingleResultOperator(

return source;
}

private ShapedQueryExpression TranslateSetOperation(
MethodInfo setOperationMethodInfo,
ShapedQueryExpression source1,
ShapedQueryExpression source2)
{
var inMemoryQueryExpression1 = (InMemoryQueryExpression)source1.QueryExpression;
var inMemoryQueryExpression2 = (InMemoryQueryExpression)source2.QueryExpression;

// Apply any pending selectors, ensuring that the shape of both expressions is identical
// prior to applying the set operation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only works when shapes are really identical. (what we support right now). For any EntityType differences, this would not work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the idea is to implement that at the same time for relational and InMemory when the time comes.

inMemoryQueryExpression1.PushdownIntoSubquery();
inMemoryQueryExpression2.PushdownIntoSubquery();

inMemoryQueryExpression1.ServerQueryExpression = Expression.Call(
setOperationMethodInfo.MakeGenericMethod(typeof(ValueBuffer)),
inMemoryQueryExpression1.ServerQueryExpression,
inMemoryQueryExpression2.ServerQueryExpression);

return source1;
}
}
}
161 changes: 1 addition & 160 deletions test/EFCore.InMemory.FunctionalTests/Query/SimpleQueryInMemoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,171 +87,12 @@ public override void Client_code_using_instance_method_throws()
base.Client_code_using_instance_method_throws();
}

#region Set Operations
public override Task Concat(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Concat_nested(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Concat_non_entity(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Except(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Except_nested(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Except_non_entity(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Except_simple_followed_by_projecting_constant(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Intersect(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Intersect_nested(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Intersect_non_entity(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Include(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Intersect(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_nested(bool isAsync)
{
return Task.CompletedTask;
}

public override void Union_non_entity(bool isAsync)
{
}

public override Task Union_OrderBy_Skip_Take(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_over_different_projection_types(bool isAsync, string leftType, string rightType)
{
return Task.CompletedTask;
}

public override Task Union_Select(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Skip_Take_OrderBy_ThenBy_Where(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Take_Union_Take(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Union(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_Where(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Union_with_anonymous_type_projection(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Include_Union(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Client_eval_Union_FirstOrDefault(bool isAsync)
{
return Task.CompletedTask;
}

[ConditionalTheory(Skip = "Issue#16963 (GroupBy)")]
public override Task GroupBy_Select_Union(bool isAsync)
{
return Task.CompletedTask;
}

public override void Include_Union_different_includes_throws()
{
}

public override void Include_Union_only_on_one_side_throws()
{
}

public override Task Select_Union(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Select_Union_different_fields_in_anonymous_with_subquery(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Select_Union_unrelated(bool isAsync)
{
return Task.CompletedTask;
}

public override Task SubSelect_Union(bool isAsync)
{
return Task.CompletedTask;
}

public override Task Select_Except_reference_projection(bool isAsync)
{
return Task.CompletedTask;
}

#endregion

[ConditionalTheory(Skip = "Issue#17386")]
public override Task Contains_with_local_tuple_array_closure(bool isAsync)
{
Expand Down