Пример #1
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" ) ) );
    }
Пример #2
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 ) ) );
    }
TEST(MatchExpressionParserTreeTest, NOREmbedded) {
    BSONObj query = BSON("$nor" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
    boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    StatusWithMatchExpression result = MatchExpressionParser::parse(query, 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)));
}
Пример #4
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 ) ) );
    }
Пример #5
0
Status ModifierPull::init(const BSONElement& modExpr, const Options& opts,
                          bool* positional) {
    // 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 (positional)
        *positional = foundDollar;

    if (foundDollar && foundCount > 1) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << "Too many positional (i.e. '$') elements found in path '"
                      << _fieldRef.dottedField() << "'");
    }

    _exprElt = modExpr;

    // If the element in the mod is actually an object or a regular expression, we need to
    // build a matcher, instead of just doing an equality comparision.
    if ((_exprElt.type() == mongo::Object) || (_exprElt.type() == mongo::RegEx)) {
        if (_exprElt.type() == Object) {
            _exprObj = _exprElt.embeddedObject();

            // If not is not a query operator, then it is a primitive.
            _matcherOnPrimitive = (_exprObj.firstElement().getGtLtOp() != 0);

            // If the object is primitive then wrap it up into an object.
            if (_matcherOnPrimitive)
                _exprObj = BSON( "" << _exprObj );
        }
        else {
            // For a regex, we also need to wrap and treat like a primitive.
            _matcherOnPrimitive = true;
            _exprObj = _exprElt.wrap("");
        }

        // Build the matcher around the object we built above.
        StatusWithMatchExpression parseResult = MatchExpressionParser::parse(_exprObj);
        if (!parseResult.isOK())
            return parseResult.getStatus();

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

    return Status::OK();
}
Пример #6
0
std::unique_ptr<MatchExpression> QueryPlannerTest::parseMatchExpression(
    const BSONObj& obj, const CollatorInterface* collator) {
    boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    expCtx->setCollator(collator);
    StatusWithMatchExpression status = MatchExpressionParser::parse(obj, std::move(expCtx));
    if (!status.isOK()) {
        FAIL(str::stream() << "failed to parse query: " << obj.toString() << ". Reason: "
                           << status.getStatus().toString());
    }
    return std::move(status.getValue());
}
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)));
}
Пример #8
0
TEST(MatchExpressionParserTreeTest, NOREmbedded) {
    BSONObj query = BSON("$nor" << BSON_ARRAY(BSON("x" << 1) << BSON("y" << 2)));
    const 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)));
}
Пример #9
0
        void run() {
            Client::WriteContext ctx(ns());
            DurTransaction txn;
            Database* db = ctx.ctx().db();
            Collection* coll = db->getCollection(ns());
            if (!coll) {
                coll = db->createCollection(&txn, ns());
            }
            WorkingSet ws;

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

            // Create a mock stage that returns the WSM.
            auto_ptr<MockStage> mockStage(new MockStage(&ws));

            // Mock data.
            {
                WorkingSetMember mockMember;
                mockMember.state = WorkingSetMember::LOC_AND_IDX;
                mockMember.loc = *locs.begin();

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

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

            // Matcher requires that foo==6 but we only have data with foo==5.
            auto_ptr<FetchStage> fetchStage(
                new FetchStage(&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);
        }
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}}")));
}
Пример #11
0
TEST(MatchExpressionParserGeoNear, ParseInvalidNearSphere) {
    {
        BSONObj query = fromjson("{loc: {$maxDistance: 100, $nearSphere: [0,0]}}");
        const CollatorInterface* collator = nullptr;
        StatusWithMatchExpression result =
            MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
        ASSERT_FALSE(result.isOK());
    }
    {
        BSONObj query = fromjson("{loc: {$minDistance: 100, $nearSphere: [0,0]}}");
        const CollatorInterface* collator = nullptr;
        StatusWithMatchExpression result =
            MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
        ASSERT_FALSE(result.isOK());
    }
    {
        BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $maxDistance: {}}}");
        const CollatorInterface* collator = nullptr;
        ASSERT_THROWS(
            MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
                .status_with_transitional_ignore(),
            UserException);
    }
    {
        BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $minDistance: {}}}");
        const CollatorInterface* collator = nullptr;
        ASSERT_THROWS(
            MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
                .status_with_transitional_ignore(),
            UserException);
    }
    {
        BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $eq: 1}}");
        const CollatorInterface* collator = nullptr;
        ASSERT_THROWS(
            MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator)
                .status_with_transitional_ignore(),
            UserException);
    }
}
// For $near, $nearSphere, and $geoNear syntax of:
// {
//   $near/$nearSphere/$geoNear: [ <x>, <y> ],
//   $minDistance: <distance in radians>,
//   $maxDistance: <distance in radians>
// }
TEST(MatchExpressionParserGeoNear, ParseValidNear) {
    BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: 100, $minDistance: 50}}");

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

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

    GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
    ASSERT_EQ(gnexp->getData().maxDistance, 100);
    ASSERT_EQ(gnexp->getData().minDistance, 50);
}
Пример #13
0
    TEST( MatchExpressionParserText, Parse1 ) {
        BSONObj query = fromjson( "{$text:{$search:\"awesome\", $language:\"english\"}}" );

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

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

        TextMatchExpression* textExp = static_cast<TextMatchExpression*>( exp );
        ASSERT_EQUALS( textExp->getQuery(), "awesome" );
        ASSERT_EQUALS( textExp->getLanguage(), "english" );
    }
    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() );

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

        GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
        ASSERT_EQUALS(gnexp->getData().maxDistance, 100);
    }
