Пример #1
0
    TEST( MatchExpressionParserTreeTest, NOT1 ) {
        BSONObj query = BSON( "x" << BSON( "$not" << BSON( "$gt" << 5 ) ) );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( result.getValue()->matchesBSON( BSON( "x" << 2 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 8 ) ) );
    }
Пример #2
0
    TEST( MatchExpressionParserTest, SimpleEQ1 ) {
        BSONObj query = BSON( "x" << 2 );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( result.getValue()->matchesBSON( BSON( "x" << 2 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 3 ) ) );
    }
TEST(MatchExpressionParserTreeTest, NOT1) {
    BSONObj query = BSON("x" << BSON("$not" << BSON("$gt" << 5)));
    boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
    ASSERT_TRUE(result.isOK());

    ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 8)));
}
TEST(MatchExpressionParserTest, SimpleEQ1) {
    BSONObj query = BSON("x" << 2);
    const CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
Пример #5
0
    void run() {
        // Rewrite (AND (OR a b) e) => (OR (AND a e) (AND b e))
        {
            BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1}");
            const CollatorInterface* collator = nullptr;
            StatusWithMatchExpression expr = MatchExpressionParser::parse(
                queryObj, ExtensionsCallbackDisallowExtensions(), collator);
            ASSERT_OK(expr.getStatus());
            std::unique_ptr<MatchExpression> rewrittenExpr =
                SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));

            std::string findCmdRewritten =
                "{find: 'testns',"
                "filter: {$or:[{a:1,e:1}, {b:1,e:1}]}}";
            std::unique_ptr<CanonicalQuery> cqRewritten = cqFromFindCommand(findCmdRewritten);

            ASSERT(rewrittenExpr->equivalent(cqRewritten->root()));
        }

        // Rewrite (AND (OR a b) e f) => (OR (AND a e f) (AND b e f))
        {
            BSONObj queryObj = fromjson("{$or:[{a:1}, {b:1}], e:1, f:1}");
            const CollatorInterface* collator = nullptr;
            StatusWithMatchExpression expr = MatchExpressionParser::parse(
                queryObj, ExtensionsCallbackDisallowExtensions(), collator);
            ASSERT_OK(expr.getStatus());
            std::unique_ptr<MatchExpression> rewrittenExpr =
                SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));

            std::string findCmdRewritten =
                "{find: 'testns',"
                "filter: {$or:[{a:1,e:1,f:1}, {b:1,e:1,f:1}]}}";
            std::unique_ptr<CanonicalQuery> cqRewritten = cqFromFindCommand(findCmdRewritten);

            ASSERT(rewrittenExpr->equivalent(cqRewritten->root()));
        }

        // Rewrite (AND (OR (AND a b) (AND c d) e f) => (OR (AND a b e f) (AND c d e f))
        {
            BSONObj queryObj = fromjson("{$or:[{a:1,b:1}, {c:1,d:1}], e:1,f:1}");
            const CollatorInterface* collator = nullptr;
            StatusWithMatchExpression expr = MatchExpressionParser::parse(
                queryObj, ExtensionsCallbackDisallowExtensions(), collator);
            ASSERT_OK(expr.getStatus());
            std::unique_ptr<MatchExpression> rewrittenExpr =
                SubplanStage::rewriteToRootedOr(std::move(expr.getValue()));

            std::string findCmdRewritten =
                "{find: 'testns',"
                "filter: {$or:[{a:1,b:1,e:1,f:1},"
                "{c:1,d:1,e:1,f:1}]}}";
            std::unique_ptr<CanonicalQuery> cqRewritten = cqFromFindCommand(findCmdRewritten);

            ASSERT(rewrittenExpr->equivalent(cqRewritten->root()));
        }
    }
Пример #6
0
TEST(MatchExpressionParserTreeTest, NOT1) {
    BSONObj query = BSON("x" << BSON("$not" << BSON("$gt" << 5)));
    const CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 8)));
}
Пример #7
0
    TEST( MatchExpressionParserTest, Multiple1 ) {
        BSONObj query = BSON( "x" << 5 << "y" << BSON( "$gt" << 5 << "$lt" << 8 ) );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( result.getValue()->matchesBSON( BSON( "x" << 5 << "y" << 7 ) ) );
        ASSERT( result.getValue()->matchesBSON( BSON( "x" << 5 << "y" << 6 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 6 << "y" << 7 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 5 << "y" << 9 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 5 << "y" << 4 ) ) );
    }
