Skip to content

Commit

Permalink
SERVER-958 tests
Browse files Browse the repository at this point in the history
  • Loading branch information
astaple committed Apr 25, 2011
1 parent f799371 commit 870fedc
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
58 changes: 58 additions & 0 deletions jstests/indexk.js
Original file line number Diff line number Diff line change
@@ -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
41 changes: 41 additions & 0 deletions jstests/indexn.js
Original file line number Diff line number Diff line change
@@ -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 );
32 changes: 32 additions & 0 deletions jstests/indexo.js
Original file line number Diff line number Diff line change
@@ -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 ] );
48 changes: 48 additions & 0 deletions jstests/ori.js
Original file line number Diff line number Diff line change
@@ -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.