Пример #15
0
Matcher::Matcher(const BSONObj& pattern,
                 const boost::intrusive_ptr<ExpressionContext>& expCtx,
                 const ExtensionsCallback& extensionsCallback,
                 const MatchExpressionParser::AllowedFeatureSet allowedFeatures)
    : _pattern(pattern) {
    StatusWithMatchExpression statusWithMatcher =
        MatchExpressionParser::parse(pattern, expCtx, extensionsCallback, allowedFeatures);
    uassert(16810,
            mongoutils::str::stream() << "bad query: " << statusWithMatcher.getStatus().toString(),
            statusWithMatcher.isOK());

    _expression = std::move(statusWithMatcher.getValue());
}
Пример #16
0
// static
StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
    const std::string& ns,
    const BSONObj& query,
    const BSONObj& sort,
    const BSONObj& proj,
    long long skip,
    long long limit,
    const BSONObj& hint,
    const BSONObj& minObj,
    const BSONObj& maxObj,
    bool snapshot,
    bool explain,
    const MatchExpressionParser::WhereCallback& whereCallback) {
    // Pass empty sort and projection.
    BSONObj emptyObj;

    auto lpqStatus = LiteParsedQuery::makeAsOpQuery(NamespaceString(ns),
                                                    skip,
                                                    limit,
                                                    0,
                                                    query,
                                                    proj,
                                                    sort,
                                                    hint,
                                                    minObj,
                                                    maxObj,
                                                    snapshot,
                                                    explain);
    if (!lpqStatus.isOK()) {
        return lpqStatus.getStatus();
    }

    auto& lpq = lpqStatus.getValue();

    // Build a parse tree from the BSONObj in the parsed query.
    StatusWithMatchExpression statusWithMatcher =
        MatchExpressionParser::parse(lpq->getFilter(), whereCallback);
    if (!statusWithMatcher.isOK()) {
        return statusWithMatcher.getStatus();
    }
    std::unique_ptr<MatchExpression> me = std::move(statusWithMatcher.getValue());

    // Make the CQ we'll hopefully return.
    std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery());
    Status initStatus = cq->init(lpq.release(), whereCallback, me.release());

    if (!initStatus.isOK()) {
        return initStatus;
    }
    return std::move(cq);
}
Пример #17
0
// static
StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
    OperationContext* opCtx,
    std::unique_ptr<QueryRequest> qr,
    const boost::intrusive_ptr<ExpressionContext>& expCtx,
    const ExtensionsCallback& extensionsCallback,
    MatchExpressionParser::AllowedFeatureSet allowedFeatures) {
    auto qrStatus = qr->validate();
    if (!qrStatus.isOK()) {
        return qrStatus;
    }

    std::unique_ptr<CollatorInterface> collator;
    if (!qr->getCollation().isEmpty()) {
        auto statusWithCollator = CollatorFactoryInterface::get(opCtx->getServiceContext())
                                      ->makeFromBSON(qr->getCollation());
        if (!statusWithCollator.isOK()) {
            return statusWithCollator.getStatus();
        }
        collator = std::move(statusWithCollator.getValue());
    }

    // Make MatchExpression.
    boost::intrusive_ptr<ExpressionContext> newExpCtx;
    if (!expCtx.get()) {
        newExpCtx.reset(new ExpressionContext(opCtx, collator.get()));
    } else {
        newExpCtx = expCtx;
        invariant(CollatorInterface::collatorsMatch(collator.get(), expCtx->getCollator()));
    }
    StatusWithMatchExpression statusWithMatcher = MatchExpressionParser::parse(
        qr->getFilter(), newExpCtx, extensionsCallback, allowedFeatures);
    if (!statusWithMatcher.isOK()) {
        return statusWithMatcher.getStatus();
    }
    std::unique_ptr<MatchExpression> me = std::move(statusWithMatcher.getValue());

    // Make the CQ we'll hopefully return.
    std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery());

    Status initStatus =
        cq->init(opCtx,
                 std::move(qr),
                 parsingCanProduceNoopMatchNodes(extensionsCallback, allowedFeatures),
                 std::move(me),
                 std::move(collator));

    if (!initStatus.isOK()) {
        return initStatus;
    }
    return std::move(cq);
}
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}}")));
}
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")));
}
// For $near, $nearSphere, and $geoNear syntax of:
// {
//   $near/$nearSphere/$geoNear: [ <x>, <y> ],
//   $minDistance: <distance in radians>,
//   $maxDistance: <distance in radians>
// }
TEST(MatchExpressionParserGeoNear, ParseValidNear) {
    BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: 100, $minDistance: 50}}");

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

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

    GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
    ASSERT_EQ(gnexp->getData().maxDistance, 100);
    ASSERT_EQ(gnexp->getData().minDistance, 50);
}
TEST(MatchExpressionParserGeoNear, ParseNear) {
    BSONObj query = fromjson(
        "{loc:{$near:{$maxDistance:100, "
        "$geometry:{type:\"Point\", coordinates:[0,0]}}}}");

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

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

    GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
    ASSERT_EQUALS(gnexp->getData().maxDistance, 100);
}
Пример #22
0
    // Test a tree that exceeds the maximum depth limit.
    TEST( MatchExpressionParserTreeTest, MaximumTreeDepthExceed ) {
        static const int depth = 105;

        std::stringstream ss;
        for (int i = 0; i < depth/2; i++) {
            ss << "{$and: [{a: 3}, {$or: [{b: 2},";
        }
        ss << "{b: 4}";
        for (int i = 0; i < depth/2; i++) {
            ss << "]}]}";
        }

        BSONObj query = fromjson( ss.str() );
        StatusWithMatchExpression result = MatchExpressionParser::parse( query );
        ASSERT_FALSE( result.isOK() );
    }