Пример #8
0
    TEST( MatchExpressionParserLeafTest, NotRegex1 ) {
        BSONObjBuilder b;
        b.appendRegex( "$not", "abc", "i" );
        BSONObj query = BSON( "x" << b.obj() );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << "abc" ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << "ABC" ) ) );
        ASSERT( result.getValue()->matchesBSON( BSON( "x" << "AC" ) ) );
    }
Пример #9
0
    TEST( MatchExpressionParserTreeTest, NOREmbedded ) {
        BSONObj query = BSON( "$nor" << BSON_ARRAY( BSON( "x" << 1 ) <<
                                                    BSON( "y" << 2 ) ) );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );

        ASSERT( !result.getValue()->matchesBSON( BSON( "x" << 1 ) ) );
        ASSERT( !result.getValue()->matchesBSON( BSON( "y" << 2 ) ) );
        ASSERT( result.getValue()->matchesBSON( BSON( "x" << 3 ) ) );
        ASSERT( result.getValue()->matchesBSON( BSON( "y" << 1 ) ) );
    }
Пример #10
0
TEST(MatchExpressionParserTreeTest, NOREmbedded) {
    BSONObj query = BSON("$nor" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
    CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
    ASSERT(!result.getValue()->matchesBSON(BSON("y" << 2)));
    ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
    ASSERT(result.getValue()->matchesBSON(BSON("y" << 1)));
}
TEST(MatchExpressionParserTest, Multiple1) {
    BSONObj query = BSON("x" << 5 << "y" << BSON("$gt" << 5 << "$lt" << 8));
    const CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result = MatchExpressionParser::parse(query, collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 7)));
    ASSERT(result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 6)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 6 << "y" << 7)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 9)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5 << "y" << 4)));
}
TEST(MatchExpressionParserTreeTest, OREmbedded) {
    BSONObj query1 = BSON("$or" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
    BSONObj query2 = BSON("$or" << BSON_ARRAY(query1));
    boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    StatusWithMatchExpression result = MatchExpressionParser::parse(query2, expCtx);
    ASSERT_TRUE(result.isOK());

    ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
    ASSERT(result.getValue()->matchesBSON(BSON("y" << 2)));
    ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
    ASSERT(!result.getValue()->matchesBSON(BSON("y" << 1)));
}
TEST(MatchExpressionParserGeo, WithinBox) {
    BSONObj query = fromjson("{a:{$within:{$box:[{x: 4, y:4},[6,6]]}}}");

    StatusWithMatchExpression result = MatchExpressionParser::parse(query);
    ASSERT_TRUE(result.isOK());

    ASSERT(!result.getValue()->matchesBSON(fromjson("{a: [3,4]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [4,4]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [5,5]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [5,5.1]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: {x: 5, y:5.1}}")));
}
Пример #14
0
    TEST( MatchExpressionParserGeoNear, ParseNear ) {
        BSONObj query = fromjson("{loc:{$near:{$maxDistance:100, "
                                 "$geometry:{type:\"Point\", coordinates:[0,0]}}}}");

        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_TRUE( result.isOK() );
        std::unique_ptr<MatchExpression> destroy(result.getValue());

        MatchExpression* exp = result.getValue();
        ASSERT_EQUALS(MatchExpression::GEO_NEAR, exp->matchType());

        GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
        ASSERT_EQUALS(gnexp->getData().maxDistance, 100);
    }
TEST(MatchExpressionParserGeo, WithinBox) {
    BSONObj query = fromjson("{a:{$within:{$box:[{x: 4, y:4},[6,6]]}}}");

    const CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(!result.getValue()->matchesBSON(fromjson("{a: [3,4]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [4,4]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [5,5]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: [5,5.1]}")));
    ASSERT(result.getValue()->matchesBSON(fromjson("{a: {x: 5, y:5.1}}")));
}
Пример #16
0
TEST(AtomicMatchExpressionTest, Simple1) {
    BSONObj query = BSON("x" << 5 << "$atomic" << BSON("$gt" << 5 << "$lt" << 8));
    StatusWithMatchExpression result = MatchExpressionParser::parse(query);
    ASSERT_TRUE(result.isOK());
    delete result.getValue();

    query = BSON("x" << 5 << "$isolated" << 1);
    result = MatchExpressionParser::parse(query);
    ASSERT_TRUE(result.isOK());
    delete result.getValue();

    query = BSON("x" << 5 << "y" << BSON("$isolated" << 1));
    result = MatchExpressionParser::parse(query);
    ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, NotRegex1) {
    BSONObjBuilder b;
    b.appendRegex("$not", "abc", "i");
    BSONObj query = BSON("x" << b.obj());
    boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
    ASSERT_TRUE(result.isOK());

    ASSERT(!result.getValue()->matchesBSON(BSON("x"
                                                << "abc")));
    ASSERT(!result.getValue()->matchesBSON(BSON("x"
                                                << "ABC")));
    ASSERT(result.getValue()->matchesBSON(BSON("x"
                                               << "AC")));
}
Пример #18
0
    int countResults(const IndexScanParams& params, BSONObj filterObj = BSONObj()) {
        AutoGetCollectionForReadCommand ctx(&_opCtx, NamespaceString(ns()));

        const CollatorInterface* collator = nullptr;
        const boost::intrusive_ptr<ExpressionContext> expCtx(
            new ExpressionContext(&_opCtx, collator));
        StatusWithMatchExpression statusWithMatcher =
            MatchExpressionParser::parse(filterObj, expCtx);
        verify(statusWithMatcher.isOK());
        unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());

        unique_ptr<WorkingSet> ws = stdx::make_unique<WorkingSet>();
        unique_ptr<IndexScan> ix =
            stdx::make_unique<IndexScan>(&_opCtx, params, ws.get(), filterExpr.get());

        auto statusWithPlanExecutor = PlanExecutor::make(
            &_opCtx, std::move(ws), std::move(ix), ctx.getCollection(), PlanExecutor::NO_YIELD);
        ASSERT_OK(statusWithPlanExecutor.getStatus());
        auto exec = std::move(statusWithPlanExecutor.getValue());

        int count = 0;
        PlanExecutor::ExecState state;
        for (RecordId dl; PlanExecutor::ADVANCED == (state = exec->getNext(NULL, &dl));) {
            ++count;
        }
        ASSERT_EQUALS(PlanExecutor::IS_EOF, state);

        return count;
    }
