Permalink
Browse files

SERVER-958 tests

  • Loading branch information...
1 parent f799371 commit 870fedc9e1dea57532d109782b2a31378b32f16c @astaple astaple committed Apr 25, 2011
Showing with 179 additions and 0 deletions.
  1. +58 −0 jstests/indexk.js
  2. +41 −0 jstests/indexn.js
  3. +32 −0 jstests/indexo.js
  4. +48 −0 jstests/ori.js
View
@@ -0,0 +1,58 @@
+// Check correct result set when bounds each match different multikeys SERVER-958
+
+t = db.jstests_indexk;
+t.drop();
+
+t.insert({a:[1,10]});
+
+assert.eq( 1, t.count({a: {$gt:2, $lt:5}}) );
+assert.eq( 1, t.count({a: {$gt:2}}) );
+assert.eq( 1, t.count({a: {$lt:5}}) );
+
+assert.eq( 1, t.count({a: {$gt:5, $lt:2}}) );
+assert.eq( 1, t.count({a: {$gt:5}}) );
+assert.eq( 1, t.count({a: {$lt:2}}) );
+
+t.ensureIndex({a:1});
+
+// Check that only one constraint limits the index range for a multikey index.
+// The constraint used is arbitrary, but testing current behavior here.
+
+assert.eq( 1, t.count({a: {$gt: 2, $lt:5}}) );
+e = t.find({a: {$gt: 2, $lt:5}}).explain();
+assert.eq( 1, e.nscanned );
+assert.eq( 1, e.n );
+assert.eq( 2, e.indexBounds.a[ 0 ][ 0 ] );
+// Check that upper bound is large ( > 5 ).
+assert.lt( 1000, e.indexBounds.a[ 0 ][ 1 ] );
+
+assert.eq( 1, t.count({a: {$lt: 5, $gt:2}}) );
+e = t.find({a: {$lt: 5, $gt:2}}).explain();
+assert.eq( 1, e.nscanned );
+assert.eq( 1, e.n );
+// Check that upper bound is low ( < 2 ).
+assert.gt( -1000, e.indexBounds.a[ 0 ][ 0 ] );
+assert.eq( 5, e.indexBounds.a[ 0 ][ 1 ] );
+
+// Now check cases where no match is possible with a single key index.
+
+assert.eq( 1, t.count({a: {$gt: 5, $lt:2}}) );
+e = t.find({a: {$gt: 5, $lt:2}}).explain();
+assert.eq( 1, e.nscanned );
+assert.eq( 1, e.n );
+assert.eq( 5, e.indexBounds.a[ 0 ][ 0 ] );
+// Check that upper bound is low ( < 2 ).
+assert.lt( 1000, e.indexBounds.a[ 0 ][ 1 ] );
+
+assert.eq( 1, t.count({a: {$lt: 2, $gt:5}}) );
+e = t.find({a: {$lt: 2, $gt:5}}).explain();
+assert.eq( 1, e.nscanned );
+assert.eq( 1, e.n );
+// Check that upper bound is large ( > 5 ).
+assert.gt( -1000, e.indexBounds.a[ 0 ][ 0 ] );
+assert.eq( 2, e.indexBounds.a[ 0 ][ 1 ] );
+
+assert.eq( 1, t.count({a: {$gt: 2}}) );
+assert.eq( 1, t.count({a: {$lt: 5}}) );
+
+// Check good performance of single key index
View
@@ -0,0 +1,41 @@
+// Check fast detection of empty result set with a single key index SERVER-958.
+
+t = db.jstests_indexn;
+t.drop();
+
+function checkImpossibleMatchDummyCursor( explain ) {
+ assert.eq( 'BasicCursor', explain.cursor );
+ assert.eq( 0, explain.nscanned );
+ assert.eq( 0, explain.n );
+}
+
+t.save( {a:1,b:[1,2]} );
+
+t.ensureIndex( {a:1} );
+t.ensureIndex( {b:1} );
+
+assert.eq( 0, t.count( {a:{$gt:5,$lt:0}} ) );
+// {a:1} is a single key index, so no matches are possible for this query
+checkImpossibleMatchDummyCursor( t.find( {a:{$gt:5,$lt:0}} ).explain() );
+
+assert.eq( 0, t.count( {a:{$gt:5,$lt:0},b:2} ) );
+checkImpossibleMatchDummyCursor( t.find( {a:{$gt:5,$lt:0},b:2} ).explain() );
+
+assert.eq( 0, t.count( {a:{$gt:5,$lt:0},b:{$gt:0,$lt:5}} ) );
+checkImpossibleMatchDummyCursor( t.find( {a:{$gt:5,$lt:0},b:{$gt:0,$lt:5}} ).explain() );
+
+assert.eq( 1, t.count( {$or:[{a:{$gt:5,$lt:0}},{a:1}]} ) );
+checkImpossibleMatchDummyCursor( t.find( {$or:[{a:{$gt:5,$lt:0}},{a:1}]} ).explain().clauses[ 0 ] );
+
+// A following invalid range is eliminated.
+assert.eq( 1, t.count( {$or:[{a:1},{a:{$gt:5,$lt:0}}]} ) );
+assert.eq( null, t.find( {$or:[{a:1},{a:{$gt:5,$lt:0}}]} ).explain().clauses );
+
+t.save( {a:2} );
+
+// An intermediate invalid range is eliminated.
+assert.eq( 2, t.count( {$or:[{a:1},{a:{$gt:5,$lt:0}},{a:2}]} ) );
+explain = t.find( {$or:[{a:1},{a:{$gt:5,$lt:0}},{a:2}]} ).explain();
+assert.eq( 2, explain.clauses.length );
+assert.eq( [[1,1]], explain.clauses[ 0 ].indexBounds.a );
+assert.eq( [[2,2]], explain.clauses[ 1 ].indexBounds.a );
View
@@ -0,0 +1,32 @@
+// Check that dummy basic cursors work correctly SERVER-958.
+
+t = db.jstests_indexo;
+t.drop();
+
+function checkDummyCursor( explain ) {
+ assert.eq( "BasicCursor", explain.cursor );
+ assert.eq( 0, explain.nscanned );
+ assert.eq( 0, explain.n );
+}
+
+t.save( {a:1} );
+
+t.ensureIndex( {a:1} );
+
+// Match is impossible, so no documents should be scanned.
+checkDummyCursor( t.find( {a:{$gt:5,$lt:0}} ).explain() );
+
+t.drop();
+checkDummyCursor( t.find( {a:1} ).explain() );
+
+t.save( {a:1} );
+t.ensureIndex( {a:1} );
+checkDummyCursor( t.find( {$or:[{a:{$gt:5,$lt:0}},{a:1}]} ).explain().clauses[ 0 ] );
+
+t.drop();
+t.save( {a:5,b:[1,2]} );
+t.ensureIndex( {a:1,b:1} );
+t.ensureIndex( {a:1} );
+// The first clause will use index {a:1,b:1} with the current implementation.
+// The second clause has no valid values for index {a:1} so it will use a dummy cursor.
+checkDummyCursor( t.find( {$or:[{b:{$exists:true},a:{$gt:4}},{a:{$lt:6,$gt:4}}]} ).explain().clauses[ 1 ] );
View
@@ -0,0 +1,48 @@
+// Check elimination of proper range type when popping a $or clause SERVER-958.
+
+t = db.jstests_ori;
+t.drop();
+
+t.ensureIndex( {a:1,b:1} );
+t.ensureIndex( {a:1,c:1} );
+
+t.save( {a:1,b:[2,3],c:4} );
+t.save( {a:10,b:2,c:4} );
+
+// Check that proper results are returned.
+
+assert.eq( 2, t.count( {$or:[{a:{$gt:0,$lt:5},b:2},{a:10,c:4}]} ) );
+// Two $or clauses expected to be scanned.
+assert.eq( 2, t.find( {$or:[{a:{$gt:0,$lt:5},b:2},{a:10,c:4}]} ).explain().clauses.length );
+assert.eq( 2, t.count( {$or:[{a:10,b:2},{a:{$gt:0,$lt:5},c:4}]} ) );
+
+t.drop();
+
+// Now try a different index order.
+
+t.ensureIndex( {b:1,a:1} );
+t.ensureIndex( {a:1,c:1} );
+
+t.save( {a:1,b:[2,3],c:4} );
+t.save( {a:10,b:2,c:4} );
+
+assert.eq( 2, t.count( {$or:[{a:{$gt:0,$lt:5},b:2},{a:10,c:4}]} ) );
+assert.eq( 2, t.count( {$or:[{a:10,b:2},{a:{$gt:0,$lt:5},c:4}]} ) );
+
+t.drop();
+
+// Now eliminate a range.
+
+t.ensureIndex( {a:1} );
+t.ensureIndex( {b:1} );
+
+t.save( {a:[1,2],b:1} );
+t.save( {a:10,b:1} );
+
+assert.eq( 2, t.count( {$or:[{a:{$gt:0,$lt:5}},{a:10,b:1}]} ) );
+// Because a:1 is multikey, the value a:10 is scanned with the first clause.
+assert.isnull( t.find( {$or:[{a:{$gt:0,$lt:5}},{a:10,b:1}]} ).explain().clauses );
+
+assert.eq( 2, t.count( {$or:[{a:{$lt:5,$gt:0}},{a:10,b:1}]} ) );
+// Now a:10 is not scanned in the first clause so the second clause is not eliminated.
+assert.eq( 2, t.find( {$or:[{a:{$lt:5,$gt:0}},{a:10,b:1}]} ).explain().clauses.length );

0 comments on commit 870fedc

Please sign in to comment.