[SERVER-19348] $mod results are inconsistent with indexing enabled on Infinity, -Infinity, NaN Created: 09/Jul/15  Updated: 19/Sep/15  Resolved: 28/Jul/15

Status: Closed
Project: Core Server
Component/s: Index Maintenance, Querying
Affects Version/s: 2.2.7, 2.4.14, 2.6.10, 3.1.5
Fix Version/s: 3.1.7

Type: Bug Priority: Major - P3
Reporter: David Hatch Assignee: David Hatch
Resolution: Done Votes: 0
Labels: dnsf
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-19349 $type results are inconsistent with i... Closed
Backwards Compatibility: Minor Change
Operating System: ALL
Steps To Reproduce:

In the shell:

> db.test.insert({ a : Infinity })
WriteResult({ "nInserted" : 1})
> db.test.insert({ a: -Infinity })
WriteResult({ "nInserted" : 1 })
> db.test.insert({ a: NaN })
WriteResult({ "nInserted" : 1 })
> db.test.find({ a : { $mod: [10, -8] }})
{ "_id" : ObjectId("559edbdb37a9ccb7245bb7f9"), "a" : Infinity }
{ "_id" : ObjectId("559edbdc37a9ccb7245bb7fa"), "a" : -Infinity }
{ "_id" : ObjectId("559edbdf37a9ccb7245bb7fb"), "a" : NaN }
> db.test.ensureIndex({ a: 1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.test.find({ a : { $mod: [10, -8] }})
> db.test.dropIndex({ a : 1 })
{ "nIndexesWas" : 2, "ok" : 1 }
> db.test.find({ a : { $mod: [10, -8] }})
{ "_id" : ObjectId("559edbdb37a9ccb7245bb7f9"), "a" : Infinity }
{ "_id" : ObjectId("559edbdc37a9ccb7245bb7fa"), "a" : -Infinity }
{ "_id" : ObjectId("559edbdf37a9ccb7245bb7fb"), "a" : NaN }
 

Participants:

 Description   

The $mod operator in find queries currently casts values to long long when matching, using the unsafe BSONElement.numberLong(...). This means NaN, -Infinity, and Infinity are all converted to the minimum long long, although the behavior is undefined. Behavior for doubles out of range of long long is also undefined, although I haven't checked precisely what does occur.

If $mod is going to convert to long long, it might be appropriate to not match any values outside the range of long long, as all of them will have undefined value.

This would solve the indexing problem, and we could scan the interval of NumberLong s instead of NumberDouble.

This issue was introduced because BSONElement.appendMinForType and BSONElement.appendMaxForType appends the maximum and minimum double value, not Infinity. Elsewhere in src/mongo/db/query/index_bounds_builder.cpp, appendMin/MaxForType is not used, in favor of explicitly using Infinity. In practice the only time this function is called is for the $mod and $type match expressions.



 Comments   
Comment by Githook User [ 28/Jul/15 ]

Author:

{u'username': u'dhatch', u'name': u'David Hatch', u'email': u'david.hatch@mongodb.com'}

Message: SERVER-19348, SERVER-19349: Correct index bounds on $type and $mod.
Branch: master
https://github.com/mongodb/mongo/commit/4273fdf07c5af4bd0fd156f5a8a1d8efa56519fb

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