diff options
author | Ian Boros <puppyofkosh@gmail.com> | 2019-04-04 19:20:35 -0400 |
---|---|---|
committer | Ian Boros <puppyofkosh@gmail.com> | 2019-04-11 18:34:10 -0400 |
commit | 502df279c7476c01758ab210728f4acc4a27a218 (patch) | |
tree | f350da86174a673c792ca99e16ae43a0319e71c8 /jstests/core/minmax_edge.js | |
parent | d131d7861c73efe052c5909ae8f1452c100a461d (diff) | |
download | mongo-502df279c7476c01758ab210728f4acc4a27a218.tar.gz |
SERVER-39567 Change find min/max options to require hint
Diffstat (limited to 'jstests/core/minmax_edge.js')
-rw-r--r-- | jstests/core/minmax_edge.js | 371 |
1 files changed, 189 insertions, 182 deletions
diff --git a/jstests/core/minmax_edge.js b/jstests/core/minmax_edge.js index 759d87dc21e..cf75edaef80 100644 --- a/jstests/core/minmax_edge.js +++ b/jstests/core/minmax_edge.js @@ -2,224 +2,231 @@ * Test that .min() and .max() queries properly handle the edge cases with NaN and Infinity. * Other edge cases are covered by C++ unit tests. */ +(function() { + const t = db.minmax_edge; + + /* + * Function to verify that the results of a query match the expected results. + * Results is the cursor toArray, expectedIds is a list of _ids + */ + function verifyResultIds(results, expectedIds) { + // check they are the same length + assert.eq(results.length, expectedIds.length); + + function compare(a, b) { + if (a._id < b._id) + return -1; + if (a._id > b._id) + return 1; + return 0; + } + + results.sort(compare); + expectedIds.sort(); + + for (var i = 0; i < results.length; i++) { + assert.eq(results._id, expectedIds._ids); + } + } -var t = db.minmax_edge; - -/* - * Function to verify that the results of a query match the expected results. - * Results is the cursor toArray, expectedIds is a list of _ids - */ -function verifyResultIds(results, expectedIds) { - // check they are the same length - assert.eq(results.length, expectedIds.length); - - function compare(a, b) { - if (a._id < b._id) - return -1; - if (a._id > b._id) - return 1; - return 0; + /* + * Shortcut to drop the collection and insert these 3 test docs. Used to change the indices + * regardless of any previous indices. + */ + function reset(t) { + t.drop(); + assert.writeOK(t.insert({_id: 0, a: 1, b: 1})); + assert.writeOK(t.insert({_id: 1, a: 1, b: 2})); + assert.writeOK(t.insert({_id: 2, a: 1, b: 3})); + + assert.writeOK(t.insert({_id: 3, a: 2, b: 1})); + assert.writeOK(t.insert({_id: 4, a: 2, b: 2})); + assert.writeOK(t.insert({_id: 5, a: 2, b: 3})); + + assert.writeOK(t.insert({_id: 6, a: 3, b: 1})); + assert.writeOK(t.insert({_id: 7, a: 3, b: 2})); + assert.writeOK(t.insert({_id: 8, a: 3, b: 3})); } - results.sort(compare); - expectedIds.sort(); + // Two helpers to save typing + function verifyMin(minDoc, idx, expectedIds) { + verifyResultIds(t.find().min(minDoc).hint(idx).toArray(), expectedIds); + } - for (var i = 0; i < results.length; i++) { - assert.eq(results._id, expectedIds._ids); + function verifyMax(minDoc, idx, expectedIds) { + verifyResultIds(t.find().max(minDoc).hint(idx).toArray(), expectedIds); } -} -/* - * Shortcut to drop the collection and insert these 3 test docs. Used to change the indices - * regardless of any previous indices. - */ -function reset(t) { - t.drop(); - assert.writeOK(t.insert({_id: 0, a: 1, b: 1})); - assert.writeOK(t.insert({_id: 1, a: 1, b: 2})); - assert.writeOK(t.insert({_id: 2, a: 1, b: 3})); + // Basic ascending index. + reset(t); + let indexSpec = {a: 1}; + assert.commandWorked(t.createIndex(indexSpec)); + + verifyMin({a: Infinity}, indexSpec, []); + verifyMax({a: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - assert.writeOK(t.insert({_id: 3, a: 2, b: 1})); - assert.writeOK(t.insert({_id: 4, a: 2, b: 2})); - assert.writeOK(t.insert({_id: 5, a: 2, b: 3})); + verifyMin({a: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: -Infinity}, indexSpec, []); - assert.writeOK(t.insert({_id: 6, a: 3, b: 1})); - assert.writeOK(t.insert({_id: 7, a: 3, b: 2})); - assert.writeOK(t.insert({_id: 8, a: 3, b: 3})); -} + // NaN < all ints. + verifyMin({a: NaN}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: NaN}, indexSpec, []); -// Two helpers to save typing -function verifyMin(minDoc, expectedIds) { - verifyResultIds(t.find().min(minDoc).toArray(), expectedIds); -} + // {a: 1} > all ints. + verifyMin({a: {a: 1}}, indexSpec, []); + verifyMax({a: {a: 1}}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -function verifyMax(minDoc, expectedIds) { - verifyResultIds(t.find().max(minDoc).toArray(), expectedIds); -} + // 'a' > all ints. + verifyMin({a: 'a'}, indexSpec, []); + verifyMax({a: 'a'}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Basic ascending index. -reset(t); -assert.commandWorked(t.ensureIndex({a: 1})); + // Now with a compound index. + reset(t); + indexSpec = {a: 1, b: -1}; -verifyMin({a: Infinity}, []); -verifyMax({a: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + assert.commandWorked(t.createIndex(indexSpec)); -verifyMin({a: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: -Infinity}, []); + // Same as single-key index assertions, with b field present. + verifyMin({a: NaN, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: NaN, b: 1}, indexSpec, []); -// NaN < all ints. -verifyMin({a: NaN}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: NaN}, []); + verifyMin({a: Infinity, b: 1}, indexSpec, []); + verifyMax({a: Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// {a: 1} > all ints. -verifyMin({a: {a: 1}}, []); -verifyMax({a: {a: 1}}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: -Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: -Infinity, b: 1}, indexSpec, []); -// 'a' > all ints. -verifyMin({a: 'a'}, []); -verifyMax({a: 'a'}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: {a: 1}, b: 1}, indexSpec, []); + verifyMax({a: {a: 1}, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Now with a compound index. -reset(t); -assert.commandWorked(t.ensureIndex({a: 1, b: -1})); + verifyMin({a: 'a', b: 1}, indexSpec, []); + verifyMax({a: 'a', b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Same as single-key index assertions, with b field present. -verifyMin({a: NaN, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: NaN, b: 1}, []); + // Edge cases on b values + verifyMin({a: 1, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMin({a: 3, b: Infinity}, indexSpec, [6, 7, 8]); + verifyMax({a: 1, b: Infinity}, indexSpec, []); + verifyMax({a: 2, b: Infinity}, indexSpec, [0, 1, 2]); + verifyMax({a: 3, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); -verifyMin({a: Infinity, b: 1}, []); -verifyMax({a: Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 1, b: -Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: -Infinity}, indexSpec, [6, 7, 8]); + verifyMin({a: 3, b: -Infinity}, indexSpec, []); + verifyMax({a: 1, b: -Infinity}, indexSpec, [0, 1, 2]); + verifyMax({a: 2, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMax({a: 3, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: -Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: -Infinity, b: 1}, []); + verifyMin({a: 2, b: NaN}, indexSpec, [6, 7, 8]); + verifyMax({a: 2, b: NaN}, indexSpec, [0, 1, 2, 3, 4, 5]); -verifyMin({a: {a: 1}, b: 1}, []); -verifyMax({a: {a: 1}, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: 'a', b: 1}, []); -verifyMax({a: 'a', b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -// Edge cases on b values -verifyMin({a: 1, b: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 3, b: Infinity}, [6, 7, 8]); -verifyMax({a: 1, b: Infinity}, []); -verifyMax({a: 2, b: Infinity}, [0, 1, 2]); -verifyMax({a: 3, b: Infinity}, [0, 1, 2, 3, 4, 5]); - -verifyMin({a: 1, b: -Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: -Infinity}, [6, 7, 8]); -verifyMin({a: 3, b: -Infinity}, []); -verifyMax({a: 1, b: -Infinity}, [0, 1, 2]); -verifyMax({a: 2, b: -Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMax({a: 3, b: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: {b: 1}}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: {b: 1}}, indexSpec, [0, 1, 2]); -verifyMin({a: 2, b: NaN}, [6, 7, 8]); -verifyMax({a: 2, b: NaN}, [0, 1, 2, 3, 4, 5]); - -verifyMin({a: 2, b: {b: 1}}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: {b: 1}}, [0, 1, 2]); - -verifyMin({a: 2, b: 'b'}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: 'b'}, [0, 1, 2]); - -// Test descending index. -reset(t); -t.ensureIndex({a: -1}); - -verifyMin({a: NaN}, []); -verifyMax({a: NaN}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: Infinity}, []); - -verifyMin({a: -Infinity}, []); -verifyMax({a: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: {a: 1}}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: {a: 1}}, []); + verifyMin({a: 2, b: 'b'}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: 'b'}, indexSpec, [0, 1, 2]); -verifyMin({a: 'a'}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 'a'}, []); + // Test descending index. + reset(t); + indexSpec = {a: -1}; + assert.commandWorked(t.createIndex(indexSpec)); -// Now with a compound index. -reset(t); -t.ensureIndex({a: -1, b: -1}); + verifyMin({a: NaN}, indexSpec, []); + verifyMax({a: NaN}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Same as single-key index assertions, with b field present. -verifyMin({a: NaN, b: 1}, []); -verifyMax({a: NaN, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: Infinity}, indexSpec, []); -verifyMin({a: Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: Infinity, b: 1}, []); + verifyMin({a: -Infinity}, indexSpec, []); + verifyMax({a: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: -Infinity, b: 1}, []); -verifyMax({a: -Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: {a: 1}}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: {a: 1}}, indexSpec, []); -verifyMin({a: {a: 1}, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: {a: 1}, b: 1}, []); + verifyMin({a: 'a'}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 'a'}, indexSpec, []); -verifyMin({a: 'a', b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 'a', b: 1}, []); + // Now with a compound index. + reset(t); + indexSpec = {a: -1, b: -1}; + assert.commandWorked(t.createIndex(indexSpec)); -// Edge cases on b values. -verifyMin({a: 1, b: Infinity}, [0, 1, 2]); -verifyMin({a: 2, b: Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMin({a: 3, b: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 1, b: Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: Infinity}, [6, 7, 8]); -verifyMax({a: 3, b: Infinity}, []); + // Same as single-key index assertions, with b field present. + verifyMin({a: NaN, b: 1}, indexSpec, []); + verifyMax({a: NaN, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 1, b: -Infinity}, []); -verifyMin({a: 2, b: -Infinity}, [0, 1, 2]); -verifyMin({a: 3, b: -Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMax({a: 1, b: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: -Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 3, b: -Infinity}, [6, 7, 8]); + verifyMin({a: Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: Infinity, b: 1}, indexSpec, []); -verifyMin({a: 2, b: NaN}, [0, 1, 2]); -verifyMax({a: 2, b: NaN}, [3, 4, 5, 6, 7, 8]); - -verifyMin({a: 2, b: {b: 1}}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: {b: 1}}, [0, 1, 2]); + verifyMin({a: -Infinity, b: 1}, indexSpec, []); + verifyMax({a: -Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: 'b'}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: 'b'}, [0, 1, 2]); + verifyMin({a: {a: 1}, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: {a: 1}, b: 1}, indexSpec, []); -// Now a couple cases with an extra compound index. -t.drop(); -t.ensureIndex({a: 1, b: -1, c: 1}); -// The following documents are in order according to the index. -t.insert({_id: 0, a: 1, b: 'b', c: 1}); -t.insert({_id: 1, a: 1, b: 'b', c: 2}); -t.insert({_id: 2, a: 1, b: 'a', c: 1}); -t.insert({_id: 3, a: 1, b: 'a', c: 2}); -t.insert({_id: 4, a: 2, b: 'b', c: 1}); -t.insert({_id: 5, a: 2, b: 'b', c: 2}); -t.insert({_id: 6, a: 2, b: 'a', c: 1}); -t.insert({_id: 7, a: 2, b: 'a', c: 2}); - -verifyMin({a: 1, b: 'a', c: 1}, [2, 3, 4, 5, 6, 7]); -verifyMin({a: 2, b: 'a', c: 2}, [7]); -verifyMax({a: 1, b: 'a', c: 1}, [0, 1]); -verifyMax({a: 2, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6]); - -verifyMin({a: Infinity, b: 'a', c: 2}, []); -verifyMax({a: Infinity, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6, 7]); + verifyMin({a: 'a', b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 'a', b: 1}, indexSpec, []); -verifyMin({a: -Infinity, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6, 7]); -verifyMax({a: -Infinity, b: 'a', c: 2}, []); + // Edge cases on b values. + verifyMin({a: 1, b: Infinity}, indexSpec, [0, 1, 2]); + verifyMin({a: 2, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMin({a: 3, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 1, b: Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: Infinity}, indexSpec, [6, 7, 8]); + verifyMax({a: 3, b: Infinity}, indexSpec, []); -// 'a' > Infinity, actually. -verifyMin({a: 1, b: Infinity, c: 2}, [4, 5, 6, 7]); -verifyMax({a: 1, b: Infinity, c: 2}, [0, 1, 2, 3]); + verifyMin({a: 1, b: -Infinity}, indexSpec, []); + verifyMin({a: 2, b: -Infinity}, indexSpec, [0, 1, 2]); + verifyMin({a: 3, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMax({a: 1, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: -Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 3, b: -Infinity}, indexSpec, [6, 7, 8]); -// Also, 'a' > -Infinity. -verifyMin({a: 1, b: -Infinity, c: 2}, [4, 5, 6, 7]); -verifyMax({a: 1, b: -Infinity, c: 2}, [0, 1, 2, 3]); + verifyMin({a: 2, b: NaN}, indexSpec, [0, 1, 2]); + verifyMax({a: 2, b: NaN}, indexSpec, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 1, b: 'a', c: Infinity}, [4, 5, 6, 7]); -verifyMax({a: 1, b: 'a', c: Infinity}, [0, 1, 2, 3]); + verifyMin({a: 2, b: {b: 1}}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: {b: 1}}, indexSpec, [0, 1, 2]); -verifyMin({a: 1, b: 'a', c: -Infinity}, [2, 3, 4, 5, 6, 7]); -verifyMax({a: 1, b: 'a', c: -Infinity}, [0, 1]); + verifyMin({a: 2, b: 'b'}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: 'b'}, indexSpec, [0, 1, 2]); + + // Now a couple cases with an extra compound index. + t.drop(); + indexSpec = {a: 1, b: -1, c: 1}; + assert.commandWorked(t.createIndex(indexSpec)); + // The following documents are in order according to the index. + t.insert({_id: 0, a: 1, b: 'b', c: 1}); + t.insert({_id: 1, a: 1, b: 'b', c: 2}); + t.insert({_id: 2, a: 1, b: 'a', c: 1}); + t.insert({_id: 3, a: 1, b: 'a', c: 2}); + t.insert({_id: 4, a: 2, b: 'b', c: 1}); + t.insert({_id: 5, a: 2, b: 'b', c: 2}); + t.insert({_id: 6, a: 2, b: 'a', c: 1}); + t.insert({_id: 7, a: 2, b: 'a', c: 2}); + + verifyMin({a: 1, b: 'a', c: 1}, indexSpec, [2, 3, 4, 5, 6, 7]); + verifyMin({a: 2, b: 'a', c: 2}, indexSpec, [7]); + verifyMax({a: 1, b: 'a', c: 1}, indexSpec, [0, 1]); + verifyMax({a: 2, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6]); + + verifyMin({a: Infinity, b: 'a', c: 2}, indexSpec, []); + verifyMax({a: Infinity, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7]); + + verifyMin({a: -Infinity, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7]); + verifyMax({a: -Infinity, b: 'a', c: 2}, indexSpec, []); + + // 'a' > Infinity, actually. + verifyMin({a: 1, b: Infinity, c: 2}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: Infinity, c: 2}, indexSpec, [0, 1, 2, 3]); + + // Also, 'a' > -Infinity. + verifyMin({a: 1, b: -Infinity, c: 2}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: -Infinity, c: 2}, indexSpec, [0, 1, 2, 3]); + + verifyMin({a: 1, b: 'a', c: Infinity}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: 'a', c: Infinity}, indexSpec, [0, 1, 2, 3]); + + verifyMin({a: 1, b: 'a', c: -Infinity}, indexSpec, [2, 3, 4, 5, 6, 7]); + verifyMax({a: 1, b: 'a', c: -Infinity}, indexSpec, [0, 1]); +})(); |