Пример #19
0
        void run() {
            Client::WriteContext ctx(ns());

            for (int i = 0; i < 50; ++i) {
                insert(BSON("foo" << 1 << "bar" << 1));
            }

            addIndex(BSON("foo" << 1));
            addIndex(BSON("bar" << 1));

            WorkingSet ws;
            BSONObj filterObj = BSON("foo" << BSON("$ne" << 1));
            StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj);
            verify(swme.isOK());
            auto_ptr<MatchExpression> filterExpr(swme.getValue());
            scoped_ptr<AndSortedStage> ah(new AndSortedStage(&ws, filterExpr.get()));

            // Scan over foo == 1
            IndexScanParams params;
            params.descriptor = getIndex(BSON("foo" << 1));
            params.bounds.isSimpleRange = true;
            params.bounds.startKey = BSON("" << 1);
            params.bounds.endKey = BSON("" << 1);
            params.bounds.endKeyInclusive = true;
            params.direction = 1;
            ah->addChild(new IndexScan(params, &ws, NULL));

            // bar == 1
            params.descriptor = getIndex(BSON("bar" << 1));
            ah->addChild(new IndexScan(params, &ws, NULL));

            // Filter drops everything.
            ASSERT_EQUALS(0, countResults(ah.get()));
        }
Пример #20
0
    Status CanonicalQuery::init(LiteParsedQuery* lpq) {
        _pq.reset(lpq);

        // Build a parse tree from the BSONObj in the parsed query.
        StatusWithMatchExpression swme = MatchExpressionParser::parse(_pq->getFilter());
        if (!swme.isOK()) { return swme.getStatus(); }

        MatchExpression* root = swme.getValue();
        Status validStatus = this->normalize(root);
        if (!validStatus.isOK()) {
            return validStatus;
        }
        this->generateCacheKey();

        // Validate the projection if there is one.
        if (!_pq->getProj().isEmpty()) {
            ParsedProjection* pp;
            Status projStatus = ParsedProjection::make(_pq->getProj(), root, &pp);
            if (!projStatus.isOK()) {
                return projStatus;
            }
            _proj.reset(pp);
        }

        return Status::OK();
    }
Пример #21
0
    void run() {
        ScopedTransaction transaction(&_txn, MODE_IX);
        Lock::DBLock lk(_txn.lockState(), nsToDatabaseSubstring(ns()), MODE_X);
        OldClientContext ctx(&_txn, ns());
        Database* db = ctx.db();
        Collection* coll = db->getCollection(ns());
        if (!coll) {
            WriteUnitOfWork wuow(&_txn);
            coll = db->createCollection(&_txn, ns());
            wuow.commit();
        }

        WorkingSet ws;

        // Add an object to the DB.
        insert(BSON("foo" << 5));
        set<RecordId> recordIds;
        getRecordIds(&recordIds, coll);
        ASSERT_EQUALS(size_t(1), recordIds.size());

        // Create a mock stage that returns the WSM.
        auto mockStage = make_unique<QueuedDataStage>(&_txn, &ws);

        // Mock data.
        {
            WorkingSetID id = ws.allocate();
            WorkingSetMember* mockMember = ws.get(id);
            mockMember->recordId = *recordIds.begin();
            ws.transitionToRecordIdAndIdx(id);

            // State is RecordId and index, shouldn't be able to get the foo data inside.
            BSONElement elt;
            ASSERT_FALSE(mockMember->getFieldDotted("foo", &elt));
            mockStage->pushBack(id);
        }

        // Make the filter.
        BSONObj filterObj = BSON("foo" << 6);
        const CollatorInterface* collator = nullptr;
        StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
            filterObj, ExtensionsCallbackDisallowExtensions(), collator);
        verify(statusWithMatcher.isOK());
        unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());

        // Matcher requires that foo==6 but we only have data with foo==5.
        unique_ptr<FetchStage> fetchStage(
            new FetchStage(&_txn, &ws, mockStage.release(), filterExpr.get(), coll));

        // First call should return a fetch request as it's not in memory.
        WorkingSetID id = WorkingSet::INVALID_ID;
        PlanStage::StageState state;

        // Normally we'd return the object but we have a filter that prevents it.
        state = fetchStage->work(&id);
        ASSERT_EQUALS(PlanStage::NEED_TIME, state);

        // No more data to fetch, so, EOF.
        state = fetchStage->work(&id);
        ASSERT_EQUALS(PlanStage::IS_EOF, state);
    }
    Status AuthzManagerExternalStateMock::_queryVector(
            const NamespaceString& collectionName,
            const BSONObj& query,
            std::vector<BSONObjCollection::iterator>* result) {

        StatusWithMatchExpression parseResult = MatchExpressionParser::parse(query);
        if (!parseResult.isOK()) {
            return parseResult.getStatus();
        }
        MatchExpression* matcher = parseResult.getValue();

        NamespaceDocumentMap::iterator mapIt = _documents.find(collectionName);
        if (mapIt == _documents.end())
            return Status(ErrorCodes::NoMatchingDocument,
                          "No collection named " + collectionName.ns());

        for (BSONObjCollection::iterator vecIt = mapIt->second.begin();
             vecIt != mapIt->second.end();
             ++vecIt) {

            if (matcher->matchesBSON(*vecIt)) {
                result->push_back(vecIt);
            }
        }
        return Status::OK();
    }
    Status AuthzManagerExternalStateMock::_queryVector(
            const NamespaceString& collectionName,
            const BSONObj& query,
            std::vector<BSONObjCollection::iterator>* result) {

        StatusWithMatchExpression parseResult = 
                MatchExpressionParser::parse(query, MatchExpressionParser::WhereCallback());
        if (!parseResult.isOK()) {
            return parseResult.getStatus();
        }
        const boost::scoped_ptr<MatchExpression> matcher(parseResult.getValue());

        NamespaceDocumentMap::iterator mapIt = _documents.find(collectionName);
        if (mapIt == _documents.end())
            return Status::OK();

        for (BSONObjCollection::iterator vecIt = mapIt->second.begin();
             vecIt != mapIt->second.end();
             ++vecIt) {

            if (matcher->matchesBSON(*vecIt)) {
                result->push_back(vecIt);
            }
        }
        return Status::OK();
    }
