void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << "2d" << "b" << 1)); addIndex(BSON("a" << "2d")); BSONObj query = fromjson( "{$or: [{a: {$geoWithin: {$centerSphere: [[0,0],10]}}}," "{a: {$geoWithin: {$centerSphere: [[1,1],10]}}}]}"); auto qr = stdx::make_unique<QueryRequest>(nss); qr->setFilter(query); auto statusWithCQ = CanonicalQuery::canonicalize( txn(), std::move(qr), ExtensionsCallbackDisallowExtensions()); ASSERT_OK(statusWithCQ.getStatus()); std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); Collection* collection = ctx.getCollection(); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); // Plan selection should succeed due to falling back on regular planning. PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); }
void run() { Client::WriteContext ctx(&_txn, ns()); addIndex(BSON("a" << "2d" << "b" << 1)); addIndex(BSON("a" << "2d")); BSONObj query = fromjson("{$or: [{a: {$geoWithin: {$centerSphere: [[0,0],10]}}}," "{a: {$geoWithin: {$centerSphere: [[1,1],10]}}}]}"); CanonicalQuery* cq; ASSERT_OK(CanonicalQuery::canonicalize(ns(), query, &cq)); boost::scoped_ptr<CanonicalQuery> killCq(cq); Collection* collection = ctx.getCollection(); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq, &plannerParams); WorkingSet ws; boost::scoped_ptr<SubplanStage> subplan(new SubplanStage(&_txn, collection, &ws, plannerParams, cq)); // NULL means that 'subplan' will not yield during plan selection. Plan selection // should succeed due to falling back on regular planning. ASSERT_OK(subplan->pickBestPlan(NULL)); }
void run() { OldClientWriteContext ctx(&_txn, ns()); addIndex(BSON("a" << "2d" << "b" << 1)); addIndex(BSON("a" << "2d")); BSONObj query = fromjson("{$or: [{a: {$geoWithin: {$centerSphere: [[0,0],10]}}}," "{a: {$geoWithin: {$centerSphere: [[1,1],10]}}}]}"); CanonicalQuery* rawCq; ASSERT_OK(CanonicalQuery::canonicalize(ns(), query, &rawCq)); boost::scoped_ptr<CanonicalQuery> cq(rawCq); Collection* collection = ctx.getCollection(); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; boost::scoped_ptr<SubplanStage> subplan(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); // Plan selection should succeed due to falling back on regular planning. PlanYieldPolicy yieldPolicy(NULL, PlanExecutor::YIELD_MANUAL); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("b" << 1 << "a" << 1)); addIndex(BSON("c" << 1 << "a" << 1)); BSONObj query = fromjson("{a: 1, $or: [{b: 2}, {c: 3}]}"); // Two of these documents match. insert(BSON("_id" << 1 << "a" << 1 << "b" << 2)); insert(BSON("_id" << 2 << "a" << 2 << "b" << 2)); insert(BSON("_id" << 3 << "a" << 1 << "c" << 3)); insert(BSON("_id" << 4 << "a" << 1 << "c" << 4)); auto qr = stdx::make_unique<QueryRequest>(nss); qr->setFilter(query); auto cq = unittest::assertGet(CanonicalQuery::canonicalize( txn(), std::move(qr), ExtensionsCallbackDisallowExtensions())); Collection* collection = ctx.getCollection(); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); // Plan selection should succeed due to falling back on regular planning. PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Work the stage until it produces all results. size_t numResults = 0; PlanStage::StageState stageState = PlanStage::NEED_TIME; while (stageState != PlanStage::IS_EOF) { WorkingSetID id = WorkingSet::INVALID_ID; stageState = subplan->work(&id); ASSERT_NE(stageState, PlanStage::DEAD); ASSERT_NE(stageState, PlanStage::FAILURE); if (stageState == PlanStage::ADVANCED) { ++numResults; WorkingSetMember* member = ws.get(id); ASSERT(member->hasObj()); ASSERT(member->obj.value() == BSON("_id" << 1 << "a" << 1 << "b" << 2) || member->obj.value() == BSON("_id" << 3 << "a" << 1 << "c" << 3)); } } ASSERT_EQ(numResults, 2U); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("a" << 1 << "c" << 1)); addIndex(BSON("d" << 1)); for (int i = 0; i < 10; i++) { insert(BSON("a" << 1 << "e" << 1 << "d" << 1)); } // Running this query should not create any cache entries. For the first branch, it's // because plans using the {a: 1, b: 1} and {a: 1, c: 1} indices should tie during plan // ranking. For the second branch it's because there is only one relevant index. BSONObj query = fromjson("{$or: [{a: 1, e: 1}, {d: 1}]}"); Collection* collection = ctx.getCollection(); auto qr = stdx::make_unique<QueryRequest>(nss); qr->setFilter(query); auto statusWithCQ = CanonicalQuery::canonicalize( txn(), std::move(qr), ExtensionsCallbackDisallowExtensions()); ASSERT_OK(statusWithCQ.getStatus()); std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from // the plan cache. ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); // If we run the query again, it should again be the case that neither branch gets planned // from the cache (because the first call to pickBestPlan() refrained from creating any // cache entries). ws.clear(); subplan.reset(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << 1)); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("c" << 1)); for (int i = 0; i < 10; i++) { insert(BSON("a" << 1 << "b" << i << "c" << i)); } // This query should result in a plan cache entry for the first $or branch, because // there are two competing indices. The second branch has only one relevant index, so // its winning plan should not be cached. BSONObj query = fromjson("{$or: [{a: 1, b: 3}, {c: 1}]}"); Collection* collection = ctx.getCollection(); auto qr = stdx::make_unique<QueryRequest>(nss); qr->setFilter(query); auto statusWithCQ = CanonicalQuery::canonicalize( txn(), std::move(qr), ExtensionsCallbackDisallowExtensions()); ASSERT_OK(statusWithCQ.getStatus()); std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from // the plan cache. ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); // If we repeat the same query, the plan for the first branch should have come from // the cache. ws.clear(); subplan.reset(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); ASSERT_TRUE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("a" << 1)); addIndex(BSON("c" << 1)); for (int i = 0; i < 10; i++) { insert(BSON("a" << 1 << "b" << i << "c" << i)); } // Running this query should not create any cache entries. For the first branch, it's // because there are no matching results. For the second branch it's because there is only // one relevant index. BSONObj query = fromjson("{$or: [{a: 1, b: 15}, {c: 1}]}"); Collection* collection = ctx.getCollection(); auto statusWithCQ = CanonicalQuery::canonicalize(nss, query); ASSERT_OK(statusWithCQ.getStatus()); std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(nullptr, PlanExecutor::YIELD_MANUAL); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from // the plan cache. ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); // If we run the query again, it should again be the case that neither branch gets planned // from the cache (because the first call to pickBestPlan() refrained from creating any // cache entries). ws.clear(); subplan.reset(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); }
void run() { OldClientWriteContext ctx(&_txn, ns()); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("a" << 1 << "c" << 1)); for (int i = 0; i < 10; i++) { insert(BSON("a" << 1 << "b" << i << "c" << i)); } // This query should result in a plan cache entry for the first branch. The second // branch should tie, meaning that nothing is inserted into the plan cache. BSONObj query = fromjson("{$or: [{a: 1, b: 3}, {a: 1}]}"); Collection* collection = ctx.getCollection(); CanonicalQuery* rawCq; ASSERT_OK(CanonicalQuery::canonicalize(ns(), query, &rawCq)); boost::scoped_ptr<CanonicalQuery> cq(rawCq); // Get planner params. QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; boost::scoped_ptr<SubplanStage> subplan(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(NULL, PlanExecutor::YIELD_MANUAL); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); // Nothing is in the cache yet, so neither branch should have been planned from // the plan cache. ASSERT_FALSE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); // If we repeat the same query, then the first branch should come from the cache, // but the second is re-planned due to tying on the first run. ws.clear(); subplan.reset(new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); ASSERT_TRUE(subplan->branchPlannedFromCache(0)); ASSERT_FALSE(subplan->branchPlannedFromCache(1)); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("a" << 1 << "c" << 1)); // Every doc matches. insert(BSON("_id" << 1 << "a" << 1)); insert(BSON("_id" << 2 << "a" << 2)); insert(BSON("_id" << 3 << "a" << 3)); insert(BSON("_id" << 4)); auto qr = stdx::make_unique<QueryRequest>(nss); qr->setFilter(fromjson("{$or: [{a: 1}, {a: {$ne:1}}]}")); qr->setSort(BSON("d" << 1)); auto cq = unittest::assertGet(CanonicalQuery::canonicalize( txn(), std::move(qr), ExtensionsCallbackDisallowExtensions())); Collection* collection = ctx.getCollection(); QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); size_t numResults = 0; PlanStage::StageState stageState = PlanStage::NEED_TIME; while (stageState != PlanStage::IS_EOF) { WorkingSetID id = WorkingSet::INVALID_ID; stageState = subplan->work(&id); ASSERT_NE(stageState, PlanStage::DEAD); ASSERT_NE(stageState, PlanStage::FAILURE); if (stageState == PlanStage::ADVANCED) { ++numResults; } } ASSERT_EQ(numResults, 4U); }
void run() { OldClientWriteContext ctx(&_txn, nss.ns()); addIndex(BSON("a" << 1 << "b" << 1)); addIndex(BSON("a" << 1 << "c" << 1)); // Every doc matches. insert(BSON("_id" << 1 << "a" << 1)); insert(BSON("_id" << 2 << "a" << 2)); insert(BSON("_id" << 3 << "a" << 3)); insert(BSON("_id" << 4)); BSONObj query = fromjson("{$or: [{a: 1}, {a: {$ne:1}}]}"); BSONObj sort = BSON("d" << 1); BSONObj projection; auto cq = unittest::assertGet(CanonicalQuery::canonicalize(nss, query, sort, projection)); Collection* collection = ctx.getCollection(); QueryPlannerParams plannerParams; fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams); WorkingSet ws; std::unique_ptr<SubplanStage> subplan( new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get())); PlanYieldPolicy yieldPolicy(nullptr, PlanExecutor::YIELD_MANUAL); ASSERT_OK(subplan->pickBestPlan(&yieldPolicy)); size_t numResults = 0; PlanStage::StageState stageState = PlanStage::NEED_TIME; while (stageState != PlanStage::IS_EOF) { WorkingSetID id = WorkingSet::INVALID_ID; stageState = subplan->work(&id); ASSERT_NE(stageState, PlanStage::DEAD); ASSERT_NE(stageState, PlanStage::FAILURE); if (stageState == PlanStage::ADVANCED) { ++numResults; } } ASSERT_EQ(numResults, 4U); }