Status _initializeUserRolesFromV1RolesArray(User* user,
                                                const BSONElement& rolesElement,
                                                const StringData& dbname) {
        static const char privilegesTypeMismatchMessage[] =
                "Roles in V1 user documents must be enumerated in an array of strings.";

        if (rolesElement.type() != Array)
            return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);

        for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
            BSONElement roleElement = *iter;
            if (roleElement.type() != String)
                return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);

            user->addRole(RoleName(roleElement.String(), dbname));
        }
        return Status::OK();
    }
Beispiel #2
0
void DBConfig::unserialize(const BSONObj& from) {
    _name = from.getStringField("name");
    _partitioned = from.getBoolField("partitioned");
    _primary = from.getStringField("primary");

    _sharded.clear();
    BSONObj sharded = from.getObjectField( "sharded" );
    if ( ! sharded.isEmpty() ) {
        BSONObjIterator i(sharded);
        while ( i.more() ) {
            BSONElement e = i.next();
            if ( e.eoo() )
                break;
            uassert( "shared things have to be objects" , e.type() == Object );
            _sharded[e.fieldName()] = e.embeddedObject();
        }
    }
}
Beispiel #3
0
bool GeoNearExpression::parseLegacyQuery(const BSONObj& obj) {
    bool hasGeometry = false;

    // First, try legacy near, e.g.:
    // t.find({ loc : { $nearSphere: [0,0], $minDistance: 1, $maxDistance: 3 }})
    // t.find({ loc : { $nearSphere: [0,0] }})
    // t.find({ loc : { $near : [0, 0, 1] } });
    // t.find({ loc : { $near: { someGeoJSONPoint}})
    // t.find({ loc : { $geoNear: { someGeoJSONPoint}})
    BSONObjIterator it(obj);
    while (it.more()) {
        BSONElement e = it.next();
        if (equals(e.fieldName(), "$near") || equals(e.fieldName(), "$geoNear") ||
            equals(e.fieldName(), "$nearSphere")) {
            if (!e.isABSONObj()) {
                return false;
            }
            BSONObj embeddedObj = e.embeddedObject();

            if (GeoParser::parseQueryPoint(e, centroid.get()).isOK() ||
                GeoParser::parsePointWithMaxDistance(embeddedObj, centroid.get(), &maxDistance)) {
                uassert(18522, "max distance must be non-negative", maxDistance >= 0.0);
                hasGeometry = true;
                isNearSphere = equals(e.fieldName(), "$nearSphere");
            }
        } else if (equals(e.fieldName(), "$minDistance")) {
            uassert(16893, "$minDistance must be a number", e.isNumber());
            minDistance = e.Number();
            uassert(16894, "$minDistance must be non-negative", minDistance >= 0.0);
        } else if (equals(e.fieldName(), "$maxDistance")) {
            uassert(16895, "$maxDistance must be a number", e.isNumber());
            maxDistance = e.Number();
            uassert(16896, "$maxDistance must be non-negative", maxDistance >= 0.0);
        } else if (equals(e.fieldName(), "$uniqueDocs")) {
            warning() << "ignoring deprecated option $uniqueDocs";
        } else {
            // In a query document, $near queries can have no non-geo sibling parameters.
            uasserted(34413,
                      str::stream() << "invalid argument in geo near query: " << e.fieldName());
        }
    }

    return hasGeometry;
}
intrusive_ptr<DocumentSource> DocumentSourceCollStats::createFromBson(
    BSONElement specElem, const intrusive_ptr<ExpressionContext>& pExpCtx) {
    uassert(40166,
            str::stream() << "$collStats must take a nested object but found: " << specElem,
            specElem.type() == BSONType::Object);
    intrusive_ptr<DocumentSourceCollStats> collStats(new DocumentSourceCollStats(pExpCtx));

    for (const auto& elem : specElem.embeddedObject()) {
        StringData fieldName = elem.fieldNameStringData();

        if ("latencyStats" == fieldName) {
            uassert(40167,
                    str::stream() << "latencyStats argument must be an object, but got " << elem
                                  << " of type "
                                  << typeName(elem.type()),
                    elem.type() == BSONType::Object);
            if (!elem["histograms"].eoo()) {
                uassert(40305,
                        str::stream() << "histograms option to latencyStats must be bool, got "
                                      << elem
                                      << "of type "
                                      << typeName(elem.type()),
                        elem["histograms"].isBoolean());
            }
        } else if ("storageStats" == fieldName) {
            uassert(40279,
                    str::stream() << "storageStats argument must be an object, but got " << elem
                                  << " of type "
                                  << typeName(elem.type()),
                    elem.type() == BSONType::Object);
        } else if ("count" == fieldName) {
            uassert(40480,
                    str::stream() << "count argument must be an object, but got " << elem
                                  << " of type "
                                  << typeName(elem.type()),
                    elem.type() == BSONType::Object);
        } else {
            uasserted(40168, str::stream() << "unrecognized option to $collStats: " << fieldName);
        }
    }

    collStats->_collStatsSpec = specElem.Obj().getOwned();
    return collStats;
}
Status ModifierObjectReplace::init(const BSONElement& modExpr,
                                   const Options& opts,
                                   bool* positional) {
    if (modExpr.type() != Object) {
        // Impossible, really since the caller check this already...
        return Status(ErrorCodes::BadValue,
                      str::stream() << "Document replacement expects a complete document"
                                       " but the type supplied was " << modExpr.type());
    }

    // Object replacements never have positional operator.
    if (positional)
        *positional = false;

    // We make a copy of the object here because the update driver does not guarantees, in
    // the case of object replacement, that the modExpr is going to outlive this mod.
    _val = modExpr.embeddedObject().getOwned();
    return fixupTimestamps(_val);
}
Beispiel #6
0
 void DBConfig::unserialize(const BSONObj& from){
     _name = from.getStringField("name");
     _shardingEnabled = from.getBoolField("partitioned");
     _primary = from.getStringField("primary");
     
     _sharded.clear();
     BSONObj sharded = from.getObjectField( "sharded" );
     if ( ! sharded.isEmpty() ){
         BSONObjIterator i(sharded);
         while ( i.more() ){
             BSONElement e = i.next();
             uassert( 10182 ,  "sharded things have to be objects" , e.type() == Object );
             BSONObj c = e.embeddedObject();
             uassert( 10183 ,  "key has to be an object" , c["key"].type() == Object );
             _sharded[e.fieldName()] = CollectionInfo( c["key"].embeddedObject() , 
                                                       c["unique"].trueValue() );
         }
     }
 }
boost::intrusive_ptr<DocumentSource> DocumentSourceInternalSplitPipeline::createFromBson(
    BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
    uassert(ErrorCodes::TypeMismatch,
            str::stream() << "$_internalSplitPipeline must take a nested object but found: "
                          << elem,
            elem.type() == BSONType::Object);

    auto specObj = elem.embeddedObject();

    HostTypeRequirement mergeType = HostTypeRequirement::kNone;

    for (auto&& elt : specObj) {
        if (elt.fieldNameStringData() == "mergeType"_sd) {
            uassert(ErrorCodes::BadValue,
                    str::stream() << "'mergeType' must be a string value but found: " << elt.type(),
                    elt.type() == BSONType::String);

            auto mergeTypeString = elt.valueStringData();

            if ("localOnly"_sd == mergeTypeString) {
                mergeType = HostTypeRequirement::kLocalOnly;
            } else if ("anyShard"_sd == mergeTypeString) {
                mergeType = HostTypeRequirement::kAnyShard;
            } else if ("primaryShard"_sd == mergeTypeString) {
                mergeType = HostTypeRequirement::kPrimaryShard;
            } else if ("mongos"_sd == mergeTypeString) {
                mergeType = HostTypeRequirement::kMongoS;
            } else {
                uasserted(ErrorCodes::BadValue,
                          str::stream() << "unrecognized field while parsing mergeType: '"
                                        << elt.fieldNameStringData()
                                        << "'");
            }
        } else {
            uasserted(ErrorCodes::BadValue,
                      str::stream() << "unrecognized field while parsing $_internalSplitPipeline: '"
                                    << elt.fieldNameStringData()
                                    << "'");
        }
    }

    return new DocumentSourceInternalSplitPipeline(expCtx, mergeType);
}
Beispiel #8
0
    void BSONElementHasher::recursiveHash( Hasher* h ,
                                           const BSONElement& e ,
                                           bool includeFieldName ) {

        int canonicalType = e.canonicalType();
        h->addData( &canonicalType , sizeof( canonicalType ) );

        if ( includeFieldName ){
            h->addData( e.fieldName() , e.fieldNameSize() );
        }

        if ( !e.mayEncapsulate() ){
            //if there are no embedded objects (subobjects or arrays),
            //compute the hash, squashing numeric types to 64-bit ints
            if ( e.isNumber() ){
                long long int i = e.safeNumberLong(); //well-defined for troublesome doubles
                h->addData( &i , sizeof( i ) );
            }
            else {
                h->addData( e.value() , e.valuesize() );
            }
        }
        else {
            //else identify the subobject.
            //hash any preceding stuff (in the case of codeWscope)
            //then each sub-element
            //then finish with the EOO element.
            BSONObj b;
            if ( e.type() == CodeWScope ) {
                h->addData( e.codeWScopeCode() , e.codeWScopeCodeLen() );
                b = e.codeWScopeObject();
            }
            else {
                b = e.embeddedObject();
            }
            BSONObjIterator i(b);
            while( i.moreWithEOO() ) {
                BSONElement el = i.next();
                recursiveHash( h , el ,  true );
            }
        }
    }
    boost::optional<Document> DocumentSourceCommandShards::getNext() {
        pExpCtx->checkForInterrupt();

        while(true) {
            if (!pBsonSource.get()) {
                /* if there aren't any more futures, we're done */
                if (iterator == listEnd)
                    return boost::none;

                /* grab the next command result */
                BSONObj resultObj = iterator->result;

                uassert(16390, str::stream() << "sharded pipeline failed on shard " <<
                                            iterator->shardTarget.getName() << ": " <<
                                            resultObj.toString(),
                        resultObj["ok"].trueValue());

                /* grab the result array out of the shard server's response */
                BSONElement resultArray = resultObj["result"];
                massert(16391, str::stream() << "no result array? shard:" <<
                                            iterator->shardTarget.getName() << ": " <<
                                            resultObj.toString(),
                        resultArray.type() == Array);

                // done with error checking, don't need the shard name anymore
                ++iterator;

                if (resultArray.embeddedObject().isEmpty()){
                    // this shard had no results, on to the next one
                    continue;
                }

                pBsonSource = DocumentSourceBsonArray::create(&resultArray, pExpCtx);
            }

            if (boost::optional<Document> out = pBsonSource->getNext())
                return out;

            // Source exhausted. Try next.
            pBsonSource.reset();
        }
    }
    Status LiteParsedQuery::init(const string& ns, int ntoskip, int ntoreturn, int queryOptions,
                                 const BSONObj& queryObj, const BSONObj& proj,
                                 bool fromQueryMessage) {
        _ns = ns;
        _ntoskip = ntoskip;
        _ntoreturn = ntoreturn;
        _options = queryOptions;
        _proj = proj.getOwned();

        if (_ntoskip < 0) {
            return Status(ErrorCodes::BadValue, "bad skip value in query");
        }
        
        if (_ntoreturn < 0) {
            // _ntoreturn greater than zero is simply a hint on how many objects to send back per
            // "cursor batch".  A negative number indicates a hard limit.
            _wantMore = false;
            _ntoreturn = -_ntoreturn;
        }

        if (fromQueryMessage) {
            BSONElement queryField = queryObj["query"];
            if (!queryField.isABSONObj()) { queryField = queryObj["$query"]; }
            if (queryField.isABSONObj()) {
                _filter = queryField.embeddedObject().getOwned();
                Status status = initFullQuery(queryObj);
                if (!status.isOK()) { return status; }
            }
            else {
                // TODO: Does this ever happen?
                _filter = queryObj.getOwned();
            }
        }
        else {
            // This is the debugging code path.
            _filter = queryObj.getOwned();
        }

        _hasReadPref = queryObj.hasField("$readPreference");

        return Status::OK();
    }
Beispiel #11
0
 static bool isLegacyCenterSphere(const BSONObj &obj) {
     BSONObjIterator typeIt(obj);
     BSONElement type = typeIt.next();
     if (!type.isABSONObj()) { return false; }
     bool isCenterSphere = mongoutils::str::equals(type.fieldName(), "$centerSphere");
     if (!isCenterSphere) { return false; }
     BSONObjIterator objIt(type.embeddedObject());
     BSONElement center = objIt.next();
     if (!center.isABSONObj()) { return false; }
     if (!isLegacyPoint(center.Obj())) { return false; }
     // Check to make sure the points are valid lng/lat.
     BSONObjIterator coordIt(center.Obj());
     BSONElement lng = coordIt.next();
     BSONElement lat = coordIt.next();
     if (!isValidLngLat(lng.Number(), lat.Number())) { return false; }
     if (!objIt.more()) { return false; }
     BSONElement radius = objIt.next();
     if (!radius.isNumber()) { return false; }
     return true;
 }
Beispiel #12
0
 bool GeoParser::parsePolygon(const BSONObj &obj, PolygonWithCRS *out) {
     if (isGeoJSONPolygon(obj)) {
         const vector<BSONElement>& coordinates = obj.getFieldDotted(GEOJSON_COORDINATES).Array();
         if (!parseGeoJSONPolygonCoordinates(coordinates, obj, &out->polygon)) { return false; }
         out->crs = SPHERE;
     } else {
         BSONObjIterator typeIt(obj);
         BSONElement type = typeIt.next();
         BSONObjIterator coordIt(type.embeddedObject());
         vector<Point> points;
         while (coordIt.more()) {
             Point p;
             if (!parseLegacyPoint(coordIt.next().Obj(), &p)) { return false; }
             points.push_back(p);
         }
         out->oldPolygon = Polygon(points);
         out->crs = FLAT;
     }
     return true;
 }
Beispiel #13
0
 BSONElement BSONObj::getFieldDottedOrArray(const char *&name) const {
     const char *p = strchr(name, '.');
     string left;
     if ( p ) {
         left = string(name, p-name);
         name = p + 1;
     } else {
         left = string(name);
         name = name + strlen(name);
     }
     BSONElement sub = getField(left.c_str());
     if ( sub.eoo() )
         return nullElement;
     else if ( sub.type() == Array || strlen( name ) == 0 )
         return sub;
     else if ( sub.type() == Object )
         return sub.embeddedObject().getFieldDottedOrArray( name );
     else
         return nullElement;
 }
Beispiel #14
0
    Status Command::parseCommandCursorOptions(const BSONObj& cmdObj,
                                              long long defaultBatchSize,
                                              long long* batchSize) {
        invariant(batchSize);
        *batchSize = defaultBatchSize;

        BSONElement cursorElem = cmdObj["cursor"];
        if (cursorElem.eoo()) {
            return Status::OK();
        }

        if (cursorElem.type() != mongo::Object) {
            return Status(ErrorCodes::TypeMismatch, "cursor field must be missing or an object");
        }

        BSONObj cursor = cursorElem.embeddedObject();
        BSONElement batchSizeElem = cursor["batchSize"];

        const int expectedNumberOfCursorFields = batchSizeElem.eoo() ? 0 : 1;
        if (cursor.nFields() != expectedNumberOfCursorFields) {
            return Status(ErrorCodes::BadValue,
                          "cursor object can't contain fields other than batchSize");
        }

        if (batchSizeElem.eoo()) {
            return Status::OK();
        }

        if (!batchSizeElem.isNumber()) {
            return Status(ErrorCodes::TypeMismatch, "cursor.batchSize must be a number");
        }

        // This can change in the future, but for now all negatives are reserved.
        if (batchSizeElem.numberLong() < 0) {
            return Status(ErrorCodes::BadValue, "cursor.batchSize must not be negative");
        }

        *batchSize = batchSizeElem.numberLong();

        return Status::OK();
    }
