[SERVER-16801] update considers a change in numerical type to be a noop Created: 11/Jan/15  Updated: 13/Feb/20  Resolved: 17/May/16

Status: Closed
Project: Core Server
Component/s: Write Ops
Affects Version/s: 2.6.6, 2.8.0-rc4, 3.2.0
Fix Version/s: 3.2.10, 3.3.6

Type: Bug Priority: Blocker - P1
Reporter: Asya Kamsky Assignee: David Storch
Resolution: Done Votes: 5
Labels: code-and-test, fuzzer-blocker
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Duplicate
is duplicated by SERVER-20390 Updating just the type for a numeric ... Closed
is duplicated by SERVER-21800 updates that implicitly change type m... Closed
is duplicated by SERVER-22025 Attempt to update Double to NumberInt... Closed
is duplicated by SERVER-22490 Casted type-change updates are discarded Closed
Related
is related to SERVER-16783 Indexes not updated when types change... Closed
Backwards Compatibility: Minor Change
Operating System: ALL
Backport Completed:
Steps To Reproduce:

db.foo.insert({f1:0})
db.foo.update({},{$set:{f1:NumberInt(0)}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

Sprint: QuInt E (01/11/16), Query F (02/01/16), Query 10 (02/22/16), Query 11 (03/14/16)
Participants:
Linked BF Score: 0

 Description   

When trying to set value of one numerical type to the same number of different numerical type, the update treats it as a noop and doesn't update the field.



 Comments   
Comment by Githook User [ 02/Sep/16 ]

Author:

{u'username': u'acmorrow', u'name': u'Andrew Morrow', u'email': u'acm@mongodb.com'}

Message: SERVER-16801 Require strict equality for $set no-op checks

(cherry picked from commit a7e243500cbf11d1e153f55b551c86713ddf2a9b)
Branch: v3.2
https://github.com/mongodb/mongo/commit/0c7d0e7ad583100e721c9f1e9436a6de07ee533c

Comment by Githook User [ 05/May/16 ]

Author:

{u'username': u'acmorrow', u'name': u'Andrew Morrow', u'email': u'acm@mongodb.com'}

Message: SERVER-16801 Require strict equality for $set no-op checks
Branch: master
https://github.com/mongodb/mongo/commit/a7e243500cbf11d1e153f55b551c86713ddf2a9b

Comment by Charlie Swanson [ 08/Jan/16 ]

I like Andy's argument that $set is unconditional.

Today, that update will have no affect. By your argument, I think it should replace the array to have two doubles.

Comment by Andy Schwerin [ 08/Jan/16 ]

What happens today if you you have this document:

{ _id: 0, a: [ NumberLong(2), 3.0 ] }

And you issue an update with the operation

{ $set: { a: [ 2.0, 3.0 ] } }

? What should happen?

Comment by Andy Schwerin [ 08/Jan/16 ]

I'm also uncomfortable changing anything other than $set. I think the argument for changing $set is that it is an unconditional write operation. It says "under all circumstances, assign this value to this field". The array operations mentioned above are conditional, and the condition they depend on is equality comparison. Our defined equality comparison operation allows numeric values of distinct types to compare equally in some circumstances.

Comment by Asya Kamsky [ 07/Jan/16 ]

I'd be very uncomfortable changing existing update behavior for array operators as you described.

Note the main reason for the original ticket being filed is there are operators that will not work on floats (but work on ints) - in particular our $bit operators. When attempting to set new value (type) was when I encountered this. So some of our operators do treat different numeric types differently already.

Comment by Max Hirschhorn [ 07/Jan/16 ]

If we were the change the behavior of $addToSet and $pull, then that would give find and update two different definitions of set membership; it would be possible to find a document because the array contains an equivalent number of a different bson type, but update only if the bson types were identical.

For example, we would be able to find the document {a: [1.0]} with the query {a: NumberLong(1)}, but fail to update it with {$pull: {a: NumberLong(1)}}

Comment by Charlie Swanson [ 07/Jan/16 ]

This stems from the fact that Doubles are treated as equal to a NumberInt or NumberLong representing the same number. If we change this here, should we also change the following behaviors?

  1. Using $addToSet to add NumberLong(2) to [2.0] is a no-op today.
  2. Using $pull to remove NumberLong(2) from [2.0] is not a no-op today, it will remove the 2.0.

If we change $set to treat 2.0 and NumberLong(2) as distinct, perhaps we should change the above to

  1. insert a new element (NumberLong(2))
  2. no-op

Is that preferable?

Comment by Asya Kamsky [ 07/Dec/15 ]

Still present in 3.2.0

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