Skip to content

Commit

Permalink
Cosmos: Stop nesting results in extra JSON object
Browse files Browse the repository at this point in the history
Closes #25527
  • Loading branch information
roji committed Jul 5, 2024
1 parent 20edb63 commit e2ff6ba
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ public static bool TryExtractArray(
Limit: null,
Orderings: [],
IsDistinct: false,
UsesSingleValueProjection: true,
Projection: [{ Expression: var a }]
},
}
Expand Down
4 changes: 1 addition & 3 deletions src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression)
{
// If the SELECT projects a single value out, we just project that with the Cosmos VALUE keyword (without VALUE,
// Cosmos projects a JSON object containing the value).
// TODO: Ideally, just always use VALUE for all single-projection SELECTs - but this like requires shaper changes.
if (selectExpression.UsesSingleValueProjection && projection is [var singleProjection])
if (projection is [var singleProjection])
{
_sqlBuilder.Append("VALUE ");

Expand Down Expand Up @@ -752,7 +751,6 @@ void VisitContainerExpression(Expression containerExpression)
Limit: null,
Orderings: [],
IsDistinct: false,
UsesSingleValueProjection: true,
Projection.Count: 1
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
/// 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.
/// </remarks>
public class ObjectReferenceExpression(IEntityType entityType, string name) : Expression, IAccessExpression
public class ObjectReferenceExpression(IEntityType entityType, string name) : Expression, IPrintableExpression, IAccessExpression
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down Expand Up @@ -72,6 +72,15 @@ string IAccessExpression.PropertyName
protected override Expression VisitChildren(ExpressionVisitor visitor)
=> this;

/// <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 void Print(ExpressionPrinter expressionPrinter)
=> expressionPrinter.Append(Name);

/// <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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
/// 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>
[DebuggerDisplay("{Microsoft.EntityFrameworkCore.Query.ExpressionPrinter.Print(this), nq}")]
public class ProjectionExpression(Expression expression, string alias)
: Expression, IPrintableExpression
{
Expand Down
47 changes: 13 additions & 34 deletions src/EFCore.Cosmos/Query/Internal/Expressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,12 @@ public static SelectExpression CreateForCollection(Expression sourceExpression,
sourceExpression = new SelectExpression(
[new ProjectionExpression(sourceExpression, null!)],
sources: [],
orderings: [])
{
UsesSingleValueProjection = true
};
orderings: []);
}

var source = new SourceExpression(sourceExpression, sourceAlias, withIn: true);

return new SelectExpression(source, projection)
{
UsesSingleValueProjection = true
};
return new SelectExpression(source, projection);
}

/// <summary>
Expand All @@ -112,18 +106,6 @@ [new ProjectionExpression(sourceExpression, null!)],
public IReadOnlyList<ProjectionExpression> Projection
=> _projection;

/// <summary>
/// If set, indicates that the <see cref="SelectExpression" /> has a Cosmos VALUE projection, which does not get wrapped in a
/// JSON object. If <see langword="true" />, <see cref="Projection" /> must contain a single item.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public bool UsesSingleValueProjection { get; init; }

/// <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
Expand Down Expand Up @@ -595,8 +577,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor)
Predicate = predicate,
Offset = offset,
Limit = limit,
IsDistinct = IsDistinct,
UsesSingleValueProjection = UsesSingleValueProjection
IsDistinct = IsDistinct
};

return newSelectExpression;
Expand Down Expand Up @@ -632,7 +613,6 @@ public SelectExpression Update(
Offset = offset,
Limit = limit,
IsDistinct = IsDistinct,
UsesSingleValueProjection = UsesSingleValueProjection,
ReadItemInfo = ReadItemInfo
};
}
Expand All @@ -658,7 +638,6 @@ public SelectExpression WithSingleValueProjection()
Offset = Offset,
Limit = Limit,
IsDistinct = IsDistinct,
UsesSingleValueProjection = true
};
}

Expand Down Expand Up @@ -711,18 +690,18 @@ private void PrintSql(ExpressionPrinter expressionPrinter, bool withTags = true)
expressionPrinter.Append("DISTINCT ");
}

if (Projection.Any())
switch (Projection)
{
if (UsesSingleValueProjection)
{
case []:
expressionPrinter.Append("1");
break;
case [var singleProjection]:
expressionPrinter.Append("VALUE ");
}

expressionPrinter.VisitCollection(Projection);
}
else
{
expressionPrinter.Append("1");
expressionPrinter.Visit(singleProjection);
break;
default:
expressionPrinter.VisitCollection(Projection);
break;
}

if (Sources.Count > 0)
Expand Down

0 comments on commit e2ff6ba

Please sign in to comment.