void run() { const int N = 5000; for (int i = 0; i < N; ++i) { insert(BSON("foo" << (i % 10))); } addIndex(BSON("foo" << 1)); AutoGetCollectionForRead ctx(&_txn, ns()); const Collection* coll = ctx.getCollection(); // Plan 0: IXScan over foo == 7 // Every call to work() returns something so this should clearly win (by current scoring // at least). IndexScanParams ixparams; ixparams.descriptor = coll->getIndexCatalog()->findIndexByKeyPattern(&_txn, BSON("foo" << 1)); ixparams.bounds.isSimpleRange = true; ixparams.bounds.startKey = BSON("" << 7); ixparams.bounds.endKey = BSON("" << 7); ixparams.bounds.endKeyInclusive = true; ixparams.direction = 1; auto_ptr<WorkingSet> sharedWs(new WorkingSet()); IndexScan* ix = new IndexScan(&_txn, ixparams, sharedWs.get(), NULL); auto_ptr<PlanStage> firstRoot(new FetchStage(&_txn, sharedWs.get(), ix, NULL, coll)); // Plan 1: CollScan with matcher. CollectionScanParams csparams; csparams.collection = coll; csparams.direction = CollectionScanParams::FORWARD; // Make the filter. BSONObj filterObj = BSON("foo" << 7); StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj); verify(swme.isOK()); auto_ptr<MatchExpression> filter(swme.getValue()); // Make the stage. auto_ptr<PlanStage> secondRoot(new CollectionScan(&_txn, csparams, sharedWs.get(), filter.get())); // Hand the plans off to the runner. CanonicalQuery* cq = NULL; verify(CanonicalQuery::canonicalize(ns(), BSON("foo" << 7), &cq).isOK()); verify(NULL != cq); MultiPlanStage* mps = new MultiPlanStage(&_txn, ctx.getCollection(), cq); mps->addPlan(createQuerySolution(), firstRoot.release(), sharedWs.get()); mps->addPlan(createQuerySolution(), secondRoot.release(), sharedWs.get()); // Plan 0 aka the first plan aka the index scan should be the best. NULL means that // 'mps' will not yield during plan selection. mps->pickBestPlan(NULL); ASSERT(mps->bestPlanChosen()); ASSERT_EQUALS(0, mps->bestPlanIdx()); // Takes ownership of arguments other than 'collection'. PlanExecutor* rawExec; Status status = PlanExecutor::make(&_txn, sharedWs.release(), mps, cq, coll, PlanExecutor::YIELD_MANUAL, &rawExec); ASSERT_OK(status); boost::scoped_ptr<PlanExecutor> exec(rawExec); // Get all our results out. int results = 0; BSONObj obj; while (PlanExecutor::ADVANCED == exec->getNext(&obj, NULL)) { ASSERT_EQUALS(obj["foo"].numberInt(), 7); ++results; } ASSERT_EQUALS(results, N / 10); }
void run() { Client::WriteContext ctx(&_txn, ns()); const int N = 5000; for (int i = 0; i < N; ++i) { insert(BSON("foo" << (i % 10))); } addIndex(BSON("foo" << 1)); // Plan 0: IXScan over foo == 7 // Every call to work() returns something so this should clearly win (by current scoring // at least). IndexScanParams ixparams; ixparams.descriptor = getIndex(&_txn, ctx.ctx().db(), BSON("foo" << 1)); ixparams.bounds.isSimpleRange = true; ixparams.bounds.startKey = BSON("" << 7); ixparams.bounds.endKey = BSON("" << 7); ixparams.bounds.endKeyInclusive = true; ixparams.direction = 1; const Collection* coll = ctx.ctx().db()->getCollection(&_txn, ns()); auto_ptr<WorkingSet> sharedWs(new WorkingSet()); IndexScan* ix = new IndexScan(ixparams, sharedWs.get(), NULL); auto_ptr<PlanStage> firstRoot(new FetchStage(sharedWs.get(), ix, NULL, coll)); // Plan 1: CollScan with matcher. CollectionScanParams csparams; csparams.collection = ctx.ctx().db()->getCollection( &_txn, ns() ); csparams.direction = CollectionScanParams::FORWARD; // Make the filter. BSONObj filterObj = BSON("foo" << 7); StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj); verify(swme.isOK()); auto_ptr<MatchExpression> filter(swme.getValue()); // Make the stage. auto_ptr<PlanStage> secondRoot(new CollectionScan(csparams, sharedWs.get(), filter.get())); // Hand the plans off to the runner. CanonicalQuery* cq = NULL; verify(CanonicalQuery::canonicalize(ns(), BSON("foo" << 7), &cq).isOK()); verify(NULL != cq); MultiPlanStage* mps = new MultiPlanStage(ctx.ctx().db()->getCollection(&_txn, ns()),cq); mps->addPlan(createQuerySolution(), firstRoot.release(), sharedWs.get()); mps->addPlan(createQuerySolution(), secondRoot.release(), sharedWs.get()); // Plan 0 aka the first plan aka the index scan should be the best. mps->pickBestPlan(); ASSERT(mps->bestPlanChosen()); ASSERT_EQUALS(0, mps->bestPlanIdx()); SingleSolutionRunner sr( ctx.ctx().db()->getCollection(&_txn, ns()), cq, mps->bestSolution(), mps, sharedWs.release() ); // Get all our results out. int results = 0; BSONObj obj; while (Runner::RUNNER_ADVANCED == sr.getNext(&obj, NULL)) { ASSERT_EQUALS(obj["foo"].numberInt(), 7); ++results; } ctx.commit(); ASSERT_EQUALS(results, N / 10); }