[SERVER-56128] [SBE] $add of single NumberDecimal returns 0 with SBE on, should be a no-op Created: 15/Apr/21  Updated: 29/Oct/23  Resolved: 20/Apr/21

Status: Closed
Project: Core Server
Component/s: Query Execution
Affects Version/s: None
Fix Version/s: 5.0.0-rc0

Type: Bug Priority: Major - P3
Reporter: David Storch Assignee: Eric Cox (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
is depended on by SERVER-56119 Enable generational agg and query fuz... Closed
Backwards Compatibility: Fully Compatible
Operating System: ALL
Sprint: Query Execution 2021-04-19, Query Execution 2021-05-03
Participants:

 Description   

Demonstration of the problem against a mongod with SBE enabled:

MongoDB Enterprise > db.c.drop()
true
MongoDB Enterprise > db.c.insert({a: NumberDecimal("-380.85092727960944")})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise > db.c.aggregate([{$project: {out: {$add: "$a"}}}])
{ "_id" : ObjectId("60789c93529583162225a821"), "out" : NumberDecimal("0") }

Here, the $add expression ends up evaluating to 0. This does not seem like the correct behavior. Indeed, with SBE off an $add with a single argument ends up being a no-op:

MongoDB Enterprise > db.c.aggregate([{$project: {out: {$add: "$a"}}}])
{ "_id" : ObjectId("60789c93529583162225a821"), "out" : NumberDecimal("-380.85092727960944") }

This problem was detected by the aggregation_expression_multiversion_fuzzer. See this example failing task.

Here is the SBE plan, with same additional whitespace added for legibility:

[2] traverse s8 s7 s2 {} {}
from
    [1] scan s2 s3 [] @\"d0d922c5-fea8-408a-8c53-32726c6995a9\" true
in
    [2] mkbson s7 s2 [] keep [a = s6] true false
    [2] project [s6 = let [l1.0 = s5]
        if (! exists (l1.0) || typeMatch (l1.0, 0x00000440),
            null,
            if (! isNumber (l1.0) && ! isDate (l1.0),
                fail ( 4974203 ,only numbers and dates are allowed in an $add expression),
                doubleDoubleSum (l1.0)))]
    [2] traverse s5 s5 s4 {} {}
    from
        [2] project [s4 = getField (s2, \"num\")]
        [2] limit 1
        [2] coscan
    in
        [2] project [s5 = s4]
        [2] limit 1
        [2] coscan

At a glance, it appears that perhaps the "doubleDoubleSum" builtin function is doing the wrong thing?



 Comments   
Comment by Githook User [ 20/Apr/21 ]

Author:

{'name': 'Eric Cox', 'email': 'eric.cox@mongodb.com', 'username': 'ericox'}

Message: SERVER-56128 Fix usage of Decimal128::add in SBE vm doubleDoubleSum builtin
Branch: master
https://github.com/mongodb/mongo/commit/18c5731a624f06cc1b961205760beb593163f55c

Comment by Eric Cox (Inactive) [ 16/Apr/21 ]

This one was caused by line 1219 in the doubleDoubleSum builtin. Decmial128::add is a const method so we passed the default value of Decmial128{} from the stack var into makeCopyDecimal(). The fix is to mutate the stack var sum with the return value of Decmial128::add().

Generated at Thu Feb 08 05:38:25 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.