summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Percy <david.percy@mongodb.com>2022-11-15 16:40:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-05-17 19:49:10 +0000
commitd34931161eb5ec47029f8c69d731ed9360f51b9a (patch)
treec41bdce23d1166010f9f923dfce1b3cc975e7bea
parentac697ae13dcb5567e34fe5a98bfa3ea2fdedb175 (diff)
downloadmongo-v5.0.tar.gz
SERVER-71387 Add missing typecheck for range-based windowv5.0
-rw-r--r--jstests/aggregation/sources/setWindowFields/range_wrong_type.js36
-rw-r--r--src/mongo/db/pipeline/window_function/partition_iterator.cpp9
2 files changed, 43 insertions, 2 deletions
diff --git a/jstests/aggregation/sources/setWindowFields/range_wrong_type.js b/jstests/aggregation/sources/setWindowFields/range_wrong_type.js
new file mode 100644
index 00000000000..26001c40888
--- /dev/null
+++ b/jstests/aggregation/sources/setWindowFields/range_wrong_type.js
@@ -0,0 +1,36 @@
+/**
+ * Test that a window of the form [+N, unbounded] does not trigger a tassert
+ * on mixed-type input.
+ *
+ * Originally intended to reproduce SERVER-71387.
+ */
+(function() {
+"use strict";
+
+const coll = db.set_window_fields_range_wrong_type;
+coll.drop();
+assert.commandWorked(coll.insert([
+ // Numbers sort before strings, so we'll scan {a: 2} first.
+ {a: 2},
+ {a: 'xyz'},
+]));
+
+const err = assert.throws(() => {
+ return coll
+ .aggregate({
+ $setWindowFields: {
+ sortBy: {a: 1},
+ output: {
+ // The lower bound +3 excludes the current document {a: 2}.
+ // The only remaining document is {a: 'xyz'}.
+ // We wrongly consider {a: 'xyz'} to be 'within' the lower bound.
+ // Then, when we search for the upper bound, we are surprised
+ // to be starting from 'xyz' which is the wrong type.
+ b: {$max: 5, window: {range: [+3, 'unbounded']}},
+ },
+ }
+ })
+ .toArray();
+});
+assert.eq(err.code, 5429414, err);
+})();
diff --git a/src/mongo/db/pipeline/window_function/partition_iterator.cpp b/src/mongo/db/pipeline/window_function/partition_iterator.cpp
index 95a0935d86c..7ec49c6132f 100644
--- a/src/mongo/db/pipeline/window_function/partition_iterator.cpp
+++ b/src/mongo/db/pipeline/window_function/partition_iterator.cpp
@@ -302,8 +302,13 @@ optional<std::pair<int, int>> PartitionIterator::getEndpointsRangeBased(
for (int i = start; (doc = (*this)[i]); ++i) {
Value v = (*_sortExpr)->evaluate(*doc, &_expCtx->variables);
if (!lessThan(v, threshold)) {
- // This is the first doc we've scanned that crossed the threshold.
- return i;
+ // This is the first doc we've scanned that crossed the threshold,
+ // so it's the first doc in the window (as long as it's the expected type).
+ if (hasExpectedType(v)) {
+ return i;
+ } else {
+ return boost::none;
+ }
}
}
// We scanned every document in the partition, and none crossed the