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

Some code cleanup/style #34062

Merged
merged 1 commit into from
Jun 22, 2024
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 @@ -3248,57 +3248,69 @@ protected override Expression VisitExtension(Expression extensionExpression)
{
var entityProjection = selectExpression.GetProjection(entityProjectionBindingExpression).GetConstantValue<object>();

if (entityProjection is QueryableJsonProjectionInfo || (_insideCollection && entityProjection is JsonProjectionInfo))
switch (entityProjection)
{
throw new InvalidOperationException(
RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)));
}
case QueryableJsonProjectionInfo:
case JsonProjectionInfo when _insideCollection:
throw new InvalidOperationException(
RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(
nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)));

if (entityProjection is JsonProjectionInfo jsonEntityProjectionInfo)
{
var jsonEntityType = (IEntityType)entityShaperExpression.StructuralType;
if (_insideInclude)
case JsonProjectionInfo jsonEntityProjectionInfo:
{
if (!_includedJsonEntityTypes.Contains(jsonEntityType))
var jsonEntityType = (IEntityType)entityShaperExpression.StructuralType;
if (_insideInclude)
{
_includedJsonEntityTypes.Add(jsonEntityType);
if (!_includedJsonEntityTypes.Contains(jsonEntityType))
{
_includedJsonEntityTypes.Add(jsonEntityType);
}
}
else
{
_projectedKeyAccessInfos.Add((jsonEntityType, jsonEntityProjectionInfo.KeyAccessInfo));
}

break;
}
else
{
_projectedKeyAccessInfos.Add((jsonEntityType, jsonEntityProjectionInfo.KeyAccessInfo));
}
}

return extensionExpression;
default:
return extensionExpression;
}
}

if (extensionExpression is CollectionResultExpression { ProjectionBindingExpression: ProjectionBindingExpression collectionProjectionBindingExpression } collectionResultExpression)
{
var collectionProjection = selectExpression.GetProjection(collectionProjectionBindingExpression).GetConstantValue<object>();
if (collectionProjection is QueryableJsonProjectionInfo || (_insideCollection && collectionProjection is JsonProjectionInfo))
{
throw new InvalidOperationException(
RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)));
}

if (collectionProjection is JsonProjectionInfo jsonCollectionProjectionInfo)
switch (collectionProjection)
{
var jsonEntityType = collectionResultExpression.Navigation!.TargetEntityType;
if (_insideInclude)
case QueryableJsonProjectionInfo:
case JsonProjectionInfo when _insideCollection:
throw new InvalidOperationException(
RelationalStrings.JsonProjectingQueryableOperationNoTrackingWithIdentityResolution(nameof(QueryTrackingBehavior.NoTrackingWithIdentityResolution)));

case JsonProjectionInfo jsonCollectionProjectionInfo:
{
if (!_includedJsonEntityTypes.Contains(jsonEntityType))
var jsonEntityType = collectionResultExpression.Navigation!.TargetEntityType;
if (_insideInclude)
{
_includedJsonEntityTypes.Add(jsonEntityType);
if (!_includedJsonEntityTypes.Contains(jsonEntityType))
{
_includedJsonEntityTypes.Add(jsonEntityType);
}
}
else
{
_projectedKeyAccessInfos.Add((jsonEntityType, jsonCollectionProjectionInfo.KeyAccessInfo));
}

break;
}
else
{
_projectedKeyAccessInfos.Add((jsonEntityType, jsonCollectionProjectionInfo.KeyAccessInfo));
}
}

return extensionExpression;
default:
return extensionExpression;
}
}