Пример #23
0
        int countResults(const IndexScanParams& params, BSONObj filterObj = BSONObj()) {
            Client::ReadContext ctx(ns());
            PlanExecutor runner;

            StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj);
            verify(swme.isOK());
            auto_ptr<MatchExpression> filterExpr(swme.getValue());
            runner.setRoot(new IndexScan(params, runner.getWorkingSet(), filterExpr.get()));

            int count = 0;
            for (BSONObj obj; Runner::RUNNER_ADVANCED == runner.getNext(&obj); ) {
                ++count;
            }

            return count;
        }
Пример #24
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")));
}
Пример #25
0
    Status CanonicalQuery::canonicalize(const string& ns, const BSONObj& query,
                                        CanonicalQuery** out) {
        auto_ptr<CanonicalQuery> cq(new CanonicalQuery());

        LiteParsedQuery* lpq;
        Status parseStatus = LiteParsedQuery::make(ns, 0, 0, 0, query, &lpq);
        if (!parseStatus.isOK()) { return parseStatus; }
        cq->_pq.reset(lpq);

        StatusWithMatchExpression swme = MatchExpressionParser::parse(cq->_pq->getFilter());
        if (!swme.isOK()) { return swme.getStatus(); }

        cq->_root.reset(swme.getValue());
        *out = cq.release();
        return Status::OK();
    }
