void ProjectionSpecValidator::parseElement(const BSONElement& elem, const FieldPath& pathToElem) { if (elem.type() == BSONType::Object) { parseNestedObject(elem.Obj(), pathToElem); } else { ensurePathDoesNotConflictOrThrow(pathToElem.fullPath()); } }
void ExclusionNode::excludePath(FieldPath path) { if (path.getPathLength() == 1) { _excludedFields.insert(path.fullPath()); return; } addOrGetChild(path.getFieldName(0))->excludePath(path.tail()); }
void ProjectionNode::addProjectionForPath(const FieldPath& path) { if (path.getPathLength() == 1) { _projectedFields.insert(path.fullPath()); return; } // FieldPath can't be empty, so it is safe to obtain the first path component here. addOrGetChild(path.getFieldName(0).toString())->addProjectionForPath(path.tail()); }
void ProjectionNode::addExpressionForPath(const FieldPath& path, boost::intrusive_ptr<Expression> expr) { // If the computed fields policy is 'kBanComputedFields', we should never reach here. invariant(_policies.computedFieldsPolicy == ComputedFieldsPolicy::kAllowComputedFields); if (path.getPathLength() == 1) { auto fieldName = path.fullPath(); _expressions[fieldName] = expr; _orderToProcessAdditionsAndChildren.push_back(fieldName); return; } // FieldPath can't be empty, so it is safe to obtain the first path component here. addOrGetChild(path.getFieldName(0).toString())->addExpressionForPath(path.tail(), expr); }
void ProjectionSpecValidator::parseNestedObject(const BSONObj& thisLevelSpec, const FieldPath& prefix) { if (thisLevelSpec.isEmpty()) { uasserted( 40180, str::stream() << "an empty object is not a valid value. Found empty object at path " << prefix.fullPath()); } for (auto&& elem : thisLevelSpec) { auto fieldName = elem.fieldNameStringData(); if (fieldName[0] == '$') { // This object is an expression specification like {$add: [...]}. It will be parsed // into an Expression later, but for now, just track that the prefix has been // specified and skip it. if (thisLevelSpec.nFields() != 1) { uasserted(40181, str::stream() << "an expression specification must contain exactly " "one field, the name of the expression. Found " << thisLevelSpec.nFields() << " fields in " << thisLevelSpec.toString() << ", while parsing object " << _rawObj.toString()); } ensurePathDoesNotConflictOrThrow(prefix.fullPath()); continue; } if (fieldName.find('.') != std::string::npos) { uasserted(40183, str::stream() << "cannot use dotted field name '" << fieldName << "' in a sub object: " << _rawObj.toString()); } parseElement(elem, FieldPath::getFullyQualifiedPath(prefix.fullPath(), fieldName)); } }