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

Better cast/convert support for Cosmos #35000

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ChrisJollyAU
Copy link
Contributor

Improve the support and handling of the cast/converts in Cosmos

Originally started for #34963 but after #34982 was created extended that work to more cases

VisitUnary now leaves the Convert operation in place instead of stripping it. This has 2 potential benefits:

  • Similarity between Cosmos and relational may help any efforts to create a common shared base rather than a lot of duplication of things (e.g. SqlExpressionFactory etc) in Cosmos
  • Leaving it in place allows binary expressions to work out what type mapping the Convert needs (if it doesn't have one already)
  • This is especially the case with string concatenation to an int or something like that. the int value will have a Convert to type of Object - aka we know we need a convert but we don't yet know what to convert it to. The type mapping handling of the binary expression will work it out and apply to all sides

In the QuerySqlGenerator, we effectively no-op most casts except for if we have a convert to string.

This does light up a number of math function tests that were failing - all of them due to #17246 (client evaluation exception)
Also some tests for #20677 are now passing (not all of them related to that issue)
The Cosmos tests for #34729 are now passing as well

This fixes #34982

@ChrisJollyAU ChrisJollyAU requested a review from a team as a code owner October 28, 2024 16:43
@AndriySvyryd AndriySvyryd requested a review from Copilot December 4, 2024 20:56

Choose a reason for hiding this comment

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

Copilot reviewed 5 out of 12 changed files in this pull request and generated no suggestions.

Files not reviewed (7)
  • src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs: Evaluated as low risk
  • src/EFCore.Cosmos/Query/Internal/Expressions/SqlUnaryExpression.cs: Evaluated as low risk
  • src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs: Evaluated as low risk
  • src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs: Evaluated as low risk
  • test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs: Evaluated as low risk
  • test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs: Evaluated as low risk
  • src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs: Evaluated as low risk
@ChrisJollyAU
Copy link
Contributor Author

@roji Was just working on this to update and resync everything especially because of all your reorganization of the tests and have a question.

In the original NorthwindFunctions you have the test Where_mathf_floor which fails but the new test Floor_float passes. There is in fact a difference between the 2 and that is that there is a cast to the function parameter.

Can be summarized by this test (based on Floor_float)

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Floor_float_double(bool async)
    => AssertQuery(
        async,
        ss => ss.Set<BasicTypesEntity>().Where(b => MathF.Floor((float)b.Double) == 8));

In the current main branch this will fail (not translated) but with this PR it does work.
Is there any test in the new set of tests that does test this sort of cast/convert as the transition to MathTranslations seems to have simplified that aspect out?

@roji
Copy link
Member

roji commented Jan 20, 2025

In the original NorthwindFunctions you have the test Where_mathf_floor which fails but the new test Floor_float passes. There is in fact a difference between the 2 and that is that there is a cast to the function parameter.

OK, understood. Yeah, part of the translation test refactoring was also about making it very clear the intent behind each test, and trying to test exactly one thing. If there's an issue specifically with the downcast, then that's something we should verify in a separate test that focuses on downcasting (and is named appropriately).

There's a Translations/Operators folder where we have test suites for operator translation - a test inside MiscellaneousOperatorTranslationsTestBase probably makes sense here (or we could even start a new CastOperatorTransationsTestBase if we think we'll add more coverage specifically around casting...).

How does that sound?

@ChrisJollyAU
Copy link
Contributor Author

CastOperatorTranslation would probably work if you had lots of casts in various ways that you wanted to test.

To me it might make more sense to do it in the same place as the original i.e. you have one test normal with direct value and the next test with the cast. Then you end up dealing with the same tables and data and if you modify something for one, you have all the similar tests close by to modify as well

@roji
Copy link
Member

roji commented Jan 20, 2025

To me it might make more sense to do it in the same place as the original i.e. you have one test normal with direct value and the next test with the cast. Then you end up dealing with the same tables and data and if you modify something for one, you have all the similar tests close by to modify as well

The thing is that one test here (the missing one) tests only the downcast, without it mattering at all which function (or even type) is involved, whereas the other one tests translation for a specific function on a specific type (MathF.Floor), no? Unless you think there is (or could be) a specific issue with the translation of MathF.Floor around the cast?

Also, note that all the translation tests already use the same tables and data. The idea is to try to be in a place where data can be added to accomodate new tests, without that breaking existing tests (it'll likely not be 100% successful, but that's the idea).

@ChrisJollyAU
Copy link
Contributor Author

Unless you think there is (or could be) a specific issue with the translation of MathF.Floor around the cast?

Pretty sure its just the cast itself and doesn't matter what function its used in.

But this is more of a Cosmos specific issue. Relational already has this sorted out since practically v1

Also, there are a bunch of other tests that seem to test this intrinsically and pass with this fix

e.g. in NorthwindFunctions Where_functions_nested you have a Length (int) within a Math.Pow (double)

So a specific test might not be needed

@ChrisJollyAU
Copy link
Contributor Author

@roji Can see how this goes now. Should be updated and back in sync

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.

Cosmos: review cast/convert handling
2 participants