Пример #24
0
        int countResults(CollectionScanParams::Direction direction, const BSONObj& filterObj) {
            AutoGetCollectionForRead ctx(&_txn, ns());

            // Configure the scan.
            CollectionScanParams params;
            params.collection = ctx.getCollection();
            params.direction = direction;
            params.tailable = false;

            // Make the filter.
            StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj);
            verify(swme.isOK());
            auto_ptr<MatchExpression> filterExpr(swme.getValue());

            // Make a scan and have the runner own it.
            WorkingSet* ws = new WorkingSet();
            PlanStage* ps = new CollectionScan(&_txn, params, ws, filterExpr.get());

            PlanExecutor* rawExec;
            Status status = PlanExecutor::make(&_txn, ws, ps, params.collection,
                                               PlanExecutor::YIELD_MANUAL, &rawExec);
            ASSERT_OK(status);
            boost::scoped_ptr<PlanExecutor> exec(rawExec);

            // Use the runner to count the number of objects scanned.
            int count = 0;
            for (BSONObj obj; PlanExecutor::ADVANCED == exec->getNext(&obj, NULL); ) { ++count; }
            return count;
        }
Status AuthzManagerExternalStateMock::_queryVector(
    OperationContext* opCtx,
    const NamespaceString& collectionName,
    const BSONObj& query,
    std::vector<BSONObjCollection::iterator>* result) {
    const CollatorInterface* collator = nullptr;
    boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContext(opCtx, collator));
    StatusWithMatchExpression parseResult = MatchExpressionParser::parse(query, std::move(expCtx));
    if (!parseResult.isOK()) {
        return parseResult.getStatus();
    }
    const std::unique_ptr<MatchExpression> matcher = std::move(parseResult.getValue());

    NamespaceDocumentMap::iterator mapIt = _documents.find(collectionName);
    if (mapIt == _documents.end())
        return Status::OK();

    for (BSONObjCollection::iterator vecIt = mapIt->second.begin(); vecIt != mapIt->second.end();
         ++vecIt) {
        if (matcher->matchesBSON(*vecIt)) {
            result->push_back(vecIt);
        }
    }
    return Status::OK();
}
Пример #26
0
    int countResults(const IndexScanParams& params, BSONObj filterObj = BSONObj()) {
        AutoGetCollectionForRead ctx(&_txn, NamespaceString(ns()));

        const CollatorInterface* collator = nullptr;
        StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
            filterObj, ExtensionsCallbackDisallowExtensions(), collator);
        verify(statusWithMatcher.isOK());
        unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());

        unique_ptr<WorkingSet> ws = stdx::make_unique<WorkingSet>();
        unique_ptr<IndexScan> ix =
            stdx::make_unique<IndexScan>(&_txn, params, ws.get(), filterExpr.get());

        auto statusWithPlanExecutor = PlanExecutor::make(
            &_txn, std::move(ws), std::move(ix), ctx.getCollection(), PlanExecutor::YIELD_MANUAL);
        ASSERT_OK(statusWithPlanExecutor.getStatus());
        unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());

        int count = 0;
        PlanExecutor::ExecState state;
        for (RecordId dl; PlanExecutor::ADVANCED == (state = exec->getNext(NULL, &dl));) {
            ++count;
        }
        ASSERT_EQUALS(PlanExecutor::IS_EOF, state);

        return count;
    }
