Whenever an expression encounters an error and yields no result, this infects the outer expression it is embedded in — any access to an undefined property voids the whole computation for the current input. There currently is only one way to work around this: CASE conditions “catch” the error and try the next condition instead of erroring out immediately. In order to use this facility, the user must formulate a boolean condition to check the data, though.
CASE _.my_property.some_string ≥ '' => _.my_property.x CASE TRUE => 'replacement value' ENDCASE
We solve the last part by adding the function
IsDefined(<expr>), which takes a single argument and evaluates to TRUE if the expression yields a value and FALSE otherwise. With this, one could write
CASE IsDefined(_.my_property) => _.my_property.x CASE TRUE => 'replacement value' ENDCASE
This is an improvement in that the incidental complexity of figuring out a suitable boolean condition is taken away.
One common use of this pattern is to include default values in the query in case the data are incomplete (e.g. from an old version). Here, the condition is usually that the desired value should exist, so we introduce the shorthand notation
_.desired // 'replacement'
which is equivalent to
CASE IsDefined(_.desired) => _.desired CASE TRUE => 'replacement' ENDCASE
// is a binary operator with the lowest precedence.