- Notifications
You must be signed in to change notification settings - Fork 3.3k
Implemement set operation query support for complex JSON #36417
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
Conversation
58d631a to f934356 Compare There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements set operation query support for complex JSON by extending the Entity Framework Core query pipeline to handle UNION operations over complex JSON structures. It addresses various issues in navigation expansion and adds comprehensive test coverage for different relationship types.
- Adds support for set operations (UNION, INTERSECT, EXCEPT) on complex JSON properties and collections
- Fixes navigation expansion issues when dealing with complex property references in set operations
- Implements proper SQL generation for JSON-mapped complex types in set operation scenarios
Reviewed Changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| NavigationExpandingExpressionVisitor.cs | Enhanced to handle ComplexPropertyReference and ComplexTypeReference in set operations |
| NavigationExpandingExpressionVisitor.Expressions.cs | Added ComplexTypeReference class and improved ComplexPropertyReference handling |
| SelectExpression.cs | Added comprehensive JSON handling logic for set operations with proper projection management |
| SqliteQueryableMethodTranslatingExpressionVisitor.cs | Extended JSON query transformation to include complex properties |
| Test files | Added comprehensive test coverage for set operations across different relationship types |
Comments suppressed due to low confidence (1)
src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs Outdated Show resolved Hide resolved
And fix various related issues in nav expansion Part of dotnet#36296
f934356 to 5ebed4f Compare | { | ||
| Check.DebugAssert(jsonQuery1.StructuralType == jsonQuery2.StructuralType); | ||
| Check.DebugAssert(jsonQuery1.Type == jsonQuery2.Type); | ||
| Check.DebugAssert(jsonQuery1.IsNullable == jsonQuery2.IsNullable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it safe to assume that the nullability will be the same? Are they modified to match each other earlier in the pipeline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch - it's a wrong assertion indeed. Below there was even some logic to handle nullability based on the nullability in each side, but that too was incomplete, pushed a fix.
It's proving surprisingly difficult to cover this case with a test - I'm not sure we already had coverage in the traditional tests... Specifically for the same type being projected once in a nullable and once in a non-nullable way. The various queries I've tried fail translation for other reasons currently.
| // So we create fake members to hold the JSON property name for the alias. | ||
| var projectionMember = new ProjectionMember().Append(new FakeMemberInfo(jsonPropertyName)); | ||
| | ||
| propertyJsonScalarExpression[projectionMember] = new JsonScalarExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
containerColumnName does not seem to be used outside of the Assert.
The comment // We're only interested in properties which actually exist in the JSON, filter out uninteresting shadow keys is incorrect as you aren't filtering out shadow properties. Also, invert the condition to reduce nesting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re shadow keys/properties, the intent here was to mean that we want to jump over the synthetic key properties, which don't actually exist in the JSON document - that's what the if (property.GetJsonPropertyName() is string jsonPropertyName) does.
I'll change the comment to filter out uninteresting synthetic keys to make it clearer.
| | ||
| var projectionMember = new ProjectionMember().Append(new FakeMemberInfo(jsonNavigationName)); | ||
| | ||
| propertyJsonScalarExpression[projectionMember] = new JsonScalarExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's strange that the type is called JsonScalarExpression when it also represents non-scalars
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tell me about it - this prompted me to file #36392, which contains the details. tl;dr JsonQueryExpression doesn't actually represent JSON_QUERY() in SQL, but rather represents a JSON being projected out of the database (so shaper-side expression only). Whe projections are applied (subquery pushdown, or when translation ends), any projected JsonQueryExpression gets converted to JsonScalarExpression.
... very questionable.
| : RelationshipsSetOperationsTestBase<TFixture>(fixture) | ||
| where TFixture : ComplexPropertiesFixtureBase, new() | ||
| { | ||
| // TODO: the following is temporary until change tracking is implemented for complex JSON types (#35962) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already implemented 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this will be taken care of in #36430.
b40f2fb to 5e7bbc0 Compare
And fix various related issues in nav expansion
Part of #36296