[SERVER-72843] Fix SBE stage builder to not use lambda closures Created: 13/Jan/23  Updated: 29/Oct/23  Resolved: 06/Feb/23

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 6.3.0-rc0

Type: Bug Priority: Major - P3
Reporter: Anna Wawrzyniak Assignee: Drew Paroski
Resolution: Fixed Votes: 0
Labels: pm2697-m2
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Problem/Incident
Assigned Teams:
Query Execution
Backwards Compatibility: Fully Compatible
Operating System: ALL
Sprint: QE 2023-02-06, QE 2023-02-20
Participants:
Linked BF Score: 135
Story Points: 5

 Description   

Fix SBE stage builder to not use lambda closures. Lambda closures are not supported and any translation that relies on lambda closures works by a pure coincidence, and may stop working at any time.

 

As part of fixing/verifying the fix, we should add asserts/verificiation when compiling EExpression that rejects compilation of accessing closure variables. Possibly by:

a) verifying the EExpression itself

b) by asserting during lambda compilation that there are no unbound variables leaking out of lambda body. This could be done by asserting that the collection of frames in empty inside CodeFragment::appendNoStack

 

Example of  expression with lambda capture. l2.0 is used inside the nested lambda:

traverseP(s7, lambda(l1.0) { makeBsonObj(MakeObjSpec(keep, ["_id"], ["b"]), l1.0,
[j0]     let [
[j0]         l2.0 = s6
[j0]     ]
[j0]     in
[j0]         let [
[j0]             l7.0 = s4
[j0]         ]
[j0]         in
[j0]             if (typeMatch(l7.0, 1088ll) ?: true)
[j0]             then null
[j0]             else
[j0]                 if isArray(l7.0)
[j0]                 then traverseP(l7.0, lambda(l3.0) {
[j0]                     if (coerceToBool(
[j0]                         let [
[j0]                             l6.0 =
[j0]                                 let [
[j0]                                     l4.0 = s5
[j0]                                     l4.1 = l3.0
[j0]                                 ]
[j0]                                 in
[j0]                                     if ((typeMatch(l4.0, 1088ll) ?: true) || (typeMatch(l4.1, 1088ll) ?: true))
[j0]                                     then null
[j0]                                     else
[j0]                                         if ((!(isNumber(l4.0)) && !(isDate(l4.0))) || (!(isNumber(l4.1)) && !(isDate(l4.1))))
[j0]                                         then fail(4974201, "only numbers and dates are allowed in an $add expression")
[j0]                                         else
[j0]                                             let [
[j0]                                                 l5.0 = l4.0
[j0]                                                 l5.1 = l4.1
[j0]                                             ]
[j0]                                             in
[j0]                                                 if (isDate(l5.0) && isDate(l5.1))
[j0]                                                 then fail(4974202, "only one date allowed in an $add expression")
[j0]                                                 else (l5.0 + l5.1)
[j0]
[j0]                             l6.1 = l2.0
[j0]                         ]
[j0]                         in (((l6.0 <=> l6.1) >= 0) ?: ((exists(l6.0) && typeMatch(l6.0, -65ll)) >= (exists(l6.1) && typeMatch(l6.1, -65ll))))
[j0]                    ) ?: false)
[j0]                     then l3.0
[j0]                     else Nothing
[j0]                 }, 1)
[j0]                 else fail(5073201, "input to $filter must be an array")
[j0] ) }, Nothing) 

This expression comes from a projection generated by test: https://github.com/10gen/mongo/blob/master/jstests/aggregation/expressions/filter.js#L105

 

There could be other code paths that generate such expression.

 

 



 Comments   
Comment by Githook User [ 06/Feb/23 ]

Author:

{'name': 'Drew Paroski', 'email': 'drew.paroski@mongodb.com', 'username': 'paroski'}

Message: SERVER-72843 Fallback to the classic engine for FilterExpression
Branch: master
https://github.com/mongodb/mongo/commit/6087fdd3215cb1145f5b0843988e179ad28a10b2

Generated at Thu Feb 08 06:22:57 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.