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

Support any expression type inside inline primitive collections #31046

Merged
merged 2 commits into from
Jun 13, 2023

Conversation

roji
Copy link
Member

@roji roji commented Jun 6, 2023

  • InExpression can now contain a list of SqlExpressions, just like SQL IN can hold anything in its values. It can still hold a ValuesParameter for the inefficient "legacy" mode where the collection parameters gets expanded to constants in SqlNullabilityProcessor.
  • ParameterExtractingExpressionVisitor now refrains from client-evaluating NewExpression when it's at the top of the evaluatable sub-tree. This allows us to get NewArrayExpression when it contains only parameters, rather than a single parameter containing a client-evaluated array value (which is opaque to translation).

Closes #30732
Closes #30734

@roji roji requested a review from maumar June 6, 2023 21:22
@roji roji force-pushed the InlineCollectionsWithEverything branch 2 times, most recently from 93e05c7 to de656e7 Compare June 6, 2023 22:34
@@ -2745,14 +2745,11 @@ SELECT c

public override async Task Array_of_parameters_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(bool async)
{
await base.Array_of_parameters_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(async);
// #31051
await AssertTranslationFailed(
Copy link
Member Author

Choose a reason for hiding this comment

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

Note this breaking change: since NewArrayExpression with parameters is no longer client-evaluated in ParameterExtractingEV (into a single parameter with an array-of-constants value), the node reaches translation where it fails translation (NewArrayExpression with all constants is handled).

Opened #30966 to track, and will bring to design.

Copy link
Member Author

Choose a reason for hiding this comment

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

This breaking change has been removed by having Cosmos handle NewArrayExpression properly within Contains. However, it still does not opt into query roots, so the whole thing is handled as enumerable, not queryable - #30966 still tracks that work.

@roji roji marked this pull request as ready for review June 7, 2023 15:50
@roji
Copy link
Member Author

roji commented Jun 10, 2023

@maumar @ajcvickers I pushed an additional commit which makes the "Contains over array of parameters" scenario work again on Cosmos, so there's no more breaking change. This also generally improves the Cosmos infrastructure around Contains, in case we want to improve further in the future (e.g. any expression type inside the inline collection, like this PR does for relational).

break;

default:
throw new ArgumentOutOfRangeException();
Copy link
Contributor

@maumar maumar Jun 12, 2023

Choose a reason for hiding this comment

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

I think I like this style over throw new InvalidOperationException("IMPOSSIBLE"); Either way, should we unify across the board?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, however... .NET 7.0 introduced UnreachableException, which is exactly the right thing for this case (and many others, e.g. Debug.Fail). We currently only target net6.0 so we can't use it, but we should do a pass once we change TFMs to net8.0 and just switch to that...

Sounds good? I'd be happy to do the pass once we switch TFMs...

// for each one.
// non_nullable IN (1, 2, nullable) -> non_nullable IN (1, 2) OR (non_nullable = nullable AND nullable IS NOT NULL) (full)
// non_nullable IN (1, 2, NULL, nullable) -> non_nullable IN (1, 2) OR (non_nullable = nullable AND nullable IS NOT NULL) (full)
return nullableValues.Aggregate(
Copy link
Contributor

Choose a reason for hiding this comment

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

@roji now I see why you wanted to get rid of "Negated" from all those expressions. This logic is not easy :D

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that's exactly how it went :) I started working on this, and then decided it's crazy to have to deal with negation as well...

@roji roji force-pushed the InlineCollectionsWithEverything branch from f3e4c6d to 641975d Compare June 13, 2023 07:24
@roji roji merged commit 7d3e715 into dotnet:main Jun 13, 2023
@roji roji deleted the InlineCollectionsWithEverything branch June 13, 2023 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants