void ExclusionNode::excludePath(FieldPath path) {
    if (path.getPathLength() == 1) {
        _excludedFields.insert(path.fullPath());
        return;
    }
    addOrGetChild(path.getFieldName(0))->excludePath(path.tail());
}
Beispiel #2
0
    static Value getNestedFieldHelper(const Document& doc,
                                      const FieldPath& fieldNames,
                                      vector<Position>* positions,
                                      size_t level) {

        fassert(16489, fieldNames.getPathLength());

        const string& fieldName = fieldNames.getFieldName(level);
        const Position pos = doc.positionOf(fieldName);

        if (!pos.found())
            return Value();

        if (positions)
            positions->push_back(pos);

        if (level == fieldNames.getPathLength()-1)
            return doc.getField(pos);

        Value val = doc.getField(pos);
        if (val.getType() != Object)
            return Value();

        return getNestedFieldHelper(val.getDocument(), fieldNames, positions, level+1);
    }
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());
}
Beispiel #4
0
MutableValue MutableDocument::getNestedFieldHelper(const FieldPath& dottedField, size_t level) {
    if (level == dottedField.getPathLength() - 1) {
        return getField(dottedField.getFieldName(level));
    } else {
        MutableDocument nested(getField(dottedField.getFieldName(level)));
        return nested.getNestedFieldHelper(dottedField, level + 1);
    }
}
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::parseElement(const BSONElement& elem, const FieldPath& pathToElem) {
    if (elem.type() == BSONType::Object) {
        parseNestedObject(elem.Obj(), pathToElem);
    } else {
        ensurePathDoesNotConflictOrThrow(pathToElem.fullPath());
    }
}
Beispiel #7
0
    void DependencyTracker::removeDependency(const FieldPath &rFieldPath) {
        const size_t nErased = map.erase(rFieldPath);

        DEV {
            (log() << "\n---- DependencyTracker::removeDependency(" <<
             rFieldPath.getPath(false) << ") -> " << nErased << "\n").flush();
        }
    }
Beispiel #8
0
    void DependencyTracker::reportUnsatisfied(
        const FieldPath &rPath,
        const DocumentSource *pNeeds,
        const DocumentSource *pExcludes) {

        uassert(15984, str::stream() <<
                "unable to satisfy dependency on " <<
                rPath.getPath(true) << " in pipeline[" <<
                pNeeds->getPipelineStep() << "]." <<
                pNeeds->getSourceName() << ", because pipeline[" <<
                pExcludes->getPipelineStep() << "]." <<
                pExcludes->getSourceName() << "] doesn't include it",
                false); // printf() is way easier to read than this crap
    }
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));
    }
}
Beispiel #10
0
    void DependencyTracker::addDependency(
        const FieldPath &rFieldPath, const DocumentSource *pSource) {
        Tracker tracker(rFieldPath, pSource);
        std::pair<MapType::iterator, bool> p(
            map.insert(std::pair<FieldPath, Tracker>(rFieldPath, tracker)));

        /*
          If there was already an entry, update the dependency to be the more
          recent source.
        */
        if (!p.second)
            (*p.first).second.pSource = pSource;

        DEV {
            (log() << "\n---- DependencyTracker::addDependency(" <<
             rFieldPath.getPath(false) << ", pipeline[" <<
             pSource->getPipelineStep() << "]." <<
             pSource->getSourceName() << ")").flush();
        }
    }
Beispiel #11
0
 const Value Document::getNestedField(const FieldPath& fieldNames,
                                      vector<Position>* positions) const {
     fassert(16489, fieldNames.getPathLength());
     return getNestedFieldHelper(*this, fieldNames, positions, 0);
 }
Beispiel #12
0
 MutableValue MutableDocument::getNestedField(const FieldPath& dottedField) {
     fassert(16601, dottedField.getPathLength());
     return getNestedFieldHelper(dottedField, 0);
 }
Beispiel #13
0
 size_t DependencyTracker::Tracker::Hash::operator()(
     const FieldPath &rFieldPath) const {
     size_t seed = 0xf0afbeef;
     rFieldPath.hash_combine(seed);
     return seed;
 }
Beispiel #14
0
 void run() {
     FieldPath path = FieldPath("foo.bar.baz").tail();
     ASSERT_EQUALS(2U, path.getPathLength());
     ASSERT_EQUALS("bar.baz", path.getPath(false));
 }