summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/pipeline/document_source.h10
-rw-r--r--src/mongo/db/pipeline/document_source_change_stream_oplog_match.h10
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.cpp15
-rw-r--r--src/mongo/db/pipeline/document_source_graph_lookup.h6
-rw-r--r--src/mongo/db/pipeline/document_source_list_sessions.h10
-rw-r--r--src/mongo/db/pipeline/document_source_lookup.cpp14
-rw-r--r--src/mongo/db/pipeline/document_source_lookup.h6
-rw-r--r--src/mongo/db/pipeline/document_source_match.h10
-rw-r--r--src/mongo/db/pipeline/document_source_sequential_document_cache.h5
-rw-r--r--src/mongo/db/pipeline/document_source_single_document_transformation.h6
-rw-r--r--src/mongo/db/pipeline/document_source_sort.cpp5
-rw-r--r--src/mongo/db/pipeline/document_source_sort.h3
-rw-r--r--src/mongo/db/pipeline/document_source_union_with.cpp5
-rw-r--r--src/mongo/db/pipeline/document_source_union_with.h9
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp7
-rw-r--r--src/mongo/db/pipeline/pipeline.h7
16 files changed, 83 insertions, 45 deletions
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h
index 29b98369723..ee3977aed18 100644
--- a/src/mongo/db/pipeline/document_source.h
+++ b/src/mongo/db/pipeline/document_source.h
@@ -314,9 +314,13 @@ public:
/**
* Makes a deep clone of the DocumentSource by serializing and re-parsing it. DocumentSources
- * that cannot be safely cloned this way should override this method.
+ * that cannot be safely cloned this way should override this method. Callers can optionally
+ * specify 'newExpCtx' to construct the deep clone with it instead of defaulting to the
+ * original's 'ExpressionContext'.
*/
- virtual boost::intrusive_ptr<DocumentSource> clone() const {
+ virtual boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx = nullptr) const {
+ auto expCtx = newExpCtx ? newExpCtx : pExpCtx;
std::vector<Value> serializedDoc;
serializeToArray(serializedDoc);
tassert(5757900,
@@ -324,7 +328,7 @@ public:
<< " should have serialized to exactly one document. This stage may "
"need a custom clone() implementation",
serializedDoc.size() == 1 && serializedDoc[0].getType() == BSONType::Object);
- auto dsList = parse(pExpCtx, Document(serializedDoc[0].getDocument()).toBson());
+ auto dsList = parse(expCtx, Document(serializedDoc[0].getDocument()).toBson());
// Cloning should only happen once the pipeline has been fully built, after desugaring from
// one stage to multiple stages has occurred. When cloning desugared stages we expect each
// stage to re-parse to one stage.
diff --git a/src/mongo/db/pipeline/document_source_change_stream_oplog_match.h b/src/mongo/db/pipeline/document_source_change_stream_oplog_match.h
index 52b26a181a7..d6278a400c7 100644
--- a/src/mongo/db/pipeline/document_source_change_stream_oplog_match.h
+++ b/src/mongo/db/pipeline/document_source_change_stream_oplog_match.h
@@ -43,14 +43,16 @@ public:
DocumentSourceChangeStreamOplogMatch(Timestamp clusterTime,
const boost::intrusive_ptr<ExpressionContext>& expCtx);
- DocumentSourceChangeStreamOplogMatch(const DocumentSourceChangeStreamOplogMatch& other)
- : DocumentSourceMatch(other) {
+ DocumentSourceChangeStreamOplogMatch(const DocumentSourceChangeStreamOplogMatch& other,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
+ : DocumentSourceMatch(other, newExpCtx) {
_clusterTime = other._clusterTime;
_optimizedEndOfPipeline = other._optimizedEndOfPipeline;
}
- boost::intrusive_ptr<DocumentSource> clone() const final {
- return new auto(*this);
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx = nullptr) const final {
+ return new DocumentSourceChangeStreamOplogMatch(*this, newExpCtx);
}
static boost::intrusive_ptr<DocumentSource> createFromBson(
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
index 8634d4d86bd..417e92df4b0 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp
@@ -631,9 +631,13 @@ DocumentSourceGraphLookUp::DocumentSourceGraphLookUp(
_fromPipeline.push_back(BSON("$match" << BSONObj()));
}
-DocumentSourceGraphLookUp::DocumentSourceGraphLookUp(const DocumentSourceGraphLookUp& original)
- : DocumentSource(kStageName,
- original.pExpCtx->copyWith(original.pExpCtx->ns, original.pExpCtx->uuid)),
+DocumentSourceGraphLookUp::DocumentSourceGraphLookUp(
+ const DocumentSourceGraphLookUp& original,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
+ : DocumentSource(
+ kStageName,
+ newExpCtx ? newExpCtx
+ : original.pExpCtx->copyWith(original.pExpCtx->ns, original.pExpCtx->uuid)),
_from(original._from),
_as(original._as),
_connectFromField(original._connectFromField),
@@ -783,8 +787,9 @@ intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::createFromBson(
return newSource;
}
-boost::intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::clone() const {
- return make_intrusive<DocumentSourceGraphLookUp>(*this);
+boost::intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
+ return make_intrusive<DocumentSourceGraphLookUp>(*this, newExpCtx);
}
void DocumentSourceGraphLookUp::addInvolvedCollections(
diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.h b/src/mongo/db/pipeline/document_source_graph_lookup.h
index 30e63b5d64f..bc0146f1829 100644
--- a/src/mongo/db/pipeline/document_source_graph_lookup.h
+++ b/src/mongo/db/pipeline/document_source_graph_lookup.h
@@ -66,7 +66,8 @@ public:
}
};
- DocumentSourceGraphLookUp(const DocumentSourceGraphLookUp&);
+ DocumentSourceGraphLookUp(const DocumentSourceGraphLookUp&,
+ const boost::intrusive_ptr<ExpressionContext>&);
const char* getSourceName() const final;
@@ -155,7 +156,8 @@ public:
static boost::intrusive_ptr<DocumentSource> createFromBson(
BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& pExpCtx);
- boost::intrusive_ptr<DocumentSource> clone() const final;
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const final;
protected:
GetNextResult doGetNext() final;
diff --git a/src/mongo/db/pipeline/document_source_list_sessions.h b/src/mongo/db/pipeline/document_source_list_sessions.h
index 629d565e244..9c3e4d10d68 100644
--- a/src/mongo/db/pipeline/document_source_list_sessions.h
+++ b/src/mongo/db/pipeline/document_source_list_sessions.h
@@ -50,11 +50,13 @@ namespace mongo {
*/
class DocumentSourceListSessions final : public DocumentSourceMatch {
public:
- DocumentSourceListSessions(const DocumentSourceListSessions& other)
- : DocumentSourceMatch(other), _allUsers(other._allUsers), _users(other._users) {}
+ DocumentSourceListSessions(const DocumentSourceListSessions& other,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
+ : DocumentSourceMatch(other, newExpCtx), _allUsers(other._allUsers), _users(other._users) {}
- virtual boost::intrusive_ptr<DocumentSource> clone() const {
- return make_intrusive<std::decay_t<decltype(*this)>>(*this);
+ virtual boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
+ return make_intrusive<std::decay_t<decltype(*this)>>(*this, newExpCtx);
}
static constexpr StringData kStageName = "$listSessions"_sd;
diff --git a/src/mongo/db/pipeline/document_source_lookup.cpp b/src/mongo/db/pipeline/document_source_lookup.cpp
index f6f53594e7e..cfb885e94c5 100644
--- a/src/mongo/db/pipeline/document_source_lookup.cpp
+++ b/src/mongo/db/pipeline/document_source_lookup.cpp
@@ -241,9 +241,12 @@ DocumentSourceLookUp::DocumentSourceLookUp(
initializeResolvedIntrospectionPipeline();
}
-DocumentSourceLookUp::DocumentSourceLookUp(const DocumentSourceLookUp& original)
- : DocumentSource(kStageName,
- original.pExpCtx->copyWith(original.pExpCtx->ns, original.pExpCtx->uuid)),
+DocumentSourceLookUp::DocumentSourceLookUp(const DocumentSourceLookUp& original,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
+ : DocumentSource(
+ kStageName,
+ newExpCtx ? newExpCtx
+ : original.pExpCtx->copyWith(original.pExpCtx->ns, original.pExpCtx->uuid)),
_fromNs(original._fromNs),
_resolvedNs(original._resolvedNs),
_as(original._as),
@@ -270,8 +273,9 @@ DocumentSourceLookUp::DocumentSourceLookUp(const DocumentSourceLookUp& original)
}
}
-boost::intrusive_ptr<DocumentSource> DocumentSourceLookUp::clone() const {
- return make_intrusive<DocumentSourceLookUp>(*this);
+boost::intrusive_ptr<DocumentSource> DocumentSourceLookUp::clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
+ return make_intrusive<DocumentSourceLookUp>(*this, newExpCtx);
}
void validateLookupCollectionlessPipeline(const std::vector<BSONObj>& pipeline) {
diff --git a/src/mongo/db/pipeline/document_source_lookup.h b/src/mongo/db/pipeline/document_source_lookup.h
index eb28f357291..fef7cd0067f 100644
--- a/src/mongo/db/pipeline/document_source_lookup.h
+++ b/src/mongo/db/pipeline/document_source_lookup.h
@@ -121,7 +121,8 @@ public:
/**
* Copy constructor used for clone().
*/
- DocumentSourceLookUp(const DocumentSourceLookUp&);
+ DocumentSourceLookUp(const DocumentSourceLookUp&,
+ const boost::intrusive_ptr<ExpressionContext>&);
const char* getSourceName() const final;
void serializeToArray(
@@ -244,7 +245,8 @@ public:
return buildPipeline(inputDoc);
}
- boost::intrusive_ptr<DocumentSource> clone() const final;
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const final;
bool sbeCompatible() const {
return _sbeCompatible;
diff --git a/src/mongo/db/pipeline/document_source_match.h b/src/mongo/db/pipeline/document_source_match.h
index 241b0b265f3..5bf27ddfe5c 100644
--- a/src/mongo/db/pipeline/document_source_match.h
+++ b/src/mongo/db/pipeline/document_source_match.h
@@ -43,9 +43,10 @@ namespace mongo {
class DocumentSourceMatch : public DocumentSource {
public:
- virtual boost::intrusive_ptr<DocumentSource> clone() const {
+ virtual boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx = nullptr) const {
// Raw new is needed to access non-public constructors.
- return new auto(*this);
+ return new DocumentSourceMatch(*this, newExpCtx);
}
static constexpr StringData kStageName = "$match"_sd;
@@ -205,10 +206,11 @@ public:
}
protected:
- DocumentSourceMatch(const DocumentSourceMatch& other)
+ DocumentSourceMatch(const DocumentSourceMatch& other,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
: DocumentSourceMatch(
other.serialize().getDocument().toBson().firstElement().embeddedObject(),
- other.pExpCtx) {}
+ newExpCtx ? newExpCtx : other.pExpCtx) {}
GetNextResult doGetNext() override;
DocumentSourceMatch(const BSONObj& query,
diff --git a/src/mongo/db/pipeline/document_source_sequential_document_cache.h b/src/mongo/db/pipeline/document_source_sequential_document_cache.h
index 792b3b56a53..4e81390d4ef 100644
--- a/src/mongo/db/pipeline/document_source_sequential_document_cache.h
+++ b/src/mongo/db/pipeline/document_source_sequential_document_cache.h
@@ -88,8 +88,9 @@ public:
* that is being cloned. It is expected that only one of the DocumentSourceSequentialCache
* copies will be used, and therefore only one will actively be using the cache.
*/
- boost::intrusive_ptr<DocumentSource> clone() const final {
- auto newStage = create(pExpCtx, _cache);
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const final {
+ auto newStage = create(newExpCtx ? newExpCtx : pExpCtx, _cache);
// Keep the position flag so in case the containing pipeline is cloned post-optimization.
newStage->_hasOptimizedPos = _hasOptimizedPos;
newStage->_cacheIsEOF = _cacheIsEOF;
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 ca4855dfff2..db76f149213 100644
--- a/src/mongo/db/pipeline/document_source_single_document_transformation.h
+++ b/src/mongo/db/pipeline/document_source_single_document_transformation.h
@@ -44,8 +44,10 @@ namespace mongo {
*/
class DocumentSourceSingleDocumentTransformation final : public DocumentSource {
public:
- virtual boost::intrusive_ptr<DocumentSource> clone() const {
- auto list = DocumentSource::parse(pExpCtx, serialize().getDocument().toBson());
+ virtual boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx = nullptr) const {
+ auto list = DocumentSource::parse(newExpCtx ? newExpCtx : pExpCtx,
+ serialize().getDocument().toBson());
invariant(list.size() == 1);
return list.front();
}
diff --git a/src/mongo/db/pipeline/document_source_sort.cpp b/src/mongo/db/pipeline/document_source_sort.cpp
index 009b4e9defb..2c07c43c501 100644
--- a/src/mongo/db/pipeline/document_source_sort.cpp
+++ b/src/mongo/db/pipeline/document_source_sort.cpp
@@ -272,8 +272,9 @@ DocumentSource::GetNextResult DocumentSourceSort::doGetNext() {
return GetNextResult{_sortExecutor->getNext().second};
}
-boost::intrusive_ptr<DocumentSource> DocumentSourceSort::clone() const {
- return create(pExpCtx,
+boost::intrusive_ptr<DocumentSource> DocumentSourceSort::clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
+ return create(newExpCtx ? newExpCtx : pExpCtx,
getSortKeyPattern(),
_sortExecutor->getLimit(),
_sortExecutor->getMaxMemoryBytes());
diff --git a/src/mongo/db/pipeline/document_source_sort.h b/src/mongo/db/pipeline/document_source_sort.h
index da554304a77..f0ab0c28a3c 100644
--- a/src/mongo/db/pipeline/document_source_sort.h
+++ b/src/mongo/db/pipeline/document_source_sort.h
@@ -74,7 +74,8 @@ public:
std::vector<Value>& array,
boost::optional<ExplainOptions::Verbosity> explain = boost::none) const final;
- boost::intrusive_ptr<DocumentSource> clone() const final;
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const final;
GetModPathsReturn getModifiedPaths() const final {
// A $sort does not modify any paths.
diff --git a/src/mongo/db/pipeline/document_source_union_with.cpp b/src/mongo/db/pipeline/document_source_union_with.cpp
index 6e69746dd98..62904bfb270 100644
--- a/src/mongo/db/pipeline/document_source_union_with.cpp
+++ b/src/mongo/db/pipeline/document_source_union_with.cpp
@@ -107,10 +107,11 @@ void validateUnionWithCollectionlessPipeline(
);
}
-boost::intrusive_ptr<DocumentSource> DocumentSourceUnionWith::clone() const {
+boost::intrusive_ptr<DocumentSource> DocumentSourceUnionWith::clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
// At this point the ExpressionContext already has info about any resolved namespaces, so there
// is no need to resolve them again when creating the clone.
- return make_intrusive<DocumentSourceUnionWith>(*this);
+ return make_intrusive<DocumentSourceUnionWith>(*this, newExpCtx);
}
std::unique_ptr<DocumentSourceUnionWith::LiteParsed> DocumentSourceUnionWith::LiteParsed::parse(
diff --git a/src/mongo/db/pipeline/document_source_union_with.h b/src/mongo/db/pipeline/document_source_union_with.h
index e1b19c93049..0e2999a2bfc 100644
--- a/src/mongo/db/pipeline/document_source_union_with.h
+++ b/src/mongo/db/pipeline/document_source_union_with.h
@@ -70,8 +70,10 @@ public:
}
}
- DocumentSourceUnionWith(const DocumentSourceUnionWith& original)
- : DocumentSource(kStageName, original.pExpCtx->copyWith(original.pExpCtx->ns)),
+ DocumentSourceUnionWith(const DocumentSourceUnionWith& original,
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx)
+ : DocumentSource(kStageName,
+ newExpCtx ? newExpCtx : original.pExpCtx->copyWith(original.pExpCtx->ns)),
_pipeline(original._pipeline->clone()) {}
~DocumentSourceUnionWith();
@@ -138,7 +140,8 @@ public:
return *_pipeline;
}
- boost::intrusive_ptr<DocumentSource> clone() const final;
+ boost::intrusive_ptr<DocumentSource> clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const final;
const Pipeline::SourceContainer* getSubPipeline() const final {
if (_pipeline) {
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp
index d92a6fa3b29..97a896e5898 100644
--- a/src/mongo/db/pipeline/pipeline.cpp
+++ b/src/mongo/db/pipeline/pipeline.cpp
@@ -153,12 +153,13 @@ Pipeline::~Pipeline() {
invariant(_disposed);
}
-std::unique_ptr<Pipeline, PipelineDeleter> Pipeline::clone() const {
+std::unique_ptr<Pipeline, PipelineDeleter> Pipeline::clone(
+ const boost::intrusive_ptr<ExpressionContext>& newExpCtx) const {
SourceContainer clonedStages;
for (auto&& stage : _sources) {
- clonedStages.push_back(stage->clone());
+ clonedStages.push_back(stage->clone(newExpCtx));
}
- return create(clonedStages, getContext());
+ return create(clonedStages, newExpCtx ? newExpCtx : getContext());
}
template <class T>
diff --git a/src/mongo/db/pipeline/pipeline.h b/src/mongo/db/pipeline/pipeline.h
index 8784ad262c3..96cf6426be3 100644
--- a/src/mongo/db/pipeline/pipeline.h
+++ b/src/mongo/db/pipeline/pipeline.h
@@ -177,7 +177,12 @@ public:
std::vector<BSONObj> currentPipeline,
MakePipelineOptions opts);
- std::unique_ptr<Pipeline, PipelineDeleter> clone() const;
+ /**
+ * Callers can optionally specify 'newExpCtx' to construct the deep clone with it. This will be
+ * used to construct all the cloned DocumentSources as well.
+ */
+ std::unique_ptr<Pipeline, PipelineDeleter> clone(
+ const boost::intrusive_ptr<ExpressionContext>& = nullptr) const;
const boost::intrusive_ptr<ExpressionContext>& getContext() const {
return pCtx;