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 ) ) ); }
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))); }
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())); } }
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))); }
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 ) ) ); }
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" ) ) ); }
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))); 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}}"))); }
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}}"))); }
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"))); }
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; }
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())); }
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(); }
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(); }
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(); }
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; }
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"))); }
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; }
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; }
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(); }