Beispiel #15
0
bool NearQuery::parseLegacyQuery(const BSONObj &obj) {

    bool hasGeometry = false;

    // First, try legacy near, e.g.:
    // t.find({ loc : { $nearSphere: [0,0], $minDistance: 1, $maxDistance: 3 }})
    // t.find({ loc : { $nearSphere: [0,0] }})
    // t.find({ loc : { $near : [0, 0, 1] } });
    // t.find({ loc : { $near: { someGeoJSONPoint}})
    // t.find({ loc : { $geoNear: { someGeoJSONPoint}})
    BSONObjIterator it(obj);
    while (it.more()) {
        BSONElement e = it.next();
        if (equals(e.fieldName(), "$near") || equals(e.fieldName(), "$geoNear")
                || equals(e.fieldName(), "$nearSphere")) {
            if (!e.isABSONObj()) {
                return false;
            }
            BSONObj embeddedObj = e.embeddedObject();

            if ((GeoParser::isPoint(embeddedObj) && GeoParser::parsePoint(embeddedObj, &centroid))
                    || GeoParser::parsePointWithMaxDistance(embeddedObj, &centroid, &maxDistance)) {
                uassert(18522, "max distance must be non-negative", maxDistance >= 0.0);
                hasGeometry = true;
                isNearSphere = equals(e.fieldName(), "$nearSphere");
            }
        } else if (equals(e.fieldName(), "$minDistance")) {
            uassert(16893, "$minDistance must be a number", e.isNumber());
            minDistance = e.Number();
            uassert(16894, "$minDistance must be non-negative", minDistance >= 0.0);
        } else if (equals(e.fieldName(), "$maxDistance")) {
            uassert(16895, "$maxDistance must be a number", e.isNumber());
            maxDistance = e.Number();
            uassert(16896, "$maxDistance must be non-negative", maxDistance >= 0.0);
        } else if (equals(e.fieldName(), "$uniqueDocs")) {
            warning() << "ignoring deprecated option $uniqueDocs";
        }
    }

    return hasGeometry;
}
Beispiel #16
0
    void Chunk::unserialize(const BSONObj& from){
        _ns = from.getStringField( "ns" );
        _shard = from.getStringField( "shard" );
        _lastmod = from.hasField( "lastmod" ) ? from["lastmod"]._numberLong() : 0;

        BSONElement e = from["minDotted"];
        cout << from << endl;
        if (e.eoo()){
            _min = from.getObjectField( "min" ).getOwned();
            _max = from.getObjectField( "max" ).getOwned();
        } else { // TODO delete this case after giving people a chance to migrate
            _min = e.embeddedObject().getOwned();
            _max = from.getObjectField( "maxDotted" ).getOwned();
        }
        
        uassert( 10170 ,  "Chunk needs a ns" , ! _ns.empty() );
        uassert( 10171 ,  "Chunk needs a server" , ! _ns.empty() );

        uassert( 10172 ,  "Chunk needs a min" , ! _min.isEmpty() );
        uassert( 10173 ,  "Chunk needs a max" , ! _max.isEmpty() );
    }
Beispiel #17
0
    static bool _hasShardKey(const BSONObj& doc,
                             const set<string>& patternFields,
                             bool allowRegex) {

        // this is written s.t. if doc has lots of fields, if the shard key fields are early,
        // it is fast.  so a bit more work to try to be semi-fast.

        for (set<string>::const_iterator it = patternFields.begin(); it != patternFields.end();
            ++it) {
            BSONElement shardKeyField = doc.getFieldDotted(it->c_str());
            if (shardKeyField.eoo()
                || shardKeyField.type() == Array
                || (!allowRegex && shardKeyField.type() == RegEx)
                || (shardKeyField.type() == Object &&
                    !shardKeyField.embeddedObject().okForStorage())) {
                // Don't allow anything for a shard key we can't store -- like $gt/$lt ops
                return false;
            }
        }
        return true;
    }
