summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2020-02-07 09:34:54 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-07 14:47:44 +0000
commitb52d0d06a080ac7b2879ebb7da4a551f5aa36610 (patch)
tree1364d788dc2eb6a21d009847dafa0708d955b832 /src/mongo/db/pipeline
parent592bb96b9cd7c00b8741afaec23152ec7adc4909 (diff)
downloadmongo-b52d0d06a080ac7b2879ebb7da4a551f5aa36610.tar.gz
Revert "SERVER-45530 Implement $match and $project duplication and pushdown across $unionWith"
This reverts commit 942ec3300e82672536f34d8273314c5504ae91fb.
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r--src/mongo/db/pipeline/document_source_change_stream.cpp4
-rw-r--r--src/mongo/db/pipeline/document_source_change_stream.h11
-rw-r--r--src/mongo/db/pipeline/document_source_list_sessions.h10
-rw-r--r--src/mongo/db/pipeline/document_source_match.h13
-rw-r--r--src/mongo/db/pipeline/document_source_single_document_transformation.h8
-rw-r--r--src/mongo/db/pipeline/document_source_union_with.cpp35
-rw-r--r--src/mongo/db/pipeline/document_source_union_with.h25
-rw-r--r--src/mongo/db/pipeline/pipeline_test.cpp154
8 files changed, 16 insertions, 244 deletions
diff --git a/src/mongo/db/pipeline/document_source_change_stream.cpp b/src/mongo/db/pipeline/document_source_change_stream.cpp
index 9af00b5773c..153bc685a70 100644
--- a/src/mongo/db/pipeline/document_source_change_stream.cpp
+++ b/src/mongo/db/pipeline/document_source_change_stream.cpp
@@ -139,6 +139,10 @@ Value DocumentSourceOplogMatch::serialize(optional<ExplainOptions::Verbosity> ex
return Value();
}
+DocumentSourceOplogMatch::DocumentSourceOplogMatch(BSONObj filter,
+ const intrusive_ptr<ExpressionContext>& expCtx)
+ : DocumentSourceMatch(std::move(filter), expCtx) {}
+
void DocumentSourceChangeStream::checkValueType(const Value v,
const StringData filedName,
BSONType expectedType) {
diff --git a/src/mongo/db/pipeline/document_source_change_stream.h b/src/mongo/db/pipeline/document_source_change_stream.h
index 9eeaaf19b9b..9570f2e16e1 100644
--- a/src/mongo/db/pipeline/document_source_change_stream.h
+++ b/src/mongo/db/pipeline/document_source_change_stream.h
@@ -29,15 +29,12 @@
#pragma once
-#include <type_traits>
-
#include "mongo/db/pipeline/document_source.h"
#include "mongo/db/pipeline/document_source_change_stream_gen.h"
#include "mongo/db/pipeline/document_source_match.h"
#include "mongo/db/pipeline/document_source_single_document_transformation.h"
#include "mongo/db/pipeline/field_path.h"
#include "mongo/db/pipeline/resume_token.h"
-#include "mongo/util/intrusive_counter.h"
namespace mongo {
@@ -213,12 +210,6 @@ private:
*/
class DocumentSourceOplogMatch final : public DocumentSourceMatch {
public:
- DocumentSourceOplogMatch(const DocumentSourceOplogMatch& other) : DocumentSourceMatch(other) {}
-
- virtual boost::intrusive_ptr<DocumentSourceMatch> clone() const {
- return make_intrusive<std::decay_t<decltype(*this)>>(*this);
- }
-
static boost::intrusive_ptr<DocumentSourceOplogMatch> create(
BSONObj filter, const boost::intrusive_ptr<ExpressionContext>& expCtx);
@@ -237,7 +228,7 @@ public:
Value serialize(boost::optional<ExplainOptions::Verbosity> explain) const final;
private:
- using DocumentSourceMatch::DocumentSourceMatch;
+ DocumentSourceOplogMatch(BSONObj filter, const boost::intrusive_ptr<ExpressionContext>& expCtx);
};
} // namespace mongo
diff --git a/src/mongo/db/pipeline/document_source_list_sessions.h b/src/mongo/db/pipeline/document_source_list_sessions.h
index ed8dcdf177d..86ee7c543fe 100644
--- a/src/mongo/db/pipeline/document_source_list_sessions.h
+++ b/src/mongo/db/pipeline/document_source_list_sessions.h
@@ -29,13 +29,10 @@
#pragma once
-#include <type_traits>
-
#include "mongo/bson/bsonelement.h"
#include "mongo/db/pipeline/document_source_list_local_sessions.h"
#include "mongo/db/pipeline/document_source_match.h"
#include "mongo/db/pipeline/lite_parsed_document_source.h"
-#include "mongo/util/intrusive_counter.h"
namespace mongo {
@@ -50,13 +47,6 @@ namespace mongo {
*/
class DocumentSourceListSessions final : public DocumentSourceMatch {
public:
- DocumentSourceListSessions(const DocumentSourceListSessions& other)
- : DocumentSourceMatch(other) {}
-
- virtual boost::intrusive_ptr<DocumentSourceMatch> clone() const {
- return make_intrusive<std::decay_t<decltype(*this)>>(*this);
- }
-
static constexpr StringData kStageName = "$listSessions"_sd;
class LiteParsed final : public LiteParsedDocumentSource {
diff --git a/src/mongo/db/pipeline/document_source_match.h b/src/mongo/db/pipeline/document_source_match.h
index ecdda5dc274..a684c4c82f8 100644
--- a/src/mongo/db/pipeline/document_source_match.h
+++ b/src/mongo/db/pipeline/document_source_match.h
@@ -30,24 +30,16 @@
#pragma once
#include <memory>
-#include <type_traits>
#include <utility>
#include "mongo/client/connpool.h"
#include "mongo/db/matcher/matcher.h"
#include "mongo/db/pipeline/document_source.h"
-#include "mongo/util/intrusive_counter.h"
namespace mongo {
class DocumentSourceMatch : public DocumentSource {
public:
- template <typename T, typename... Args, typename>
- friend boost::intrusive_ptr<T> make_intrusive(Args&&...);
- virtual boost::intrusive_ptr<DocumentSourceMatch> clone() const {
- return make_intrusive<std::decay_t<decltype(*this)>>(*this);
- }
-
static constexpr StringData kStageName = "$match"_sd;
/**
* Convenience method for creating a $match stage.
@@ -178,11 +170,6 @@ public:
}
protected:
- DocumentSourceMatch(const DocumentSourceMatch& other)
- : DocumentSourceMatch(
- other.serialize().getDocument().toBson().firstElement().embeddedObject(),
- other.pExpCtx) {}
-
GetNextResult doGetNext() override;
DocumentSourceMatch(const BSONObj& query,
const boost::intrusive_ptr<ExpressionContext>& expCtx);
diff --git a/src/mongo/db/pipeline/document_source_single_document_transformation.h b/src/mongo/db/pipeline/document_source_single_document_transformation.h
index d983de72021..323c628f60e 100644
--- a/src/mongo/db/pipeline/document_source_single_document_transformation.h
+++ b/src/mongo/db/pipeline/document_source_single_document_transformation.h
@@ -29,8 +29,6 @@
#pragma once
-#include <type_traits>
-
#include "mongo/db/pipeline/document_source.h"
#include "mongo/db/pipeline/transformer_interface.h"
@@ -44,12 +42,6 @@ namespace mongo {
*/
class DocumentSourceSingleDocumentTransformation final : public DocumentSource {
public:
- virtual boost::intrusive_ptr<DocumentSource> clone() const {
- auto list = DocumentSource::parse(pExpCtx, serialize().getDocument().toBson());
- invariant(list.size() == 1);
- return list.front();
- }
-
DocumentSourceSingleDocumentTransformation(
const boost::intrusive_ptr<ExpressionContext>& pExpCtx,
std::unique_ptr<TransformerInterface> parsedTransform,
diff --git a/src/mongo/db/pipeline/document_source_union_with.cpp b/src/mongo/db/pipeline/document_source_union_with.cpp
index 00f531bbf8d..a6a31657dbf 100644
--- a/src/mongo/db/pipeline/document_source_union_with.cpp
+++ b/src/mongo/db/pipeline/document_source_union_with.cpp
@@ -32,18 +32,15 @@
#include <iterator>
-#include "mongo/db/commands/test_commands_enabled.h"
-#include "mongo/db/pipeline/document_source_match.h"
-#include "mongo/db/pipeline/document_source_single_document_transformation.h"
#include "mongo/db/pipeline/document_source_union_with.h"
#include "mongo/db/pipeline/document_source_union_with_gen.h"
#include "mongo/util/log.h"
namespace mongo {
-REGISTER_DOCUMENT_SOURCE(unionWith,
- DocumentSourceUnionWith::LiteParsed::parse,
- DocumentSourceUnionWith::createFromBson);
+REGISTER_TEST_DOCUMENT_SOURCE(unionWith,
+ DocumentSourceUnionWith::LiteParsed::parse,
+ DocumentSourceUnionWith::createFromBson);
namespace {
std::unique_ptr<Pipeline, PipelineDeleter> buildPipelineFromViewDefinition(
@@ -119,9 +116,6 @@ PrivilegeVector DocumentSourceUnionWith::LiteParsed::requiredPrivileges(
boost::intrusive_ptr<DocumentSource> DocumentSourceUnionWith::createFromBson(
BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
- uassert(ErrorCodes::NotImplemented,
- "$unionWith can only be used if test commands are enabled",
- getTestCommandsEnabled());
uassert(ErrorCodes::FailedToParse,
str::stream()
<< "the $unionWith stage specification must be an object or string, but found "
@@ -169,23 +163,12 @@ DocumentSource::GetNextResult DocumentSourceUnionWith::doGetNext() {
return GetNextResult::makeEOF();
}
-Pipeline::SourceContainer::iterator DocumentSourceUnionWith::doOptimizeAt(
- Pipeline::SourceContainer::iterator itr, Pipeline::SourceContainer* container) {
- auto duplicateAcrossUnion = [&](auto&& nextStage) {
- _pipeline->addFinalSource(nextStage->clone());
- auto newStageItr = container->insert(itr, std::move(nextStage));
- container->erase(std::next(itr));
- return newStageItr == container->begin() ? newStageItr : std::prev(newStageItr);
- };
- if (std::next(itr) != container->end()) {
- if (auto nextMatch = dynamic_cast<DocumentSourceMatch*>((*std::next(itr)).get()))
- return duplicateAcrossUnion(nextMatch);
- else if (auto nextProject = dynamic_cast<DocumentSourceSingleDocumentTransformation*>(
- (*std::next(itr)).get()))
- return duplicateAcrossUnion(nextProject);
- }
- return std::next(itr);
-};
+DocumentSource::GetModPathsReturn DocumentSourceUnionWith::getModifiedPaths() const {
+ // Since we might have a document arrive from the foreign pipeline with the same path as a
+ // document in the main pipeline. Without introspecting the sub-pipeline, we must report that
+ // all paths have been modified.
+ return {GetModPathsReturn::Type::kAllPaths, {}, {}};
+}
void DocumentSourceUnionWith::doDispose() {
if (_pipeline) {
diff --git a/src/mongo/db/pipeline/document_source_union_with.h b/src/mongo/db/pipeline/document_source_union_with.h
index beb69c7e9e5..ba0327a4be2 100644
--- a/src/mongo/db/pipeline/document_source_union_with.h
+++ b/src/mongo/db/pipeline/document_source_union_with.h
@@ -80,15 +80,10 @@ public:
std::vector<Value>& array,
boost::optional<ExplainOptions::Verbosity> explain = boost::none) const final;
- GetModPathsReturn getModifiedPaths() const final {
- // Since we might have a document arrive from the foreign pipeline with the same path as a
- // document in the main pipeline. Without introspecting the sub-pipeline, we must report
- // that all paths have been modified.
- return {GetModPathsReturn::Type::kAllPaths, {}, {}};
- }
+ GetModPathsReturn getModifiedPaths() const final;
StageConstraints constraints(Pipeline::SplitState) const final {
- auto constraints = StageConstraints(
+ return StageConstraints(
StreamType::kStreaming,
PositionRequirement::kNone,
HostTypeRequirement::kAnyShard,
@@ -99,13 +94,6 @@ public:
// outside of the constraints as long as the involved namespaces are reported correctly.
LookupRequirement::kAllowed,
UnionRequirement::kAllowed);
-
- // DocumentSourceUnionWith cannot directly swap with match but it contains custom logic in
- // the doOptimizeAt() member function to allow itself to duplicate any match ahead in the
- // current pipeline and place one copy inside its sub-pipeline and one copy behind in the
- // current pipeline.
- constraints.canSwapWithMatch = false;
- return constraints;
}
DepsTracker::State getDependencies(DepsTracker* deps) const final;
@@ -123,15 +111,6 @@ public:
protected:
GetNextResult doGetNext() final;
-
- Pipeline::SourceContainer::iterator doOptimizeAt(Pipeline::SourceContainer::iterator itr,
- Pipeline::SourceContainer* container) final;
-
- boost::intrusive_ptr<DocumentSource> optimize() final {
- _pipeline->optimizePipeline();
- return this;
- }
-
void doDispose() final;
private:
diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp
index 06e3c06923f..5cc39e890bf 100644
--- a/src/mongo/db/pipeline/pipeline_test.cpp
+++ b/src/mongo/db/pipeline/pipeline_test.cpp
@@ -1853,160 +1853,6 @@ TEST(PipelineOptimizationTest, SortSkipProjSkipLimSkipLimBecomesTopKSortSkipProj
assertPipelineOptimizesAndSerializesTo(inputPipe, outputPipe, serializedPipe);
}
-TEST(PipelineOptimizationTest, MatchGetsPushedIntoBothChildrenOfUnion) {
- setTestCommandsEnabled(true); // TODO SERVER-45712 remove this line.
- assertPipelineOptimizesTo(
- "["
- " {$unionWith: 'coll'},"
- " {$match: {x: {$eq: 2}}}"
- "]",
- "[{$match: {x: {$eq: 2}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$match: {x: {$eq: 2}}}]"
- " }}]");
-
- // Test that the $match can get pulled forward through other stages.
- assertPipelineOptimizesAndSerializesTo(
- "["
- " {$unionWith: 'coll'},"
- " {$lookup: {from: 'lookupColl', as: 'y', localField: 'z', foreignField: 'z'}},"
- " {$sort: {score: 1}},"
- " {$match: {x: {$eq: 2}}}"
- "]",
- "["
- " {$match: {x: {$eq: 2}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$match: {x: {$eq: 2}}}]"
- " }},"
- " {$lookup: {from: 'lookupColl', as: 'y', localField: 'z', foreignField: 'z'}},"
- " {$sort: {sortKey: {score: 1}}}"
- "]",
- "["
- " {$match: {x: {$eq: 2}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$match: {x: {$eq: 2}}}]"
- " }},"
- " {$lookup: {from: 'lookupColl', as: 'y', localField: 'z', foreignField: 'z'}},"
- " {$sort: {score: 1}}"
- "]");
-
- // Test that the $match can get pulled forward from after the $unionWith to inside, then to the
- // beginning of a $unionWith subpipeline.
- // TODO: SERVER-45535 the explained inner pipeline should have the 'sortKey' form for $sort.
- assertPipelineOptimizesAndSerializesTo(
- "["
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: ["
- " {$project: {y: false}},"
- " {$sort: {score: 1}}"
- " ]"
- " }},"
- " {$match: {x: {$eq: 2}}}"
- "]",
- "["
- " {$match: {x: {$eq: 2}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: ["
- " {$match: {x: {$eq: 2}}},"
- " {$project: {y: false}},"
- " {$sort: {score: 1}}"
- " ]"
- " }}"
- "]",
- "["
- " {$match: {x: {$eq: 2}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: ["
- " {$match: {x: {$eq: 2}}},"
- " {$project: {y: false}},"
- " {$sort: {score: 1}}"
- " ]"
- " }}"
- "]");
-}
-
-TEST(PipelineOptimizationTest, ProjectGetsPushedIntoBothChildrenOfUnion) {
- setTestCommandsEnabled(true); // TODO SERVER-45712 remove this line.
- assertPipelineOptimizesTo(
- "["
- " {$unionWith: 'coll'},"
- " {$project: {x: false}}"
- "]",
- "[{$project: {x: false}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$project: {x: false}}]"
- " }}]");
-
- // Test an inclusion projection.
- assertPipelineOptimizesTo(
- "["
- " {$unionWith: 'coll'},"
- " {$project: {x: true}}"
- "]",
- "[{$project: {_id: true, x: true}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$project: {_id: true, x: true}}]"
- " }}]");
-
- // Test a $set.
- assertPipelineOptimizesTo(
- "["
- " {$unionWith: 'coll'},"
- " {$set: {x: 'new value'}}"
- "]",
- "[{$set: {x: {$const: 'new value'}}},"
- " {$unionWith: {"
- " coll: 'coll',"
- " pipeline: [{$set: {x: {$const: 'new value'}}}]"
- " }}]");
-}
-
-TEST(PipelineOptimizationTest, UnionWithViewsSampleUseCase) {
- setTestCommandsEnabled(true); // TODO SERVER-45712 remove this line.
- // Test that if someone uses $unionWith to query one logical collection from four physical
- // collections then the query and projection can get pushed down to next to each collection
- // access.
- assertPipelineOptimizesTo(
- "["
- " {$unionWith: 'Q2'},"
- " {$unionWith: 'Q3'},"
- " {$unionWith: 'Q4'},"
- " {$match: {business: {$eq: 'good'}}},"
- " {$project: {_id: true, x: true}}"
- "]",
- "[{$match: {business: {$eq: 'good'}}},"
- " {$project: {_id: true, x: true}},"
- " {$unionWith: {"
- " coll: 'Q2',"
- " pipeline: ["
- " {$match: {business: {$eq: 'good'}}},"
- " {$project: {_id: true, x: true}}"
- " ]"
- " }},"
- " {$unionWith: {"
- " coll: 'Q3',"
- " pipeline: ["
- " {$match: {business: {$eq: 'good'}}},"
- " {$project: {_id: true, x: true}}"
- " ]"
- " }},"
- " {$unionWith: {"
- " coll: 'Q4',"
- " pipeline: ["
- " {$match: {business: {$eq: 'good'}}},"
- " {$project: {_id: true, x: true}}"
- " ]"
- " }}"
- "]");
-}
} // namespace Local
namespace Sharded {