diff options
author | William Schultz <william.schultz@mongodb.com> | 2020-02-07 09:34:54 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-07 14:47:44 +0000 |
commit | b52d0d06a080ac7b2879ebb7da4a551f5aa36610 (patch) | |
tree | 1364d788dc2eb6a21d009847dafa0708d955b832 /src/mongo/db/pipeline | |
parent | 592bb96b9cd7c00b8741afaec23152ec7adc4909 (diff) | |
download | mongo-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')
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 { |