summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2010-05-05 22:52:51 -0400
committerEliot Horowitz <eliot@10gen.com>2010-05-05 22:53:59 -0400
commitc1007834f6c7d724e824a91c60ab1e2aef2e07c9 (patch)
treec764fbe407edd0ed78c6e95771e3763c43a071ba
parent19672f06efbb3edf279e175b2fdca2469a7fbeb1 (diff)
downloadmongo-c1007834f6c7d724e824a91c60ab1e2aef2e07c9.tar.gz
fix updates on indexes fields when using array offsets SERVER-1093
-rw-r--r--db/update.h48
-rw-r--r--jstests/index_arr2.js51
2 files changed, 97 insertions, 2 deletions
diff --git a/db/update.h b/db/update.h
index 5d20114fe97..3c4daabaeae 100644
--- a/db/update.h
+++ b/db/update.h
@@ -100,12 +100,13 @@ namespace mongo {
}
}
- bool isIndexed( const set<string>& idxKeys ) const {
+ static bool isIndexed( const string& fullName , const set<string>& idxKeys ){
+ const char * fieldName = fullName.c_str();
// check if there is an index key that is a parent of mod
for( const char *dot = strchr( fieldName, '.' ); dot; dot = strchr( dot + 1, '.' ) )
if ( idxKeys.count( string( fieldName, dot - fieldName ) ) )
return true;
- string fullName = fieldName;
+
// check if there is an index key equal to mod
if ( idxKeys.count(fullName) )
return true;
@@ -113,6 +114,49 @@ namespace mongo {
set< string >::const_iterator j = idxKeys.upper_bound( fullName );
if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[fullName.size()] == '.' )
return true;
+
+ return false;
+ }
+
+ bool isIndexed( const set<string>& idxKeys ) const {
+ string fullName = fieldName;
+
+ if ( isIndexed( fullName , idxKeys ) )
+ return true;
+
+ if ( strstr( fieldName , "." ) ){
+ // check for a.0.1
+ StringBuilder buf( fullName.size() + 1 );
+ for ( size_t i=0; i<fullName.size(); i++ ){
+ char c = fullName[i];
+ buf << c;
+
+ if ( c != '.' )
+ continue;
+
+ if ( ! isdigit( fullName[i+1] ) )
+ continue;
+
+ bool possible = true;
+ size_t j=i+2;
+ for ( ; j<fullName.size(); j++ ){
+ char d = fullName[j];
+ if ( d == '.' )
+ break;
+ if ( isdigit( d ) )
+ continue;
+ possible = false;
+ break;
+ }
+
+ if ( possible )
+ i = j;
+ }
+ string x = buf.str();
+ if ( isIndexed( x , idxKeys ) )
+ return true;
+ }
+
return false;
}
diff --git a/jstests/index_arr2.js b/jstests/index_arr2.js
new file mode 100644
index 00000000000..21a511b8485
--- /dev/null
+++ b/jstests/index_arr2.js
@@ -0,0 +1,51 @@
+NUM = 20;
+M = 5;
+
+t = db.xxx;
+
+function test( withIndex ){
+ t.drop();
+
+ // insert a bunch of items to force queries to use the index.
+ newObject = {
+ _id : 1,
+ a : [
+ { b : { c : 1 } }
+ ]
+ }
+
+ now = (new Date()).getTime() / 1000;
+ for (created = now - NUM; created <= now; created++ ) {
+ newObject['created'] = created;
+ t.insert(newObject);
+ newObject['_id'] ++;
+ }
+
+ // change the last M items.
+ query = {
+ 'created' : { '$gte' : now - M }
+ }
+
+ Z = t.find( query ).count();
+
+ if ( withIndex ){
+ //t.ensureIndex( { 'a.b.c' : 1, 'created' : -1 } )
+ //t.ensureIndex( { created : -1 } )
+ t.ensureIndex( { 'a.b.c' : 1 } , { name : "x" } )
+ }
+
+ t.update(query, { '$set' : { "a.0.b.c" : 0 } } , false , true )
+ assert.eq( Z , db.getLastErrorObj().n , "num updated withIndex:" + withIndex );
+
+ // now see how many were actually updated.
+ query['a.b.c'] = 0;
+
+ count = t.count(query);
+
+ assert.eq( Z , count , "count after withIndex:" + withIndex );
+}
+
+test( false )
+test( true );
+
+