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

Json full query support well almost #31369

Merged
merged 4 commits into from
Aug 1, 2023
Merged

Conversation

maumar
Copy link
Contributor

@maumar maumar commented Jul 28, 2023

building on top of @roji 's json query support #31095


_nvarchar4000TypeMapping ??= _typeMappingSource.FindMapping("nvarchar(4000)");

if (columnExpression.TypeMapping!.ElementTypeMapping is not null)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to know if the underlying value was scalar or primitive array - i'm using TypeMapping.ElementTypeMapping is not null for that purpose (is there a better way?) Also, when we are building JsonScalar, in sql generator we have code to introduce casts when they are needed (based on expected type mapping), so perhaps we can avoid manually adding the cast below (in some cases?).

Copy link
Member

@roji roji Jul 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I understand.

First, I think possibly the more robust/correct way to recognize an OPENJSON over a primitive collection is simply to check if the path is '$'. Looking at the type mapping as you've done should work, but I think that ideally we should be pattern matching on the query tree structure. I'd still add an assertion that ElementTypeMapping isn't null in that case, just for extra checking.

Second, does this code add a JsonScalarExpression for the primitive collection case? Because I don't think that's needed (it wasn't happening before): for that case OPENJSON without WITH just returns the elements of the primitive collection (they still need to be cast to the right type because they're nvarchar(4000)).

So I'd split RewriteOpenJsonColumn a bit more along primitive vs. non-primitive lines. i.e. for primitive collections, just slap the cast on; otherwise, add JsonScalarExpression and refrain from the cast. It may even make sense to have two different functions here.

Makes sense?

@maumar maumar force-pushed the json_full_query_support_well_almost branch 2 times, most recently from 06dea50 to a4f4769 Compare July 28, 2023 07:22
- adding support for projecting primitive arrays from JSON entities (making sure we can deal with all the Includes that owned types generate by default)
- some other fixes
- more tests
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maumar looks pretty good. There's definitely some cleanup potential but we can do that later. Apart from a few nits should be good for merging.

Note that if you think there's a chance you can get the projection fully working (as discussed offline) before you leave on vacation, that's obviously the high-priority thing - I can always take care of the nits and merge later. Up to you.


_nvarchar4000TypeMapping ??= _typeMappingSource.FindMapping("nvarchar(4000)");

if (columnExpression.TypeMapping!.ElementTypeMapping is not null)
Copy link
Member

@roji roji Jul 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I understand.

First, I think possibly the more robust/correct way to recognize an OPENJSON over a primitive collection is simply to check if the path is '$'. Looking at the type mapping as you've done should work, but I think that ideally we should be pattern matching on the query tree structure. I'd still add an assertion that ElementTypeMapping isn't null in that case, just for extra checking.

Second, does this code add a JsonScalarExpression for the primitive collection case? Because I don't think that's needed (it wasn't happening before): for that case OPENJSON without WITH just returns the elements of the primitive collection (they still need to be cast to the right type because they're nvarchar(4000)).

So I'd split RewriteOpenJsonColumn a bit more along primitive vs. non-primitive lines. i.e. for primitive collections, just slap the cast on; otherwise, add JsonScalarExpression and refrain from the cast. It may even make sense to have two different functions here.

Makes sense?

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving @maumar's work; am taking over for the remaining nits/cleanups.

@roji roji force-pushed the json_full_query_support_well_almost branch from a621d09 to 1cb3250 Compare July 31, 2023 21:29
@maumar
Copy link
Contributor Author

maumar commented Jul 31, 2023

@roji 's changes look good as well. One thing to consider - in sqlite case we could do something similar to what we do for OPENJSON without WITH - it's essentially the same case. I.e. generate faux columns in the translation phase and store the json path information on the json_each node itself (like we do for SqlServerOpenJsonExpression. And then in post translation phase convert those columns to jsonscalars - we do that for sql server when we need (i.e. when we need key column for order or as identifier), in sqlite we would do this step always. OTOH this approach might be more hacky then the current FakeMember (which is also temporary if we extend/change the projection/binding logic), but food for thought

@roji roji merged commit 7a572b0 into main Aug 1, 2023
7 checks passed
@roji roji deleted the json_full_query_support_well_almost branch August 1, 2023 12:14
ranma42 added a commit to ranma42/efcore that referenced this pull request Jun 2, 2024
roji pushed a commit that referenced this pull request Jun 2, 2024
* Re-enable `Json_collection_of_primitives_SelectMany`

Fixed by #31369.

* Re-enable `Column_collection_inside_json_owned_entity`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants