-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Query Execution
-
None
-
Fully Compatible
-
ALL
-
-
Query Execution 2021-05-03
-
None
-
None
-
None
-
None
-
None
-
None
-
None
When the collection contains a single document (which has no field named "missing"), the following query succeeds with SBE off but fails when SBE is on:
coll.aggregate([{$project: {_id: 0, out: {$split: ["$missing", {$toLower: "$missing"}]}}}])
I believe the problem relates to different evaluation orders. The classic engine first checks whether each of $split's arguments are nullish, and if so returns null. This means that the $split expression returns null due to to its first argument evaluating to null, prior to doing any validation checks for the second argument. SBE, on the other hand, uses a plan which appears to validate the second argument before the first. The $toLower expression returns an empty string, which fails since this is an illegal value as the second parameter to $split. Here is the SBE plan, with a few edits I made to the spacing to make it more legible:
[2] traverse s10 s9 s2 {} {}
from
[1] scan s2 s3 [] @\"09a5b5d4-ba95-401e-bbd8-076034ee9c93\" true
in
[2] mkbson s9 s2 [] keep [out = s8] true false
[2] project [s8 = let [l2.0 = s5, l2.1 = let [l1.0 = s7]
if (! exists (l1.0) || typeMatch (l1.0, 0x00000440),
\"\",
if (typeMatch (l1.0, 0x000F4206),
toLower (coerceToString (l1.0)),
fail ( 5066300 ,$toLower input type is not supported)))]
if (! exists (l2.1) || typeMatch (l2.1, 0x00000440),
null,
if (! isString (l2.1),
fail ( 5155400 ,$split delimiter must be a string),
if (l2.1 == \"\",
fail ( 5155401 ,$split delimiter must not be an empty string),
if (! exists (l2.0) || typeMatch (l2.0, 0x00000440),
null,
if (! isString (l2.0),
fail ( 5155402 ,$split string expression must be a string),
if (l2.0 == \"\",
[\"\"],
split (l2.0, l2.1)))))))]
[2] traverse s7 s7 s6 [s4, s5] {} {}
from
[2] project [s6 = getField (s2, \"missing\")]
[2] traverse s5 s5 s4 {} {}
from
[2] project [s4 = getField (s2, \"missing\")]
[2] limit 1
[2] coscan
in
[2] project [s5 = s4]
[2] limit 1
[2] coscan
in
[2] project [s7 = s6]
[2] limit 1
[2] coscan