Skip to content

Commit

Permalink
Query: Remove public setters from customer expression properties
Browse files Browse the repository at this point in the history
Resolves #19192

Changes
- Only server side query expression are in place updated using private setters, public methods
- Moved to Update method pattern in certain cases
- TableExpressionBase still has internal set which will be fixed in #17337
- ShapedQueryExpression.VisitChildren throws now. Since ShapedQuery contains query expression (server side) and shaper expression (client side), it is unlikely that a visitor needs to visit both components. Hence we force visitor to decide which component to visit. This improves perf as we wouldn't go into client side shaper when updating something in sql tree
  • Loading branch information
smitpatel committed Jan 6, 2020
1 parent c2406e7 commit c41a2f1
Show file tree
Hide file tree
Showing 17 changed files with 282 additions and 346 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,9 @@ protected override ShapedQueryExpression TranslateCast(ShapedQueryExpression sou
Check.NotNull(source, nameof(source));
Check.NotNull(resultType, nameof(resultType));

if (source.ShaperExpression.Type == resultType)
{
return source;
}

source.ShaperExpression = Expression.Convert(source.ShaperExpression, resultType);

return source;
return source.ShaperExpression.Type != resultType
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, resultType))
: source;
}

/// <summary>
Expand Down Expand Up @@ -256,9 +251,7 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so

selectExpression.ClearOrdering();
selectExpression.ReplaceProjectionMapping(projectionMapping);
source.ShaperExpression = new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(int));

return source;
return source.UpdateShaperExpression(new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(int)));
}

/// <summary>
Expand Down Expand Up @@ -342,12 +335,9 @@ protected override ShapedQueryExpression TranslateFirstOrDefault(
var selectExpression = (SelectExpression)source.QueryExpression;
selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1)));

if (source.ShaperExpression.Type != returnType)
{
source.ShaperExpression = Expression.Convert(source.ShaperExpression, returnType);
}

return source;
return source.ShaperExpression.Type != returnType
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
: source;
}

/// <summary>
Expand Down Expand Up @@ -449,12 +439,9 @@ protected override ShapedQueryExpression TranslateLastOrDefault(
selectExpression.ReverseOrderings();
selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(1)));

if (source.ShaperExpression.Type != returnType)
{
source.ShaperExpression = Expression.Convert(source.ShaperExpression, returnType);
}

return source;
return source.ShaperExpression.Type != returnType
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
: source;
}

/// <summary>
Expand Down Expand Up @@ -510,9 +497,7 @@ protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpressio

selectExpression.ClearOrdering();
selectExpression.ReplaceProjectionMapping(projectionMapping);
source.ShaperExpression = new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(long));

return source;
return source.UpdateShaperExpression(new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(long)));
}

/// <summary>
Expand Down Expand Up @@ -657,10 +642,7 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s

var newSelectorBody = ReplacingExpressionVisitor.Replace(selector.Parameters.Single(), source.ShaperExpression, selector.Body);

source.ShaperExpression = _projectionBindingExpressionVisitor
.Translate(selectExpression, newSelectorBody);

return source;
return source.UpdateShaperExpression(_projectionBindingExpressionVisitor.Translate(selectExpression, newSelectorBody));
}

/// <summary>
Expand Down Expand Up @@ -717,12 +699,9 @@ protected override ShapedQueryExpression TranslateSingleOrDefault(
var selectExpression = (SelectExpression)source.QueryExpression;
selectExpression.ApplyLimit(TranslateExpression(Expression.Constant(2)));

if (source.ShaperExpression.Type != returnType)
{
source.ShaperExpression = Expression.Convert(source.ShaperExpression, returnType);
}

return source;
return source.ShaperExpression.Type != returnType
? source.UpdateShaperExpression(Expression.Convert(source.ShaperExpression, returnType))
: source;
}

/// <summary>
Expand Down Expand Up @@ -948,9 +927,7 @@ private ShapedQueryExpression AggregateResultShaper(
shaper = Expression.Convert(shaper, resultType);
}

source.ShaperExpression = shaper;

return source;
return source.UpdateShaperExpression(shaper);
}
}
}
13 changes: 10 additions & 3 deletions src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,19 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
{
Check.NotNull(visitor, nameof(visitor));

var accessExpression = visitor.Visit(AccessExpression);
return Update(visitor.Visit(AccessExpression));
}

return accessExpression != AccessExpression
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Expression Update([NotNull] Expression accessExpression)
=> accessExpression != AccessExpression
? new EntityProjectionExpression(EntityType, accessExpression)
: this;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
4 changes: 1 addition & 3 deletions src/EFCore.Cosmos/Query/Internal/KeyAccessExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
{
Check.NotNull(visitor, nameof(visitor));

var outerExpression = visitor.Visit(AccessExpression);

return Update(outerExpression);
return Update(visitor.Visit(AccessExpression));
}

/// <summary>
Expand Down
4 changes: 1 addition & 3 deletions src/EFCore.Cosmos/Query/Internal/ObjectAccessExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
{
Check.NotNull(visitor, nameof(visitor));

var outerExpression = visitor.Visit(AccessExpression);

return Update(outerExpression);
return Update(visitor.Visit(AccessExpression));
}

/// <summary>
Expand Down
4 changes: 1 addition & 3 deletions src/EFCore.Cosmos/Query/Internal/OrderingExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,9 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual OrderingExpression Update([NotNull] SqlExpression expression)
{
return expression != Expression
=> expression != Expression
? new OrderingExpression(expression, IsAscending)
: this;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down
18 changes: 8 additions & 10 deletions src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private readonly IDictionary<EntityProjectionExpression, IDictionary<IProperty,
private ParameterExpression _groupingParameter;

public virtual IReadOnlyList<Expression> Projection => _valueBufferSlots;
public virtual Expression ServerQueryExpression { get; [param: NotNull] set; }
public virtual Expression ServerQueryExpression { get; private set; }
public virtual ParameterExpression CurrentParameter => _groupingParameter ?? _valueBufferParameter;
public override Type Type => typeof(IEnumerable<ValueBuffer>);
public sealed override ExpressionType NodeType => ExpressionType.Extension;
Expand Down Expand Up @@ -198,6 +198,9 @@ private IEnumerable<IProperty> GetAllPropertiesInHierarchy(IEntityType entityTyp
public virtual Expression GetMappedProjection([NotNull] ProjectionMember member)
=> _projectionMapping[member];

public virtual void UpdateServerQueryExpression([NotNull] Expression serverQueryExpression)
=> ServerQueryExpression = serverQueryExpression;

public virtual void PushdownIntoSubquery()
{
var clientProjection = _valueBufferSlots.Count != 0;
Expand Down Expand Up @@ -317,16 +320,11 @@ public virtual void ApplyDefaultIfEmpty()
}

private static IPropertyBase InferPropertyFromInner(Expression expression)
{
if (expression is MethodCallExpression methodCallExpression
=> expression is MethodCallExpression methodCallExpression
&& methodCallExpression.Method.IsGenericMethod
&& methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod)
{
return (IPropertyBase)((ConstantExpression)methodCallExpression.Arguments[2]).Value;
}

return null;
}
&& methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod
? (IPropertyBase)((ConstantExpression)methodCallExpression.Arguments[2]).Value
: null;

public virtual void ApplyProjection()
{
Expand Down
Loading

0 comments on commit c41a2f1

Please sign in to comment.