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

Make ParameterExtractingExpressionVisitor capable of extracting paths to evaluatable fragments in the tree #32999

Closed
roji opened this issue Feb 2, 2024 · 1 comment · Fixed by #33106
Assignees
Labels
area-aot area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement

Comments

@roji
Copy link
Member

roji commented Feb 2, 2024

Our precompiled query feature (for supporting NativeAOT) involves intercepting query LINQ operators. The terminating query operator is replaced with an implementation that actually executes the query, while intermediate operators are basically no-ops, simply propagating the root DbContext forward to the terminating operator.

However, if an operator accepts a lambda, that lambda can capture variables; this is how query parameters are expressed in EF queries:

var name = "foo";
var blogs = await context.Blogs.Where(b => b.Name == name).ToListAsync();

In these cases, the interceptor for Where() must be capable of extracting the captured variable's value (which will be different each time the query is executed), and passing it as a query parameter. This means that we need to be able to inspect a LINQ expression tree (the lambda argument to Where), identify evaluatable fragments, and generate interceptor code that will extract those fragments when such a tree is given.

We'll modify the ParameterExtractingExpressionVisitor to have an additional mode, which is used at publish-time when generating query interceptors. This should use the same logic as the regular query execution path, but instead of actually extracting parameters (which are irrelevant at this point), the visitor will produce a tree of paths to all evaluatable fragments. The query precompilation can then take this tree and generate interceptor code based on it which will drill into the given tree, evaluate the relevant fragments and store the results as query parameters in our QueryContext.

As this is quite a change for ParameterExtractingExpressionVisitor, we may as well also optimize it (#32698).

@roji roji self-assigned this Feb 2, 2024
@roji roji added this to the 9.0.0 milestone Feb 5, 2024
roji added a commit to roji/efcore that referenced this issue Feb 10, 2024
roji added a commit to roji/efcore that referenced this issue Feb 10, 2024
roji added a commit to roji/efcore that referenced this issue Feb 15, 2024
roji added a commit to roji/efcore that referenced this issue Feb 15, 2024
roji added a commit to roji/efcore that referenced this issue Feb 15, 2024
@roji roji added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Feb 15, 2024
roji added a commit to roji/efcore that referenced this issue Feb 15, 2024
roji added a commit to roji/efcore that referenced this issue Feb 15, 2024
roji added a commit that referenced this issue Feb 22, 2024
@roji
Copy link
Member Author

roji commented Feb 23, 2024

Funcletizer features that cannot be supported in precompiled (or compiled!) mode (basically anything that modifies the tree based on a captured variable):

  • EF.Constant
  • [NotParameterized] with non-constant (e.g. EF.Property)
  • Bool-based optimizations for binary/conditional expressions (e.g. someParam ? x : y is reduced to x/y based on someParam).
    • This already doesn't happen for compiled queries, i.e. you can a CASE/WHEN.
  • Null-based optimization for coalesce (e.g. someParam ?? x is reduced to somParam/x based on somParam).
    • Similar to the bool-based optimizations above, but this optimization should be movable to SqlNullabilityProcessor, as it's null-based

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-aot area-query closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants