[SERVER-17169] 64 bit signed int issues in the mongo shell Created: 04/Feb/15  Updated: 09/Feb/15  Resolved: 09/Feb/15

Status: Closed
Project: Core Server
Component/s: Shell
Affects Version/s: 2.6.6
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Jason Welch Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Steps To Reproduce:

db.test.save({value: 9223372036854775807})
db.test.find()
db.test.update({_id: "whatever was returned in find"}, {$inc: {value: 1}})

Participants:

 Description   

So I was curious to see how auto increment would react to a field in mongo with the max 64 bit signed int value (9223372036854775807) and was surprised to find it was capping the value to 9223372036854776000. With a bit of research, I found this is the same behavior in Javascript. The two things that are concerning though were A. $inc past the 9223372036854776000 value does absolutely nothing. No error. Nada. The value remains untouched. Decrementing the value also does nothing. However B. the most alarming thing was that a query with $gt :

{ 9223372036854775999 }

returns nothing. Dropping this value down to 9223372036854775800, still nothing. I didn't test to see exactly where it begins to work again, but I found 9223372036854775100 did work and returned the original document.



 Comments   
Comment by Ramon Fernandez Marina [ 09/Feb/15 ]

jwelch, this is expected behavior caused by the 64bit double-precision floating-point numbers representation used in JavaScript, and you can observer the same behavior in V8:

> x = 9223372036854775807
9223372036854776000
> y = 9223372036854775203
9223372036854775000

By the time these numbers reach the server they've already been rounded by V8.

If you need to handle 64bit integers in the mongo shell please see the NumberLong() wrapper. Here's an example:

> db.test.drop()
>
> // Insert 2^63 - 2
> db.test.save({value: NumberLong("9223372036854775806")})
WriteResult({ "nInserted" : 1 })
> db.test.find()
{ "_id" : ObjectId("54d8d94906c26ec9753989d8"), "value" : NumberLong("9223372036854775806") }
>
> // Increment value
> db.test.update({}, {$inc : {value:NumberLong("1")}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>
> // Search using $gt
> db.test.find({value: {$gt: NumberLong("9223372036854775806")}})
{ "_id" : ObjectId("54d8d94906c26ec9753989d8"), "value" : NumberLong("9223372036854775807") }
>
> // 2^63 - + 1 should trigger an error:
> db.test.update({}, {$inc : {value:NumberLong("1")}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 16837,
                "errmsg" : "Failed to apply $inc operations to current value ((NumberLong)9223372036854775807) for document {_id: ObjectId('54d8d94906c26ec9753989d8')}"
        }
})

Generated at Thu Feb 08 03:43:31 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.