[SERVER-49943] [SBE] Fix edge case bug with 'find({"a.b.c": ..})' Created: 28/Jul/20 Updated: 29/Oct/23 Resolved: 19/Nov/20 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Querying |
| Affects Version/s: | None |
| Fix Version/s: | 4.9.0 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Drew Paroski | Assignee: | Melodee Li |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | qexec-team | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Backwards Compatibility: | Fully Compatible | |||||||||||||||||||||||||||
| Operating System: | ALL | |||||||||||||||||||||||||||
| Steps To Reproduce: |
|
|||||||||||||||||||||||||||
| Sprint: | Query 2020-11-30 | |||||||||||||||||||||||||||
| Participants: |
| Description |
|
While doing some manual testing with SBE mode enable, I encountered an edge case involving dot notation where find() doesn't always match a document when it should. See "Steps To Reproduce" for a specific example of the bug I encountered. Upon investigation, I found that despite all the recent work ( In the example shown in "Steps To Reproduce", the second document in collection c has an array field 'a' that contains two objects, where the first object has a field 'b' whose value is the empty array, and where the second object has an array field 'b' containing an object with a field 'c'. The command 'find({"a.b.c": 2})' should match the second document, but it doesn't because of an issue with the outermost TraverseStage and the TraverseStage at the second level of nesting. Here is the SBE plan we currently generate for 'find({"a.b.c": 2})':
The "from" clause of the TraverseStage at the second level of nesting is 's5 = getField (s4, "b")'. When processing the second document in collection c, this TraverseStage gets invoked twice. For the first invocation, field "b"s value is the empty array, and so the TraverseStage's fold expression is never executed and the TraverseStage produces Nothing. For the second invocation, field "b"s value is an array containing an object with field "c" whose value is true, and so the TraverseStage produces Boolean true (because the innermost TraverseStage will visit field "c", compare 2==2, and produce Boolean true). When the outermost TraverseStage applies its fold expression, it ANDs together Nothing and Boolean True which produces Nothing, which causes the second document in collection c to not match (even though it should match). Three possible ways to fix this that come to mind: |
| Comments |
| Comment by Githook User [ 19/Nov/20 ] |
|
Author: {'name': 'Melodee Li', 'email': 'melodeeli98@gmail.com', 'username': 'melodeeli98'}Message: )' |
| Comment by Martin Neupauer [ 28/Jul/20 ] |
|
There is no need to change Traverse. so #1 or #3. |
| Comment by David Storch [ 28/Jul/20 ] |
|
I actually like proposed fix #2. martin.neupauer I'm curious if you have opinions on the right fix, and in particular what you think about extending the traverse stage to allow specifying an EExpression which is executed to obtain the initial value of the fold. In this particular case, the expression would be an EConstant containing a false value. |