Пример #26
0
    // static
    Status CanonicalQuery::canonicalize(const QueryMessage& qm, CanonicalQuery** out) {
        auto_ptr<CanonicalQuery> cq(new CanonicalQuery());

        // Parse the query.
        LiteParsedQuery* lpq;
        Status parseStatus = LiteParsedQuery::make(qm, &lpq);
        if (!parseStatus.isOK()) { return parseStatus; }
        cq->_pq.reset(lpq);

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

        cq->_root.reset(swme.getValue());
        *out = cq.release();
        return Status::OK();
    }
Пример #27
0
        int countResults(const IndexScanParams& params, BSONObj filterObj = BSONObj()) {
            Client::ReadContext ctx(ns());

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

            WorkingSet* ws = new WorkingSet();
            PlanExecutor runner(ws, new IndexScan(params, ws, filterExpr.get()));

            int count = 0;
            for (DiskLoc dl; Runner::RUNNER_ADVANCED == runner.getNext(NULL, &dl); ) {
                ++count;
            }

            return count;
        }
Пример #28
0
// Test a tree that exceeds the maximum depth limit.
TEST(MatchExpressionParserTreeTest, MaximumTreeDepthExceed) {
    static const int depth = 105;

    std::stringstream ss;
    for (int i = 0; i < depth / 2; i++) {
        ss << "{$and: [{a: 3}, {$or: [{b: 2},";
    }
    ss << "{b: 4}";
    for (int i = 0; i < depth / 2; i++) {
        ss << "]}]}";
    }

    BSONObj query = fromjson(ss.str());
    CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_FALSE(result.isOK());
}
Пример #29
0
// Depth limit with nested $elemMatch object.
TEST(MatchExpressionParserTreeTest, MaximumTreeDepthExceededNestedElemMatch) {
    static const int depth = 105;

    std::stringstream ss;
    for (int i = 0; i < depth; i++) {
        ss << "{a: {$elemMatch: ";
    }
    ss << "{b: 5}";
    for (int i = 0; i < depth; i++) {
        ss << "}}";
    }

    BSONObj query = fromjson(ss.str());
    CollatorInterface* collator = nullptr;
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
    ASSERT_FALSE(result.isOK());
}
Пример #30
0
TEST(MatchExpressionParserGeo, WithinBox) {
    BSONObj query = fromjson("{a:{$within:{$box:[{x: 4, y:4},[6,6]]}}}");

    const CollatorInterface* collator = nullptr;
    const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
    StatusWithMatchExpression result =
        MatchExpressionParser::parse(query,
                                     collator,
                                     expCtx,
                                     ExtensionsCallbackNoop(),
                                     MatchExpressionParser::kAllowAllSpecialFeatures);
    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}}")));
}