return base.VisitExtension(extensionExpression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,79 +314,63 @@ public SplitCollectionInfo(

private sealed class ClientProjectionRemappingExpressionVisitor(List<object> clientProjectionIndexMap) : ExpressionVisitor
{
private readonly List<object> _clientProjectionIndexMap = clientProjectionIndexMap;

[return: NotNullIfNotNull(nameof(expression))]
public override Expression? Visit(Expression? expression)
protected override Expression VisitExtension(Expression expression)
{
if (expression is ProjectionBindingExpression projectionBindingExpression)
switch (expression)
{
var value = _clientProjectionIndexMap[projectionBindingExpression.Index!.Value];
if (value is int intValue)
case ProjectionBindingExpression projectionBindingExpression:
{
return new ProjectionBindingExpression(
projectionBindingExpression.QueryExpression, intValue, projectionBindingExpression.Type);
}

if (value is Expression innerShaper)
{
return Visit(innerShaper);
}

throw new InvalidCastException();
}
var value = clientProjectionIndexMap[projectionBindingExpression.Index!.Value];
return value switch
{
int intValue => new ProjectionBindingExpression(
projectionBindingExpression.QueryExpression, intValue, projectionBindingExpression.Type),

if (expression is CollectionResultExpression collectionResultExpression)
{
var innerProjectionBindingExpression = collectionResultExpression.ProjectionBindingExpression;
var value = _clientProjectionIndexMap[innerProjectionBindingExpression.Index!.Value];
if (value is SingleCollectionInfo singleCollectionInfo)
{
return new RelationalCollectionShaperExpression(
singleCollectionInfo.ParentIdentifier,
singleCollectionInfo.OuterIdentifier,
singleCollectionInfo.SelfIdentifier,
singleCollectionInfo.ParentIdentifierValueComparers,
singleCollectionInfo.OuterIdentifierValueComparers,
singleCollectionInfo.SelfIdentifierValueComparers,
singleCollectionInfo.ShaperExpression,
collectionResultExpression.Navigation,
collectionResultExpression.ElementType);
}
Expression innerShaper => Visit(innerShaper),

if (value is SplitCollectionInfo splitCollectionInfo)
{
return new RelationalSplitCollectionShaperExpression(
splitCollectionInfo.ParentIdentifier,
splitCollectionInfo.ChildIdentifier,
splitCollectionInfo.IdentifierValueComparers,
splitCollectionInfo.SelectExpression,
splitCollectionInfo.ShaperExpression,
collectionResultExpression.Navigation,
collectionResultExpression.ElementType);
_ => throw new InvalidCastException()
};
}

if (value is int)
case CollectionResultExpression collectionResultExpression:
{
var binding = (ProjectionBindingExpression)Visit(collectionResultExpression.ProjectionBindingExpression);

return collectionResultExpression.Update(binding);
var innerProjectionBindingExpression = collectionResultExpression.ProjectionBindingExpression;
var value = clientProjectionIndexMap[innerProjectionBindingExpression.Index!.Value];
return value switch
{
SingleCollectionInfo singleCollectionInfo
=> new RelationalCollectionShaperExpression(
singleCollectionInfo.ParentIdentifier, singleCollectionInfo.OuterIdentifier,
singleCollectionInfo.SelfIdentifier, singleCollectionInfo.ParentIdentifierValueComparers,
singleCollectionInfo.OuterIdentifierValueComparers, singleCollectionInfo.SelfIdentifierValueComparers,
singleCollectionInfo.ShaperExpression, collectionResultExpression.Navigation,
collectionResultExpression.ElementType),

SplitCollectionInfo splitCollectionInfo
=> new RelationalSplitCollectionShaperExpression(
splitCollectionInfo.ParentIdentifier, splitCollectionInfo.ChildIdentifier,
splitCollectionInfo.IdentifierValueComparers, splitCollectionInfo.SelectExpression,
splitCollectionInfo.ShaperExpression, collectionResultExpression.Navigation,
collectionResultExpression.ElementType),

int => collectionResultExpression.Update(
(ProjectionBindingExpression)Visit(collectionResultExpression.ProjectionBindingExpression)),

_ => throw new InvalidOperationException()
};
}

throw new InvalidOperationException();
}
case RelationalGroupByResultExpression relationalGroupByResultExpression:
// Only element shaper needs remapping
return new RelationalGroupByResultExpression(
relationalGroupByResultExpression.KeyIdentifier,
relationalGroupByResultExpression.KeyIdentifierValueComparers,
relationalGroupByResultExpression.KeyShaper,
Visit(relationalGroupByResultExpression.ElementShaper));

if (expression is RelationalGroupByResultExpression relationalGroupByResultExpression)
{
// Only element shaper needs remapping
return new RelationalGroupByResultExpression(
relationalGroupByResultExpression.KeyIdentifier,
relationalGroupByResultExpression.KeyIdentifierValueComparers,
relationalGroupByResultExpression.KeyShaper,
Visit(relationalGroupByResultExpression.ElementShaper));
default:
return base.VisitExtension(expression);
}

return base.Visit(expression);
}
}

Expand Down
19 changes: 8 additions & 11 deletions src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -527,22 +527,19 @@ public Expression ApplyProjection(

foreach (var projection in _clientProjections)
{
if (projection is ShapedQueryExpression sqe)
switch (projection)
{
if (sqe.ResultCardinality == ResultCardinality.Enumerable)
{
case ShapedQueryExpression { ResultCardinality: ResultCardinality.Enumerable }:
containsCollection = true;
}
break;

if (sqe.ResultCardinality is ResultCardinality.Single or ResultCardinality.SingleOrDefault)
{
case ShapedQueryExpression { ResultCardinality: ResultCardinality.Single or ResultCardinality.SingleOrDefault }:
containsSingleResult = true;
}
}
break;

if (projection is JsonQueryExpression)
{
jsonClientProjectionsCount++;
case JsonQueryExpression:
jsonClientProjectionsCount++;
break;
}
}

Expand Down