Permalink
Browse files

SERVER-6588 - fix positional updates in new find_and_modify code

  • Loading branch information...
1 parent 82f2b1e commit ba7f067a2d5de8832702b4617c3dbf6973e77c5b @erh erh committed Aug 1, 2012
Showing with 55 additions and 2 deletions.
  1. +22 −0 jstests/find_and_modify_server6588.js
  2. +33 −2 src/mongo/db/commands/find_and_modify.cpp
@@ -0,0 +1,22 @@
+
+t = db.find_and_modify_sever6588;
+
+initial = { _id : 1 , a : [ { b : 1 } ] , z : 1 }
+up = { "$set" : { "a.$.b" : 2 } }
+q = { _id : 1 , "a.b" : 1 }
+correct = { _id : 1 , a : [ { b : 2 } ] , z : 1 }
+
+t.drop();
+t.insert( initial )
+t.update( q , up )
+assert.eq( correct , t.findOne() )
+
+t.drop()
+t.insert( initial )
+x = t.findAndModify( { query : q , update : up } )
+assert.eq( correct , t.findOne() )
+
+t.drop()
+t.insert( initial )
+x = t.findAndModify( { query : { z : 1 , "a.b" : 1 } , update : up } )
+assert.eq( correct , t.findOne() )
@@ -23,6 +23,7 @@
#include "../dbhelpers.h"
#include "../ops/delete.h"
#include "../ops/update.h"
+#include "../queryutil.h"
namespace mongo {
@@ -118,8 +119,38 @@ namespace mongo {
bool found = Helpers::findOne( ns.c_str() , queryOriginal , doc );
BSONObj queryModified = queryOriginal;
- if ( found && doc["_id"].type() )
- queryModified = doc["_id"].wrap();
+ if ( found && doc["_id"].type() && ! isSimpleIdQuery( queryOriginal ) ) {
+ // we're going to re-write the query to be more efficient
+ // we have to be a little careful because of positional operators
+ // maybe we can pass this all through eventually, but right now isn't an easy way
+ BSONObjBuilder b( queryOriginal.objsize() + 10 );
+ b.append( doc["_id"] );
+
+ bool addedAtomic = false;
+
+ BSONObjIterator i( queryOriginal );
+ while ( i.more() ) {
+ const BSONElement& elem = i.next();
+
+ if ( str::equals( "_id" , elem.fieldName() ) ) {
+ // we already do _id
+ continue;
+ }
+
+ if ( ! str::contains( elem.fieldName() , '.' ) ) {
+ // if there is a dotted field, accept we may need more query parts
+ continue;
+ }
+
+ if ( ! addedAtomic ) {
+ b.appendBool( "$atomic" , true );
+ addedAtomic = true;
+ }
+
+ b.append( elem );
+ }
+ queryModified = b.obj();
+ }
if ( remove ) {
_appendHelper( result , doc , found , fields );

0 comments on commit ba7f067

Please sign in to comment.