Beispiel #18
0
FieldParser::FieldState FieldParser::extract(BSONElement elem,
                                             const BSONField<BSONArray>& field,
                                             BSONArray* out,
                                             string* errMsg) {
    if (elem.eoo()) {
        if (field.hasDefault()) {
            *out = field.getDefault();
            return FIELD_DEFAULT;
        } else {
            return FIELD_NONE;
        }
    }

    if (elem.type() == Array) {
        *out = BSONArray(elem.embeddedObject().getOwned());
        return FIELD_SET;
    }

    _genFieldErrMsg(elem, field, "array", errMsg);
    return FIELD_INVALID;
}
Beispiel #19
0
StatusWithMatchExpression JSONSchemaParser::_parseProperties(StringData path,
                                                             BSONElement propertiesElt,
                                                             TypeMatchExpression* typeExpr) {
    if (propertiesElt.type() != BSONType::Object) {
        return {Status(ErrorCodes::TypeMismatch,
                       str::stream() << "$jsonSchema keyword '" << kSchemaPropertiesKeyword
                                     << "' must be an object")};
    }
    auto propertiesObj = propertiesElt.embeddedObject();

    auto andExpr = stdx::make_unique<AndMatchExpression>();
    for (auto&& property : propertiesObj) {
        if (property.type() != BSONType::Object) {
            return {ErrorCodes::TypeMismatch,
                    str::stream() << "Nested schema for $jsonSchema property '"
                                  << property.fieldNameStringData()
                                  << "' must be an object"};
        }

        auto nestedSchemaMatch = _parse(property.fieldNameStringData(), property.embeddedObject());
        if (!nestedSchemaMatch.isOK()) {
            return nestedSchemaMatch.getStatus();
        }
        andExpr->add(nestedSchemaMatch.getValue().release());
    }

    // If this is a top-level schema, then we have no path and there is no need for an
    // explicit object match node.
    if (path.empty()) {
        return {std::move(andExpr)};
    }

    auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>();
    auto objectMatchStatus = objectMatch->init(std::move(andExpr), path);
    if (!objectMatchStatus.isOK()) {
        return objectMatchStatus;
    }

    return makeRestriction(BSONType::Object, std::move(objectMatch), typeExpr);
}
Beispiel #20
0
bool GeoQuery::parseLegacyQuery(const BSONObj &obj) {
    // The only legacy syntax is {$within: {.....}}
    BSONObjIterator outerIt(obj);
    if (!outerIt.more()) {
        return false;
    }
    BSONElement withinElt = outerIt.next();
    if (outerIt.more()) {
        return false;
    }
    if (!withinElt.isABSONObj()) {
        return false;
    }
    if (!equals(withinElt.fieldName(), "$within") && !equals(withinElt.fieldName(), "$geoWithin")) {
        return false;
    }
    BSONObj withinObj = withinElt.embeddedObject();

    bool hasGeometry = false;

    BSONObjIterator withinIt(withinObj);
    while (withinIt.more()) {
        BSONElement elt = withinIt.next();
        if (equals(elt.fieldName(), "$uniqueDocs")) {
            warning() << "deprecated $uniqueDocs option: " << obj.toString() << endl;
            // return false;
        }
        else if (elt.isABSONObj()) {
            hasGeometry = geoContainer.parseFrom(elt.wrap());
        }
        else {
            warning() << "bad geo query: " << obj.toString() << endl;
            return false;
        }
    }

    predicate = GeoQuery::WITHIN;

    return hasGeometry;
}
intrusive_ptr<DocumentSource> DocumentSourceMergeCursors::createFromBson(
    BSONElement elem, const intrusive_ptr<ExpressionContext>& pExpCtx) {
    massert(17026,
            string("Expected an Array, but got a ") + typeName(elem.type()),
            elem.type() == Array);

    std::vector<CursorDescriptor> cursorDescriptors;
    BSONObj array = elem.embeddedObject();
    BSONForEach(cursor, array) {
        massert(17027,
                string("Expected an Object, but got a ") + typeName(cursor.type()),
                cursor.type() == Object);

        // The cursor descriptors for the merge cursors stage used to lack an "ns" field; "ns" was
        // understood to be the expression context namespace in that case. For mixed-version
        // compatibility, we accept both the old and new formats here.
        std::string cursorNs = cursor["ns"] ? cursor["ns"].String() : pExpCtx->ns.ns();

        cursorDescriptors.emplace_back(ConnectionString(HostAndPort(cursor["host"].String())),
                                       std::move(cursorNs),
                                       cursor["id"].Long());
    }
BSONElement extractElementAtPathOrArrayAlongPath(const BSONObj& obj, const char*& path) {
    const char* p = strchr(path, '.');

    BSONElement sub;

    if (p) {
        sub = obj.getField(std::string(path, p - path));
        path = p + 1;
    } else {
        sub = obj.getField(path);
        path = path + strlen(path);
    }

    if (sub.eoo())
        return BSONElement();
    else if (sub.type() == Array || path[0] == '\0')
        return sub;
    else if (sub.type() == Object)
        return extractElementAtPathOrArrayAlongPath(sub.embeddedObject(), path);
    else
        return BSONElement();
}
Beispiel #23
0
        virtual IndexSuitability suitability( const FieldRangeSet& queryConstraints ,
                                              const BSONObj& order ) const {
            BSONObj query = queryConstraints.originalQuery();

            for (size_t i = 0; i < _fields.size(); ++i) {
                const IndexedField &field = _fields[i];
                if (IndexedField::GEO != field.type) { continue; }

                BSONElement e = query.getFieldDotted(field.name);
                // Some locations are given to us as arrays.  Sigh.
                if (Array == e.type()) { return HELPFUL; }
                if (Object != e.type()) { continue; }
                // getGtLtOp is horribly misnamed and really means get the operation.
                switch (e.embeddedObject().firstElement().getGtLtOp()) {
                    case BSONObj::opNEAR:
                    case BSONObj::opGEO_INTERSECTS:
                        return OPTIMAL;
                    default:
                        return HELPFUL;
                }
            }
            return USELESS;
        }
    /**
     * Given a database name and a BSONElement representing an array of roles, populates
     * "outPrivileges" with the privileges associated with the given roles on the named database.
     *
     * Returns Status::OK() on success.
     */
    Status _getPrivilegesFromRoles(const std::string& dbname,
                                   const BSONElement& rolesElement,
                                   std::vector<Privilege>* outPrivileges) {

        static const char privilegesTypeMismatchMessage[] =
            "Roles must be enumerated in an array of strings.";

        if (dbname == PrivilegeSet::WILDCARD_RESOURCE) {
            return Status(ErrorCodes::BadValue,
                          PrivilegeSet::WILDCARD_RESOURCE + " is an invalid database name.");
        }

        if (rolesElement.type() != Array)
            return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);

        for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
            BSONElement roleElement = *iter;
            if (roleElement.type() != String)
                return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);
            _addPrivilegesForSystemRole(dbname, roleElement.str(), outPrivileges);
        }
        return Status::OK();
    }
