Fix to #28648 - Json/Query: translate element access of a json array#29656
Fix to #28648 - Json/Query: translate element access of a json array#29656
Conversation
517e7c7 to
f0daace
Compare
src/EFCore.Relational/Query/Internal/CollectionIndexerToElementAtConvertingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs
Outdated
Show resolved
Hide resolved
...l/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
Show resolved
Hide resolved
a67d570 to
f852a75
Compare
...EFCore.Relational/Query/Internal/CollectionIndexerToElementAtNormalizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
f852a75 to
3f1b691
Compare
|
new version up @roji |
roji
left a comment
There was a problem hiding this comment.
LGTM, lots of comments but almost all nits. Would prefer we didn't exempt byte[] from the ElementAt normalization though...
...EFCore.Relational/Query/Internal/CollectionIndexerToElementAtNormalizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
...EFCore.Relational/Query/Internal/CollectionIndexerToElementAtNormalizingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
| var subquery = mcne.Subquery; | ||
|
|
||
| if (subquery is MethodCallExpression selectMethodCall | ||
| && selectMethodCall.Method.IsGenericMethod |
There was a problem hiding this comment.
Can integrate into pattern above (also block below)
| // MCNE(JSON_QUERY($[0].Collection)) | ||
| // MCNE(JSON_QUERY($[0].Collection).AsQueryable()) | ||
| // MCNE(JSON_QUERY($[0].Collection).Select(xx => xx.Includes()) | ||
| // MCNE(JSON_QUERY($[0].Collection).AsQueryable().Select(xx => xx.Includes()) |
There was a problem hiding this comment.
Can we also have AsQueryable after the Select? If so that's not handled below (can just do a while loop to unwrap until nothing is left).
There was a problem hiding this comment.
we don't produce those kinds of expressions - we add asqueryable when the collection is List or other Enumerable. So its always either AsQueryable().Select() or just Select(). Of course customers could also write queries like that (but why?)
There was a problem hiding this comment.
OK, thanks for clarifying, no problem.
3999868 to
8f76e65
Compare
|
new version up @roji |
Converting indexer over list/array into ElementAt, so that nav expansion understands it and can perform pushown and inject MaterializeCollectionNavigation expression where necessary. In translation phase (specifically in ExpandSharedTypeEntities) we recognize the pattern that nav expansion creates and if the root is JsonQueryExpression, we apply collection index over it. JsonQueryExpression path segment now consists of two components - string representing JSON property name and SqlExpression representing collection index (it can be constant, parameter or any arbitrary expression that resolves to int) Deduplication is heavily restricted currently - we only de-duplicate projections whose additional path consists of JSON property accesses only (no collection indexes allowed). All queries projecting entities that need JSON array access must be set to NoTracking (for now). This is because we don't flow those collection index values into shaper. Instead, the ordinal keys are filled with dummy values, which prohibits us from doing proper change tracking. Fixes #28648
8f76e65 to
94be38c
Compare
Converting indexer over list/array into ElementAt, so that nav expansion understands it and can perform pushown and inject MaterializeCollectionNavigation expression where necessary. In translation phase we recognize the pattern that nav expansion creates and if the root is JsonQueryExpression, we apply collection index over it. JsonQueryExpression path segment now consists of two components - string representing JSON property name and SqlExpression representing collection index (it can be constant, parameter or any arbitrary expression that resolves to int)
Deduplication is heavily restricted currently - we only de-duplicate projections whose additional path consists of JSON property accesses only (no collection indexes allowed). All queries projecting entities that need JSON array access must be set to NoTracking (for now). This is because we don't flow those collection index values into shaper. Instead, the ordinal keys are filled with dummy values, which prohibits us from doing proper change tracking.
Fixes #28648