-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Query Execution
-
None
-
Fully Compatible
-
ALL
-
-
Query Execution 2021-05-03
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