Beispiel #25
0
DiskLoc ArtificialTreeBuilder<OnDiskFormat>::makeTree(const BSONObj& spec) {
    DiskLoc bucketLoc = _helper->btree._addBucket(_opCtx);
    BucketType* bucket = _helper->btree.getBucket(_opCtx, bucketLoc);

    BSONObjIterator i(spec);
    while (i.more()) {
        BSONElement e = i.next();
        DiskLoc child;
        if (e.type() == Object) {
            child = makeTree(e.embeddedObject());
        }

        if (e.fieldName() == string("_")) {
            bucket->nextChild = child;
        } else {
            KeyDataOwnedType key(BSON("" << expectedKey(e.fieldName())));
            invariant(_helper->btree.pushBack(bucket, _helper->dummyDiskLoc, key, child));
        }
    }

    _helper->btree.fixParentPtrs(_opCtx, bucket, bucketLoc);
    return bucketLoc;
}
    Status _initializeUserRolesFromV1RolesArray(User* user,
                                                const BSONElement& rolesElement,
                                                const StringData& dbname) {
        static const char privilegesTypeMismatchMessage[] =
                "Roles in V1 user documents must be enumerated in an array of strings.";

        if (dbname == AuthorizationManager::WILDCARD_RESOURCE_NAME) {
            return Status(ErrorCodes::BadValue,
                          AuthorizationManager::WILDCARD_RESOURCE_NAME +
                                  " is an invalid database name.");
        }

        if (rolesElement.type() != Array)
            return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);

        for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
            BSONElement roleElement = *iter;
            if (roleElement.type() != String)
                return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);

            user->addRole(RoleName(roleElement.String(), dbname));
        }
        return Status::OK();
    }
