|
NULLIF(expr1, expr2) currently evaluates expr1 two times.
The first time to do comparison expr1=expr2, and the second time to return expr1 if the comparison evaluated to false.
While reviewing MDEV-9181, Sergei proposed to evaluate expr1 only one time.
It should be easy on top of the MDEV-9181 patch.
Rationale
Evaluating expr1 twice is not obvious at all, it's very unexpected and difficult-to-explain behavior from the user point of view, a gotcha.
The standard position
- According to the standard, NULLIF(x,y) is equivalent to CASE WHEN x=y THEN NULL ELSE x END. So it kind of implies that x is evaluated twice.
- On the other hand, COALESCE(x,y) is equivalent to CASE WHEN x IS NOT NULL THEN x ELSE y END. Which implies the same, but we do not evaluate x twice in COALESCE.
- The standard isn't crazy enough to say that x is evaluated twice, it solves the issue as A <value expression> generally contained in the <case abbreviation> shall not generally contain a <routine invocation> whose subject routine is an SQL-invoked routine that is possibly non-deterministic or that possibly modifies SQL-data. In other words, according to the standard x can not have side-effects, so it does not matter how many times it is evaluated. We don't place this restriction on x.
Other databases
- SQL Server has this remark: We recommend that you not use time-dependent functions, such as RAND(), within a NULLIF function. This could cause the function to be evaluated twice and to return different results from the two invocations. And it has the same about COALESCE This means that the input values (expression1, expression2, expressionN, etc.) will be evaluated multiple times. <...> In either case, different results can be returned between the first evaluation and subsequent evaluations. <...> As a result, you can get different results depending on the isolation level of the query.
|