-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Implement nullability computation for SqlFunctionExpression
#33814
Conversation
SqlFunction
SqlFunctionExpression
@ranma42 I really like this improvement. However, there is a slight change in the semantics of nullability propagation. The original intent for this feature was to improve null check sql (IS NULL / IS NOT NULL), where we can. Here is the original issue: #18555 and pr: #19607 The idea is that argument propagates nullability should be set to true iff (if and only if) the function can result in null based on it's argument being null (which is vast majority of sql functions). However, there is a possibility that a function can be null even if all of the arguments are not null - a good example are some of the JSON functions like JSON_VALUE. Also, users can create their own custom functions that have this property. In those cases function propagates nullability should be set to false for all the arguments, which means that we can't take any shortcuts. If I read the code correctly, the new implementation always takes the argument propagates nullability value into account, so a function which set them all to false will be marked as non-nullable, which is not always correct. Instead, we should check if at least one of the argument propagates nullability, or instance propagates nullability is set to true, and only if that's the case, apply the logic that was added. Otherwise we can't rely on the optimization and we should just use function.IsNullable. See how things are done in ProcessNullNotNull In hindsight, what we probably should have done is to add a property like useNullPropagationInformation, which would allow us to document/communicate this properly to users, rather than rely on this obscure pattern. Alas, to late to change now. |
Sorry, I was not aware of this and I ended up replicating only a part of the
I guess that the trick in this case is that Note that this behavior is not explained in the documentation of
Ah, I see, that's the purpose of the This means that the semantics changes radically. IIUC the semantics are:
I will update the PR shortly to match this.
If this interface was to be redesigned, there are also other cases where it might be interesting to have a richer semantics (for example a UDF with COALESCE-like behavior). AFAICT it might even be possible to extend this part of the
While this might be an interesting research direction (it would ideally remove the special cases for |
Good idea, filed #33833 to track this.
That's exactly the intended logic. Note also that it gives an uncertain user "a way out" - if all of them are set to false we just take the nullability of SqlFunction, we may produce less efficient sql but it will always be correct. Wheras in the previous design user had to correctly specify all the nullability propagation elements or risk data corruption in some cases.
Yeah, I think it's currently not worth the effort needed to get this right. Current design should be ok, especially once we document it bit better |
5474977
to
9e0f48e
Compare
I pushed an updated branch and kept the original one for ease of comparison.
I had to cherry-pick ranma42@1ff7042 from #33814 , otherwise the nullability computation would fail upon the out-of-range access. |
9e0f48e
to
f24ca35
Compare
rebased on top of the current main, to include the nullability arity fixes (which are required to avoid failing the evaluation of nullabilities, specifically for |
another great contribution, thanks! @ranma42 |
The current implementation of
SqlNullabilityProcessor.VisitSqlFunction()
does not take into account the nullability of the function arguments (or the target instance) nor whether they propagate nulls to the function result.This causes several additional null checks, which are not actually needed.
The computation is modeled after
ProcessNullNotNull
, specifically:efcore/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Lines 2280 to 2330 in 48eaf72