Пример #27
0
TEST(MatchExpressionParserLeafTest, NotRegex1) {
    BSONObjBuilder b;
    b.appendRegex("$not", "abc", "i");
    BSONObj query = BSON("x" << b.obj());
    const CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_TRUE(result.isOK());

    ASSERT(!result.getValue()->matchesBSON(BSON("x"
                                                << "abc")));
    ASSERT(!result.getValue()->matchesBSON(BSON("x"
                                                << "ABC")));
    ASSERT(result.getValue()->matchesBSON(BSON("x"
                                               << "AC")));
}
Пример #28
0
        bool run(OperationContext* txn,
                 const string& dbname,
                 BSONObj& jsobj,
                 int,
                 string& errmsg,
                 BSONObjBuilder& result,
                 bool /*fromRepl*/) {

            ScopedTransaction scopedXact(txn, MODE_IS);
            AutoGetDb autoDb(txn, dbname, MODE_S);

            const Database* d = autoDb.getDb();
            const DatabaseCatalogEntry* dbEntry = NULL;

            list<string> names;
            if ( d ) {
                dbEntry = d->getDatabaseCatalogEntry();
                dbEntry->getCollectionNamespaces( &names );
                names.sort();
            }

            scoped_ptr<MatchExpression> matcher;
            if ( jsobj["filter"].isABSONObj() ) {
                StatusWithMatchExpression parsed =
                    MatchExpressionParser::parse( jsobj["filter"].Obj() );
                if ( !parsed.isOK() ) {
                    return appendCommandStatus( result, parsed.getStatus() );
                }
                matcher.reset( parsed.getValue() );
            }

            BSONArrayBuilder arr;

            for ( list<string>::const_iterator i = names.begin(); i != names.end(); ++i ) {
                string ns = *i;

                StringData collection = nsToCollectionSubstring( ns );
                if ( collection == "system.namespaces" ) {
                    continue;
                }

                BSONObjBuilder b;
                b.append( "name", collection );

                CollectionOptions options =
                    dbEntry->getCollectionCatalogEntry( txn, ns )->getCollectionOptions(txn);
                b.append( "options", options.toBSON() );

                BSONObj maybe = b.obj();
                if ( matcher && !matcher->matchesBSON( maybe ) ) {
                    continue;
                }

                arr.append( maybe );
            }

            result.append( "collections", arr.arr() );

            return true;
        }
Пример #29
0
    int countResults(CollectionScanParams::Direction direction, const BSONObj& filterObj) {
        AutoGetCollectionForRead ctx(&_txn, ns());

        // Configure the scan.
        CollectionScanParams params;
        params.collection = ctx.getCollection();
        params.direction = direction;
        params.tailable = false;

        // Make the filter.
        StatusWithMatchExpression statusWithMatcher =
            MatchExpressionParser::parse(filterObj, ExtensionsCallbackDisallowExtensions());
        verify(statusWithMatcher.isOK());
        unique_ptr<MatchExpression> filterExpr = std::move(statusWithMatcher.getValue());

        // Make a scan and have the runner own it.
        unique_ptr<WorkingSet> ws = make_unique<WorkingSet>();
        unique_ptr<PlanStage> ps =
            make_unique<CollectionScan>(&_txn, params, ws.get(), filterExpr.get());

        auto statusWithPlanExecutor = PlanExecutor::make(
            &_txn, std::move(ws), std::move(ps), params.collection, PlanExecutor::YIELD_MANUAL);
        ASSERT_OK(statusWithPlanExecutor.getStatus());
        unique_ptr<PlanExecutor> exec = std::move(statusWithPlanExecutor.getValue());

        // Use the runner to count the number of objects scanned.
        int count = 0;
        PlanExecutor::ExecState state;
        for (BSONObj obj; PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL));) {
            ++count;
        }
        ASSERT_EQUALS(PlanExecutor::IS_EOF, state);
        return count;
    }
Пример #30
0
    Status ModifierPull::init(const BSONElement& modExpr, const Options& opts) {
        // Perform standard field name and updateable checks.
        _fieldRef.parse(modExpr.fieldName());
        Status status = fieldchecker::isUpdatable(_fieldRef);
        if (! status.isOK()) {
            return status;
        }

        // If a $-positional operator was used, get the index in which it occurred
        // and ensure only one occurrence.
        size_t foundCount;
        bool foundDollar = fieldchecker::isPositional(_fieldRef, &_posDollar, &foundCount);
        if (foundDollar && foundCount > 1) {
            return Status(ErrorCodes::BadValue, "too many positional($) elements found.");
        }

        _exprElt = modExpr;
        if (_exprElt.type() == Object) {

            _exprObj = _exprElt.embeddedObject();
            _matcherOnPrimitive = (_exprObj.firstElement().getGtLtOp() != 0);
            if (_matcherOnPrimitive)
                _exprObj = BSON( "" << _exprObj );

            StatusWithMatchExpression parseResult = MatchExpressionParser::parse(_exprObj);
            if (!parseResult.isOK())
                return parseResult.getStatus();

            _matchExpr.reset(parseResult.getValue());
        }

        return Status::OK();
    }