intrusive_ptr<DocumentSource> DocumentSourceSample::createFromBson(
    BSONElement specElem, const intrusive_ptr<ExpressionContext>& expCtx) {
    uassert(28745, "the $sample stage specification must be an object", specElem.type() == Object);
    intrusive_ptr<DocumentSourceSample> sample(new DocumentSourceSample(expCtx));

    bool sizeSpecified = false;
    for (auto&& elem : specElem.embeddedObject()) {
        auto fieldName = elem.fieldNameStringData();

        if (fieldName == "size") {
            uassert(28746, "size argument to $sample must be a number", elem.isNumber());
            uassert(28747, "size argument to $sample must not be negative", elem.numberLong() >= 0);
            sample->_size = elem.numberLong();
            sizeSpecified = true;
        } else {
            uasserted(28748, str::stream() << "unrecognized option to $sample: " << fieldName);
        }
    }
    uassert(28749, "$sample stage must specify a size", sizeSpecified);

    sample->_sortStage = DocumentSourceSort::create(expCtx, randSortSpec, sample->_size);

    return sample;
}
Beispiel #28
0
// todo: can be a little faster if we don't use toString() here.
    bool BSONObj::valid() const {
        try{
            BSONObjIterator it(*this);
            while( it.moreWithEOO() ){
                // both throw exception on failure
                BSONElement e = it.next(true);
                e.validate();

                if (e.eoo()){
                    if (it.moreWithEOO())
                        return false;
                    return true;
                }else if (e.isABSONObj()){
                    if(!e.embeddedObject().valid())
                        return false;
                }else if (e.type() == CodeWScope){
                    if(!e.codeWScopeObject().valid())
                        return false;
                }
            }
        } catch (...) {
        }
        return false;
    }
    Status _checkV2RolesArray(const BSONElement& rolesElement) {
        StringData fieldName = rolesElement.fieldNameStringData();

        if (rolesElement.eoo()) {
            return _badValue(mongoutils::str::stream() << "User document needs '" << fieldName <<
                                     "' field to be provided",
                             0);
        }
        if (rolesElement.type() != Array) {
            return _badValue(mongoutils::str::stream() << fieldName << " field must be an array",
                             0);
        }
        for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
            if ((*iter).type() != Object) {
                return _badValue(mongoutils::str::stream() << "Elements in '" << fieldName <<
                                         "' array must objects.",
                                 0);
            }
            BSONObj roleObj = (*iter).Obj();
            BSONElement nameElement = roleObj[ROLE_NAME_FIELD_NAME];
            BSONElement sourceElement = roleObj[ROLE_SOURCE_FIELD_NAME];
            if (nameElement.type() != String ||
                    makeStringDataFromBSONElement(nameElement).empty()) {
                return _badValue(mongoutils::str::stream() << "Entries in '" << fieldName <<
                                         "' array need 'name' field to be a non-empty string",
                                 0);
            }
            if (sourceElement.type() != String ||
                    makeStringDataFromBSONElement(sourceElement).empty()) {
                return _badValue(mongoutils::str::stream() << "Entries in '" << fieldName <<
                                         "' array need 'source' field to be a non-empty string",
                                 0);
            }
        }
        return Status::OK();
    }
Beispiel #30
0
    FieldParser::FieldState FieldParser::extract(BSONObj doc,
                              const BSONField<BSONObj>& field,
                              BSONObj* out,
                              string* errMsg)
    {
        BSONElement elem = doc[field.name()];
        if (elem.eoo()) {
            if (field.hasDefault()) {
                *out = field.getDefault();
                return FIELD_DEFAULT;
            }
            else {
                return FIELD_NONE;
            }
        }

        if (elem.type() == Object) {
            *out = elem.embeddedObject().getOwned();
            return FIELD_SET;
        }

        _genFieldErrMsg(doc, field, "object", errMsg);
        return FIELD_INVALID;
    }