diff options
author | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2021-02-22 21:28:02 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-02-23 02:51:09 +0000 |
commit | d93aff7795f7089e9bdd253db792c6878c4be1cd (patch) | |
tree | d295312e90486bd43c2be434dc6b106d238216e9 /src/mongo/db/pipeline/window_function | |
parent | 3274c2a3d916cfc3e73c9020660fe4d0fb45ebf2 (diff) | |
download | mongo-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')
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; |