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-01-06 01:22:50 +0000
commit40baa93ce71492b71fe9ace2ccc3ea6fd441c158 (patch)
tree9107c179e6165604066af3ee3efde2f7008b8300
parent2a3aa2ed8eaf76163b0506c4c7a93cb913379b69 (diff)
downloadmongo-40baa93ce71492b71fe9ace2ccc3ea6fd441c158.tar.gz
SERVER-71387 Add missing typecheck for range-based window
-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 ea59f5c6e09..872b4eb0b8d 100644
--- a/src/mongo/db/pipeline/window_function/partition_iterator.cpp
+++ b/src/mongo/db/pipeline/window_function/partition_iterator.cpp
@@ -301,8 +301,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