summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/window_function
diff options
context:
space:
mode:
authorNick Zolnierz <nicholas.zolnierz@mongodb.com>2021-02-22 21:28:02 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-23 02:51:09 +0000
commitd93aff7795f7089e9bdd253db792c6878c4be1cd (patch)
treed295312e90486bd43c2be434dc6b106d238216e9 /src/mongo/db/pipeline/window_function
parent3274c2a3d916cfc3e73c9020660fe4d0fb45ebf2 (diff)
downloadmongo-d93aff7795f7089e9bdd253db792c6878c4be1cd.tar.gz
Revert "SERVER-54049 Add translation phase for accumulator-style window functions"
This reverts commit 8b27b6710d4db7cefb840309903462ed40007402.
Diffstat (limited to 'src/mongo/db/pipeline/window_function')
-rw-r--r--src/mongo/db/pipeline/window_function/partition_iterator.cpp2
-rw-r--r--src/mongo/db/pipeline/window_function/partition_iterator.h11
-rw-r--r--src/mongo/db/pipeline/window_function/partition_iterator_test.cpp24
-rw-r--r--src/mongo/db/pipeline/window_function/window_function_exec.cpp80
-rw-r--r--src/mongo/db/pipeline/window_function/window_function_exec.h12
-rw-r--r--src/mongo/db/pipeline/window_function/window_function_exec_test.cpp9
-rw-r--r--src/mongo/db/pipeline/window_function/window_function_expression.h18
7 files changed, 19 insertions, 137 deletions
diff --git a/src/mongo/db/pipeline/window_function/partition_iterator.cpp b/src/mongo/db/pipeline/window_function/partition_iterator.cpp
index 9f2034c80f5..435cb7a765b 100644
--- a/src/mongo/db/pipeline/window_function/partition_iterator.cpp
+++ b/src/mongo/db/pipeline/window_function/partition_iterator.cpp
@@ -125,7 +125,7 @@ void PartitionIterator::getNextDocument() {
auto doc = getNextRes.releaseDocument();
if (_partitionExpr) {
- auto curKey = (*_partitionExpr)->evaluate(doc, &_expCtx->variables);
+ auto curKey = _partitionExpr->evaluate(doc, &_expCtx->variables);
uassert(ErrorCodes::TypeMismatch,
"Cannot 'partitionBy' an expression of type array",
!curKey.isArray());
diff --git a/src/mongo/db/pipeline/window_function/partition_iterator.h b/src/mongo/db/pipeline/window_function/partition_iterator.h
index 3e645d8a768..bf7f0bd1097 100644
--- a/src/mongo/db/pipeline/window_function/partition_iterator.h
+++ b/src/mongo/db/pipeline/window_function/partition_iterator.h
@@ -42,7 +42,7 @@ class PartitionIterator {
public:
PartitionIterator(ExpressionContext* expCtx,
DocumentSource* source,
- boost::optional<boost::intrusive_ptr<Expression>> partitionExpr)
+ boost::optional<const ExpressionFieldPath&> partitionExpr)
: _expCtx(expCtx),
_source(source),
_partitionExpr(partitionExpr),
@@ -75,13 +75,6 @@ public:
return _currentIndex;
}
- /**
- * Sets the input DocumentSource for this iterator to 'source'.
- */
- void setSource(DocumentSource* source) {
- _source = source;
- }
-
private:
/**
* Retrieves the next document from the prior stage and updates the state accordingly.
@@ -105,7 +98,7 @@ private:
ExpressionContext* _expCtx;
DocumentSource* _source;
- boost::optional<boost::intrusive_ptr<Expression>> _partitionExpr;
+ boost::optional<const ExpressionFieldPath&> _partitionExpr;
std::vector<Document> _cache;
int _currentIndex = 0;
Value _partitionKey;
diff --git a/src/mongo/db/pipeline/window_function/partition_iterator_test.cpp b/src/mongo/db/pipeline/window_function/partition_iterator_test.cpp
index 7c6f80b3031..f0666f12f39 100644
--- a/src/mongo/db/pipeline/window_function/partition_iterator_test.cpp
+++ b/src/mongo/db/pipeline/window_function/partition_iterator_test.cpp
@@ -84,8 +84,7 @@ TEST_F(PartitionIteratorTest, LookaheadOutOfRangeAccessNewPartition) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
ASSERT_DOCUMENT_EQ(docs[1].getDocument(), *partIter[1]);
ASSERT_FALSE(partIter[2]);
@@ -99,8 +98,7 @@ TEST_F(PartitionIteratorTest, AdvanceMovesCurrent) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
ASSERT_DOCUMENT_EQ(docs[1].getDocument(), *partIter[1]);
ASSERT_FALSE(partIter[2]);
@@ -118,8 +116,7 @@ TEST_F(PartitionIteratorTest, AdvanceOverPartitionBoundary) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
// First advance to the final document in partition with key "1".
ASSERT_ADVANCE_RESULT(PartitionIterator::AdvanceResult::kAdvanced, partIter.advance());
@@ -136,8 +133,7 @@ TEST_F(PartitionIteratorTest, AdvanceResultsInEof) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
ASSERT_ADVANCE_RESULT(PartitionIterator::AdvanceResult::kEOF, partIter.advance());
@@ -153,8 +149,7 @@ TEST_F(PartitionIteratorTest, CurrentReturnsCorrectDocumentAsIteratorAdvances) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
partIter.advance();
ASSERT_DOCUMENT_EQ(docs[1].getDocument(), *partIter[0]);
@@ -167,8 +162,7 @@ TEST_F(PartitionIteratorTest, EmptyCollectionReturnsEOF) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_FALSE(partIter[0]);
ASSERT_ADVANCE_RESULT(PartitionIterator::AdvanceResult::kEOF, partIter.advance());
}
@@ -179,8 +173,7 @@ TEST_F(PartitionIteratorTest, PartitionByArrayErrs) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_DOCUMENT_EQ(docs[0].getDocument(), *partIter[0]);
ASSERT_THROWS_CODE(*partIter[1], AssertionException, ErrorCodes::TypeMismatch);
}
@@ -191,8 +184,7 @@ TEST_F(PartitionIteratorTest, CurrentOffsetIsCorrectAfterDocumentsAreAccessed) {
const auto mock = DocumentSourceMock::createForTest(docs, getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "a", getExpCtx()->variablesParseState);
- auto partIter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto partIter = PartitionIterator(getExpCtx().get(), mock.get(), *key);
ASSERT_EQ(0, partIter.getCurrentOffset());
auto doc = partIter[0];
partIter.advance();
diff --git a/src/mongo/db/pipeline/window_function/window_function_exec.cpp b/src/mongo/db/pipeline/window_function/window_function_exec.cpp
deleted file mode 100644
index a6ff3438df7..00000000000
--- a/src/mongo/db/pipeline/window_function/window_function_exec.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright (C) 2021-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/db/pipeline/window_function/window_function_exec.h"
-#include "mongo/db/pipeline/window_function/window_function_exec_non_removable.h"
-
-namespace mongo {
-
-namespace {
-
-std::unique_ptr<WindowFunctionExec> translateDocumentWindow(
- PartitionIterator* iter,
- boost::intrusive_ptr<window_function::Expression> expr,
- const WindowBounds::DocumentBased& bounds) {
- uassert(5397904,
- "Only 'unbounded' lower bound is currently supported",
- stdx::holds_alternative<WindowBounds::Unbounded>(bounds.lower));
- uassert(5397903,
- "Only 'current' upper bound is currently supported",
- stdx::holds_alternative<WindowBounds::Current>(bounds.upper));
-
- // A left unbounded window will always be non-removable regardless of the upper
- // bound.
- return std::make_unique<WindowFunctionExecNonRemovable<AccumulatorState>>(
- iter, std::move(expr->input()), expr->buildAccumulatorOnly(), bounds.upper);
-}
-
-} // namespace
-
-std::unique_ptr<WindowFunctionExec> WindowFunctionExec::create(
- PartitionIterator* iter, const WindowFunctionStatement& functionStmt) {
- uassert(5397905,
- "Window functions cannot set to dotted paths",
- functionStmt.fieldName.find('.') == std::string::npos);
-
- // Use a sentinel variable to avoid a compilation error when some cases of std::visit don't
- // return a value.
- std::unique_ptr<WindowFunctionExec> exec;
- stdx::visit(
- visit_helper::Overloaded{
- [&](const WindowBounds::DocumentBased& docBase) {
- exec = translateDocumentWindow(iter, functionStmt.expr, docBase);
- },
- [&](const WindowBounds::RangeBased& rangeBase) {
- uasserted(5397901, "Ranged based windows not currently supported");
- },
- [&](const WindowBounds::TimeBased& timeBase) {
- uasserted(5397902, "Time based windows are not currently supported");
- }},
- functionStmt.expr->bounds().bounds);
- return exec;
-}
-
-} // namespace mongo
diff --git a/src/mongo/db/pipeline/window_function/window_function_exec.h b/src/mongo/db/pipeline/window_function/window_function_exec.h
index 0a83de32595..4dfcbdd8356 100644
--- a/src/mongo/db/pipeline/window_function/window_function_exec.h
+++ b/src/mongo/db/pipeline/window_function/window_function_exec.h
@@ -32,7 +32,6 @@
#include <queue>
#include "mongo/db/pipeline/document_source.h"
-#include "mongo/db/pipeline/document_source_set_window_fields.h"
#include "mongo/db/pipeline/expression.h"
#include "mongo/db/pipeline/window_function/partition_iterator.h"
#include "mongo/db/pipeline/window_function/window_bounds.h"
@@ -40,8 +39,6 @@
namespace mongo {
-struct WindowFunctionStatement;
-
/**
* An interface for an executor class capable of evaluating a function over a given window
* definition. The function must expose an accumulate-type interface and potentially a remove
@@ -52,12 +49,7 @@ struct WindowFunctionStatement;
*/
class WindowFunctionExec {
public:
- /**
- * Creates an appropriate WindowFunctionExec that is capable of evaluating the window function
- * over the given bounds, both found within the WindowFunctionStatement.
- */
- static std::unique_ptr<WindowFunctionExec> create(PartitionIterator* iter,
- const WindowFunctionStatement& functionStmt);
+ WindowFunctionExec(PartitionIterator* iter) : _iter(iter){};
/**
* Retrieve the next value computed by the window function.
@@ -70,8 +62,6 @@ public:
virtual void reset() = 0;
protected:
- WindowFunctionExec(PartitionIterator* iter) : _iter(iter){};
-
PartitionIterator* _iter;
};
diff --git a/src/mongo/db/pipeline/window_function/window_function_exec_test.cpp b/src/mongo/db/pipeline/window_function/window_function_exec_test.cpp
index 0892d7d164c..bdc773ee131 100644
--- a/src/mongo/db/pipeline/window_function/window_function_exec_test.cpp
+++ b/src/mongo/db/pipeline/window_function/window_function_exec_test.cpp
@@ -152,8 +152,7 @@ TEST_F(WindowFunctionExecNonRemovableTest, AccumulateOnlyWithMultiplePartitions)
auto mock = DocumentSourceMock::createForTest(std::move(docs), getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto iter = PartitionIterator(
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key));
+ auto iter = PartitionIterator{getExpCtx().get(), mock.get(), *key};
auto input =
ExpressionFieldPath::parse(getExpCtx().get(), "$a", getExpCtx()->variablesParseState);
auto mgr = WindowFunctionExecNonRemovable<AccumulatorState>(
@@ -329,8 +328,7 @@ TEST_F(WindowFunctionExecRemovableDocumentTest, CanResetFunction) {
auto mock = DocumentSourceMock::createForTest(std::move(docs), getExpCtx());
auto key = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- auto iter = PartitionIterator{
- getExpCtx().get(), mock.get(), boost::optional<boost::intrusive_ptr<Expression>>(key)};
+ auto iter = PartitionIterator{getExpCtx().get(), mock.get(), *key};
auto input =
ExpressionFieldPath::parse(getExpCtx().get(), "$a", getExpCtx()->variablesParseState);
CollatorInterfaceMock collator = CollatorInterfaceMock::MockType::kToLowerString;
@@ -357,8 +355,7 @@ TEST_F(WindowFunctionExecRemovableDocumentTest, CanResetFunction) {
auto mockTwo = DocumentSourceMock::createForTest(std::move(docsTwo), getExpCtx());
auto keyTwo = ExpressionFieldPath::createPathFromString(
getExpCtx().get(), "key", getExpCtx()->variablesParseState);
- iter = PartitionIterator{
- getExpCtx().get(), mockTwo.get(), boost::optional<boost::intrusive_ptr<Expression>>(key)};
+ iter = PartitionIterator{getExpCtx().get(), mockTwo.get(), *key};
input = ExpressionFieldPath::parse(getExpCtx().get(), "$a", getExpCtx()->variablesParseState);
maxFunc = std::make_unique<WindowFunctionMax>(cmp);
mgr = WindowFunctionExecRemovableDocument(
diff --git a/src/mongo/db/pipeline/window_function/window_function_expression.h b/src/mongo/db/pipeline/window_function/window_function_expression.h
index f02445314ee..bf1fc38a55e 100644
--- a/src/mongo/db/pipeline/window_function/window_function_expression.h
+++ b/src/mongo/db/pipeline/window_function/window_function_expression.h
@@ -29,7 +29,6 @@
#pragma once
-#include "mongo/db/pipeline/accumulator.h"
#include "mongo/db/pipeline/document_source.h"
#include "mongo/db/pipeline/document_source_set_window_fields_gen.h"
#include "mongo/db/pipeline/window_function/window_bounds.h"
@@ -93,13 +92,10 @@ public:
virtual boost::intrusive_ptr<::mongo::Expression> input() const = 0;
- virtual boost::intrusive_ptr<AccumulatorState> buildAccumulatorOnly() const = 0;
-
private:
static StringMap<Parser> parserMap;
};
-template <typename NonRemovableType>
class ExpressionFromAccumulator : public Expression {
public:
static boost::intrusive_ptr<Expression> parse(BSONElement elem,
@@ -118,8 +114,8 @@ public:
<< " found an unknown argument: " << arg.fieldNameStringData(),
allowedFields.find(arg.fieldNameStringData()) != allowedFields.end());
}
- return make_intrusive<ExpressionFromAccumulator<NonRemovableType>>(
- expCtx, std::move(accumulatorName), std::move(input), std::move(bounds));
+ return make_intrusive<ExpressionFromAccumulator>(
+ std::move(accumulatorName), std::move(input), std::move(bounds));
}
Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final {
MutableDocument args;
@@ -132,12 +128,10 @@ public:
}};
}
- ExpressionFromAccumulator(ExpressionContext* expCtx,
- std::string accumulatorName,
+ ExpressionFromAccumulator(std::string accumulatorName,
boost::intrusive_ptr<::mongo::Expression> input,
WindowBounds bounds)
- : _expCtx(expCtx),
- _accumulatorName(std::move(accumulatorName)),
+ : _accumulatorName(std::move(accumulatorName)),
_input(std::move(input)),
_bounds(std::move(bounds)) {}
@@ -153,12 +147,8 @@ public:
return _bounds;
}
- boost::intrusive_ptr<AccumulatorState> buildAccumulatorOnly() const {
- return NonRemovableType::create(_expCtx);
- }
private:
- ExpressionContext* _expCtx;
std::string _accumulatorName;
boost::intrusive_ptr<::mongo::Expression> _input;
WindowBounds _bounds;