diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/exec/update_stage.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/upsert_stage.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/ops/parsed_update.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/update/array_culling_node.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/update/modifier_node.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/update/modifier_node.h | 2 | ||||
-rw-r--r-- | src/mongo/db/update/object_replace_executor.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/update/pop_node.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/update/storage_validation.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/update/storage_validation.h | 22 | ||||
-rw-r--r-- | src/mongo/db/update/unset_node.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/update/update_driver.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/update/update_driver.h | 8 | ||||
-rw-r--r-- | src/mongo/db/update/update_executor.h | 4 |
14 files changed, 51 insertions, 30 deletions
diff --git a/src/mongo/db/exec/update_stage.cpp b/src/mongo/db/exec/update_stage.cpp index 2b6e3afddb9..f202f93d447 100644 --- a/src/mongo/db/exec/update_stage.cpp +++ b/src/mongo/db/exec/update_stage.cpp @@ -133,7 +133,7 @@ UpdateStage::UpdateStage(ExpressionContext* expCtx, _idReturning(WorkingSet::INVALID_ID), _updatedRecordIds(params.request->isMulti() ? new RecordIdSet() : nullptr) { - // Should the modifiers validate their embedded docs via storage_validation::storageValid()? + // Should the modifiers validate their embedded docs via storage_validation::scanDocument()? // Only user updates should be checked. Any system or replication stuff should pass through. const auto request = _params.request; diff --git a/src/mongo/db/exec/upsert_stage.cpp b/src/mongo/db/exec/upsert_stage.cpp index 035419f4c39..ce29c419b7d 100644 --- a/src/mongo/db/exec/upsert_stage.cpp +++ b/src/mongo/db/exec/upsert_stage.cpp @@ -283,7 +283,7 @@ void UpsertStage::_assertDocumentToBeInsertedIsValid(const mb::Document& documen serverGlobalParams.featureCompatibility.isVersionInitialized() && serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo( multiversion::FeatureCompatibilityVersion::kFullyDowngradedTo_5_0); - storage_validation::storageValid(document, + storage_validation::scanDocument(document, allowTopLevelDollarPrefixes, true, /* Should validate for storage */ &containsDotsAndDollarsField); diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp index f36bee843fb..2d4df260b1a 100644 --- a/src/mongo/db/ops/parsed_update.cpp +++ b/src/mongo/db/ops/parsed_update.cpp @@ -182,6 +182,11 @@ void ParsedUpdate::parseUpdate() { _driver.setCollator(_expCtx->getCollator()); _driver.setLogOp(true); _driver.setFromOplogApplication(_request->isFromOplogApplication()); + // Time-series operations will not result in any documents with dots or dollars fields. + if (auto source = _request->source(); source == OperationSource::kTimeseriesInsert || + source == OperationSource::kTimeseriesUpdate) { + _driver.setSkipDotsDollarsCheck(true); + } _driver.parse(_request->getUpdateModification(), _arrayFilters, diff --git a/src/mongo/db/update/array_culling_node.cpp b/src/mongo/db/update/array_culling_node.cpp index ef6c85e45d3..76e2dd25780 100644 --- a/src/mongo/db/update/array_culling_node.cpp +++ b/src/mongo/db/update/array_culling_node.cpp @@ -70,7 +70,7 @@ void ArrayCullingNode::validateUpdate(mutablebson::ConstElement updatedElement, // override validateUpdate to not validate storage constraints but we still want to know if // there is any field name containing '.'/'$'. bool doRecursiveCheck = true; - storage_validation::storageValid(updatedElement, + storage_validation::scanDocument(updatedElement, doRecursiveCheck, recursionLevel, false, /* allowTopLevelDollarPrefixedFields */ diff --git a/src/mongo/db/update/modifier_node.cpp b/src/mongo/db/update/modifier_node.cpp index c8c3327cc82..d1872b411ac 100644 --- a/src/mongo/db/update/modifier_node.cpp +++ b/src/mongo/db/update/modifier_node.cpp @@ -375,7 +375,7 @@ void ModifierNode::validateUpdate(mutablebson::ConstElement updatedElement, bool* containsDotsAndDollarsField) const { const bool doRecursiveCheck = true; - storage_validation::storageValid(updatedElement, + storage_validation::scanDocument(updatedElement, doRecursiveCheck, recursionLevel, false, /* allowTopLevelDollarPrefixedFields */ diff --git a/src/mongo/db/update/modifier_node.h b/src/mongo/db/update/modifier_node.h index 53ec3e7f375..42bb70ee336 100644 --- a/src/mongo/db/update/modifier_node.h +++ b/src/mongo/db/update/modifier_node.h @@ -103,7 +103,7 @@ protected: /** * ModifierNode::apply() calls this method after it finishes applying its update to validate * that no changes resulted in an invalid document. See the implementation of - * storage_validation::storageValid() for more detail about document validation requirements. + * storage_validation::scanDocument() for more detail about document validation requirements. * Most ModifierNode child classes can use the default implementation of this method. * * - 'updatedElement' is the element that was set by either updateExistingElement() or diff --git a/src/mongo/db/update/object_replace_executor.cpp b/src/mongo/db/update/object_replace_executor.cpp index 22af1870f62..e2d9262e001 100644 --- a/src/mongo/db/update/object_replace_executor.cpp +++ b/src/mongo/db/update/object_replace_executor.cpp @@ -105,11 +105,14 @@ UpdateExecutor::ApplyResult ObjectReplaceExecutor::applyReplacementUpdate( ApplyResult ret; - // Validate for storage and check if the document contains any '.'/'$' field name. - storage_validation::storageValid(applyParams.element.getDocument(), - allowTopLevelDollarPrefixedFields, - applyParams.validateForStorage, - &ret.containsDotsAndDollarsField); + if (!applyParams.skipDotsDollarsCheck || applyParams.validateForStorage) { + // Validate for storage and check if the document contains any '.'/'$' field name. We pass + // 'containsDotsAndDollarsField' unconditionally for now. + storage_validation::scanDocument(applyParams.element.getDocument(), + allowTopLevelDollarPrefixedFields, + applyParams.validateForStorage, + &ret.containsDotsAndDollarsField); + } // Check immutable paths. for (auto path = applyParams.immutablePaths.begin(); path != applyParams.immutablePaths.end(); diff --git a/src/mongo/db/update/pop_node.cpp b/src/mongo/db/update/pop_node.cpp index c15f26fe790..c7942a32aa9 100644 --- a/src/mongo/db/update/pop_node.cpp +++ b/src/mongo/db/update/pop_node.cpp @@ -82,7 +82,7 @@ void PopNode::validateUpdate(mutablebson::ConstElement updatedElement, // override validateUpdate to not validate storage constraints but we still want to know if // there is any field name containing '.'/'$'. bool doRecursiveCheck = true; - storage_validation::storageValid(updatedElement, + storage_validation::scanDocument(updatedElement, doRecursiveCheck, recursionLevel, false, /* allowTopLevelDollarPrefixedFields */ diff --git a/src/mongo/db/update/storage_validation.cpp b/src/mongo/db/update/storage_validation.cpp index 3e04bf45f35..d94c645a588 100644 --- a/src/mongo/db/update/storage_validation.cpp +++ b/src/mongo/db/update/storage_validation.cpp @@ -44,7 +44,7 @@ namespace { const StringData idFieldName = "_id"_sd; -void storageValidChildren(mutablebson::ConstElement elem, +void scanDocumentChildren(mutablebson::ConstElement elem, const bool deep, std::uint32_t recursionLevel, const bool allowTopLevelDollarPrefixes, @@ -56,7 +56,7 @@ void storageValidChildren(mutablebson::ConstElement elem, auto curr = elem.leftChild(); while (curr.ok()) { - storageValid(curr, + scanDocument(curr, deep, recursionLevel + 1, allowTopLevelDollarPrefixes, @@ -153,7 +153,7 @@ Status storageValidIdField(const mongo::BSONElement& element) { return Status::OK(); } -void storageValid(const mutablebson::Document& doc, +void scanDocument(const mutablebson::Document& doc, const bool allowTopLevelDollarPrefixes, const bool shouldValidate, bool* containsDotsAndDollarsField) { @@ -166,7 +166,7 @@ void storageValid(const mutablebson::Document& doc, // Validate this child element. const auto deep = true; const uint32_t recursionLevel = 1; - storageValid(currElem, + scanDocument(currElem, deep, recursionLevel, allowTopLevelDollarPrefixes, @@ -177,7 +177,7 @@ void storageValid(const mutablebson::Document& doc, } } -void storageValid(mutablebson::ConstElement elem, +void scanDocument(mutablebson::ConstElement elem, const bool deep, std::uint32_t recursionLevel, const bool allowTopLevelDollarPrefixes, @@ -223,7 +223,7 @@ void storageValid(mutablebson::ConstElement elem, if (deep) { // Check children if there are any. - storageValidChildren(elem, + scanDocumentChildren(elem, deep, recursionLevel, allowTopLevelDollarPrefixes, diff --git a/src/mongo/db/update/storage_validation.h b/src/mongo/db/update/storage_validation.h index 381abf66a9b..c1ce7e5a951 100644 --- a/src/mongo/db/update/storage_validation.h +++ b/src/mongo/db/update/storage_validation.h @@ -42,12 +42,11 @@ namespace storage_validation { Status storageValidIdField(const mongo::BSONElement& element); /** - * Validates that the MutableBSON document 'doc' is acceptable for storage in a collection. The - * check is performed recursively on subdocuments. Uasserts if the validation fails or if the depth - * exceeds the maximum allowable depth. - * - * If 'allowTopLevelDollarPrefixes' is set to false, reject $-prefixed fields at the top-level of a - document. + * Validates that the MutableBSON document 'doc' is acceptable for storage in a collection and + * checks if there exists any field name containing '.'/'$'. The check is performed recursively on + * subdocuments. Uasserts if the validation fails or if the depth exceeds the maximum allowable + * depth. If 'allowTopLevelDollarPrefixes' is set to false, reject $-prefixed fields at the + * top-level of a document. * 'shouldValidate' is true if the caller wants to validate for storage, otherwise this helper will * only check top-level $-prefixed field names skipping all the validations. @@ -55,15 +54,16 @@ Status storageValidIdField(const mongo::BSONElement& element); * 'containsDotsAndDollarsField' is set to true if there exists any field name containing '.'/'$' * during validation. */ -void storageValid(const mutablebson::Document& doc, +void scanDocument(const mutablebson::Document& doc, bool allowTopLevelDollarPrefixes, bool shouldValidate, bool* containsDotsAndDollarsField); /** - * Validates that the MutableBSON element 'elem' is acceptable for storage in a collection. If - * 'deep' is true, the check is performed recursively on subdocuments. Uasserts if the validation - * fails or if 'recursionLevel' exceeds the maximum allowable depth. + * Validates that the MutableBSON element 'elem' is acceptable for storage in a collection and + * checks if there exists any field name containing '.'/'$'. If 'deep' is true, the check is + * performed recursively on subdocuments. Uasserts if the validation fails or if 'recursionLevel' + * exceeds the maximum allowable depth. * * If 'allowTopLevelDollarPrefixes' is set to false, reject $-prefixed fields at the top-level of a * document. @@ -74,7 +74,7 @@ void storageValid(const mutablebson::Document& doc, * 'containsDotsAndDollarsField' is set to true if there exists any field name containing '.'/'$' * during validation. */ -void storageValid(mutablebson::ConstElement elem, +void scanDocument(mutablebson::ConstElement elem, bool deep, std::uint32_t recursionLevel, bool allowTopLevelDollarPrefixes, diff --git a/src/mongo/db/update/unset_node.cpp b/src/mongo/db/update/unset_node.cpp index 75612dba4be..be814cc73d1 100644 --- a/src/mongo/db/update/unset_node.cpp +++ b/src/mongo/db/update/unset_node.cpp @@ -72,7 +72,7 @@ void UnsetNode::validateUpdate(mutablebson::ConstElement updatedElement, const uint32_t recursionLevelForCheck = 0; if (leftSibling.ok()) { - storage_validation::storageValid(leftSibling, + storage_validation::scanDocument(leftSibling, doRecursiveCheck, recursionLevelForCheck, false, /* allowTopLevelDollarPrefixedFields */ @@ -81,7 +81,7 @@ void UnsetNode::validateUpdate(mutablebson::ConstElement updatedElement, } if (rightSibling.ok()) { - storage_validation::storageValid(rightSibling, + storage_validation::scanDocument(rightSibling, doRecursiveCheck, recursionLevelForCheck, false, /* allowTopLevelDollarPrefixedFields */ diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp index 2dd809aa99b..0df3cf38098 100644 --- a/src/mongo/db/update/update_driver.cpp +++ b/src/mongo/db/update/update_driver.cpp @@ -271,6 +271,7 @@ Status UpdateDriver::update(OperationContext* opCtx, applyParams.matchedField = matchedField; applyParams.insert = isInsert; applyParams.fromOplogApplication = _fromOplogApplication; + applyParams.skipDotsDollarsCheck = _skipDotsDollarsCheck; applyParams.validateForStorage = validateForStorage; applyParams.indexData = _indexedFields; applyParams.modifiedPaths = modifiedPaths; diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h index 96f34b4cfaf..0f3fb02f455 100644 --- a/src/mongo/db/update/update_driver.h +++ b/src/mongo/db/update/update_driver.h @@ -174,6 +174,10 @@ public: _fromOplogApplication = fromOplogApplication; } + void setSkipDotsDollarsCheck(bool skipDotsDollarsCheck) { + _skipDotsDollarsCheck = skipDotsDollarsCheck; + } + mutablebson::Document& getDocument() { return _objDoc; } @@ -237,6 +241,10 @@ private: // True if this update comes from an oplog application. bool _fromOplogApplication = false; + // True if this update is guaranteed not to contain dots or dollars fields and should skip the + // check. + bool _skipDotsDollarsCheck = false; + boost::intrusive_ptr<ExpressionContext> _expCtx; // Are any of the fields mentioned in the mods participating in any index? Is set anew diff --git a/src/mongo/db/update/update_executor.h b/src/mongo/db/update/update_executor.h index a7ef7dd0837..539f044432b 100644 --- a/src/mongo/db/update/update_executor.h +++ b/src/mongo/db/update/update_executor.h @@ -86,6 +86,10 @@ public: // replication. bool fromOplogApplication = false; + // If true, it is guaranteed that the document doesn't contain dots or dollars fields and + // should skip the check. + bool skipDotsDollarsCheck = false; + // If true, UpdateNode::apply ensures that modified elements do not violate depth or DBRef // constraints. bool validateForStorage = true; |