summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/commands/find_cmd.cpp31
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp12
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp27
-rw-r--r--src/mongo/db/commands/index_filter_commands_test.cpp21
-rw-r--r--src/mongo/db/commands/mr.cpp21
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp38
-rw-r--r--src/mongo/db/commands/plan_cache_commands.h7
-rw-r--r--src/mongo/db/commands/plan_cache_commands_test.cpp84
-rw-r--r--src/mongo/db/dbcommands.cpp7
-rw-r--r--src/mongo/db/dbhelpers.cpp15
-rw-r--r--src/mongo/db/exec/sort.cpp8
-rw-r--r--src/mongo/db/exec/subplan.cpp26
-rw-r--r--src/mongo/db/exec/update.cpp2
-rw-r--r--src/mongo/db/ops/parsed_delete.cpp38
-rw-r--r--src/mongo/db/ops/parsed_delete.h2
-rw-r--r--src/mongo/db/ops/parsed_update.cpp36
-rw-r--r--src/mongo/db/ops/parsed_update.h2
-rw-r--r--src/mongo/db/ops/update_driver.cpp19
-rw-r--r--src/mongo/db/ops/update_driver.h2
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp27
-rw-r--r--src/mongo/db/query/canonical_query.cpp142
-rw-r--r--src/mongo/db/query/canonical_query.h162
-rw-r--r--src/mongo/db/query/canonical_query_test.cpp25
-rw-r--r--src/mongo/db/query/find.cpp31
-rw-r--r--src/mongo/db/query/get_executor.cpp84
-rw-r--r--src/mongo/db/query/get_executor_test.cpp11
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp154
-rw-r--r--src/mongo/db/query/query_planner_test.cpp20
-rw-r--r--src/mongo/db/query/query_planner_test_fixture.cpp74
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp12
-rw-r--r--src/mongo/dbtests/executor_registry.cpp8
-rw-r--r--src/mongo/dbtests/oplogstarttests.cpp7
-rw-r--r--src/mongo/dbtests/plan_ranking.cpp166
-rw-r--r--src/mongo/dbtests/query_multi_plan_runner.cpp41
-rw-r--r--src/mongo/dbtests/query_plan_executor.cpp34
-rw-r--r--src/mongo/dbtests/query_stage_cached_plan.cpp12
-rw-r--r--src/mongo/dbtests/query_stage_delete.cpp25
-rw-r--r--src/mongo/dbtests/query_stage_subplan.cpp12
-rw-r--r--src/mongo/dbtests/query_stage_update.cpp33
-rw-r--r--src/mongo/s/chunk_manager.cpp22
-rw-r--r--src/mongo/s/chunk_manager.h2
-rw-r--r--src/mongo/s/chunk_manager_targeter_test.cpp17
-rw-r--r--src/mongo/s/shard_key_pattern.cpp11
43 files changed, 793 insertions, 737 deletions
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index f86fbbe8b34..d40ff0f766e 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -129,14 +129,17 @@ public:
}
// Finish the parsing step by using the LiteParsedQuery to create a CanonicalQuery.
-
- WhereCallbackReal whereCallback(txn, nss.db());
- auto statusWithCQ =
- CanonicalQuery::canonicalize(lpqStatus.getValue().release(), whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ std::unique_ptr<CanonicalQuery> cq;
+ {
+ CanonicalQuery* rawCq;
+ WhereCallbackReal whereCallback(txn, nss.db());
+ Status canonStatus =
+ CanonicalQuery::canonicalize(lpqStatus.getValue().release(), &rawCq, whereCallback);
+ if (!canonStatus.isOK()) {
+ return canonStatus;
+ }
+ cq.reset(rawCq);
}
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
AutoGetCollectionForRead ctx(txn, nss);
// The collection may be NULL. If so, getExecutor() should handle it by returning
@@ -211,12 +214,16 @@ public:
beginQueryOp(txn, nss, cmdObj, ntoreturn, lpq->getSkip());
// 1b) Finish the parsing step by using the LiteParsedQuery to create a CanonicalQuery.
- WhereCallbackReal whereCallback(txn, nss.db());
- auto statusWithCQ = CanonicalQuery::canonicalize(lpq.release(), whereCallback);
- if (!statusWithCQ.isOK()) {
- return appendCommandStatus(result, statusWithCQ.getStatus());
+ std::unique_ptr<CanonicalQuery> cq;
+ {
+ CanonicalQuery* rawCq;
+ WhereCallbackReal whereCallback(txn, nss.db());
+ Status canonStatus = CanonicalQuery::canonicalize(lpq.release(), &rawCq, whereCallback);
+ if (!canonStatus.isOK()) {
+ return appendCommandStatus(result, canonStatus);
+ }
+ cq.reset(rawCq);
}
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
// 2) Acquire locks.
AutoGetCollectionForRead ctx(txn, nss);
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index df8fd3bdee4..5be50f433f6 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -181,22 +181,22 @@ public:
BSONObj projObj = BSON("$pt" << BSON("$meta" << LiteParsedQuery::metaGeoNearPoint) << "$dis"
<< BSON("$meta" << LiteParsedQuery::metaGeoNearDistance));
+ CanonicalQuery* cq;
const WhereCallbackReal whereCallback(txn, nss.db());
- auto statusWithCQ = CanonicalQuery::canonicalize(
- nss, rewritten, BSONObj(), projObj, 0, numWanted, BSONObj(), whereCallback);
- if (!statusWithCQ.isOK()) {
+
+ if (!CanonicalQuery::canonicalize(
+ nss, rewritten, BSONObj(), projObj, 0, numWanted, BSONObj(), &cq, whereCallback)
+ .isOK()) {
errmsg = "Can't parse filter / create query";
return false;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
// Prevent chunks from being cleaned up during yields - this allows us to only check the
// version on initial entry into geoNear.
RangePreserver preserver(collection);
PlanExecutor* rawExec;
- if (!getExecutor(txn, collection, cq.release(), PlanExecutor::YIELD_AUTO, &rawExec, 0)
- .isOK()) {
+ if (!getExecutor(txn, collection, cq, PlanExecutor::YIELD_AUTO, &rawExec, 0).isOK()) {
errmsg = "can't get query executor";
return false;
}
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index 0b6345ef06a..20783c5b244 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -268,12 +268,13 @@ Status ClearFilters::clear(OperationContext* txn,
// - clear hints for single query shape when a query shape is described in the
// command arguments.
if (cmdObj.hasField("query")) {
- auto statusWithCQ = PlanCacheCommand::canonicalize(txn, ns, cmdObj);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cqRaw;
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
+ if (!status.isOK()) {
+ return status;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ unique_ptr<CanonicalQuery> cq(cqRaw);
querySettings->removeAllowedIndices(planCache->computeKey(*cq));
// Remove entry from plan cache
@@ -314,10 +315,11 @@ Status ClearFilters::clear(OperationContext* txn,
invariant(entry);
// Create canonical query.
- auto statusWithCQ = CanonicalQuery::canonicalize(
- ns, entry->query, entry->sort, entry->projection, whereCallback);
- invariant(statusWithCQ.isOK());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ Status result = CanonicalQuery::canonicalize(
+ ns, entry->query, entry->sort, entry->projection, &cqRaw, whereCallback);
+ invariant(result.isOK());
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Remove plan cache entry.
planCache->remove(*cq);
@@ -382,11 +384,12 @@ Status SetFilter::set(OperationContext* txn,
indexes.push_back(obj.getOwned());
}
- auto statusWithCQ = PlanCacheCommand::canonicalize(txn, ns, cmdObj);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cqRaw;
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
+ if (!status.isOK()) {
+ return status;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Add allowed indices to query settings, overriding any previous entries.
querySettings->setAllowedIndices(*cq, planCache->computeKey(*cq), indexes);
diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp
index 7da3619d1f7..ba6f6c87e6c 100644
--- a/src/mongo/db/commands/index_filter_commands_test.cpp
+++ b/src/mongo/db/commands/index_filter_commands_test.cpp
@@ -120,9 +120,9 @@ void addQueryShapeToPlanCache(PlanCache* planCache,
BSONObj projectionObj = fromjson(projectionStr);
// Create canonical query.
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projectionObj);
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, queryObj, sortObj, projectionObj, &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
QuerySolution qs;
qs.cacheData.reset(new SolutionCacheData());
@@ -144,9 +144,9 @@ bool planCacheContains(const PlanCache& planCache,
BSONObj projectionObj = fromjson(projectionStr);
// Create canonical query.
- auto statusWithInputQuery = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projectionObj);
- ASSERT_OK(statusWithInputQuery.getStatus());
- unique_ptr<CanonicalQuery> inputQuery = std::move(statusWithInputQuery.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, queryObj, sortObj, projectionObj, &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Retrieve cache entries from plan cache.
vector<PlanCacheEntry*> entries = planCache.getAllEntries();
@@ -159,12 +159,11 @@ bool planCacheContains(const PlanCache& planCache,
// Canonicalizing query shape in cache entry to get cache key.
// Alternatively, we could add key to PlanCacheEntry but that would be used in one place
// only.
- auto statusWithCurrentQuery =
- CanonicalQuery::canonicalize(ns, entry->query, entry->sort, entry->projection);
- ASSERT_OK(statusWithCurrentQuery.getStatus());
- unique_ptr<CanonicalQuery> currentQuery = std::move(statusWithCurrentQuery.getValue());
+ ASSERT_OK(
+ CanonicalQuery::canonicalize(ns, entry->query, entry->sort, entry->projection, &cqRaw));
+ unique_ptr<CanonicalQuery> currentQuery(cqRaw);
- if (planCache.computeKey(*currentQuery) == planCache.computeKey(*inputQuery)) {
+ if (planCache.computeKey(*currentQuery) == planCache.computeKey(*cq)) {
found = true;
}
// Release resources for cache entry after extracting key.
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 8b395343a14..f32ebe3b8d8 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -781,8 +781,8 @@ void State::init() {
_scope->invoke(init, 0, 0, 0, true);
// js function to run reduce on all keys
- // redfunc = _scope->createFunction("for (var key in hashmap) { print('Key is ' + key); list =
- // hashmap[key]; ret = reduce(key, list); print('Value is ' + ret); };");
+ // redfunc = _scope->createFunction("for (var key in hashmap) { print('Key is ' + key);
+ // list = hashmap[key]; ret = reduce(key, list); print('Value is ' + ret); };");
_reduceAll = _scope->createFunction(
"var map = _mrMap;"
"var list, ret;"
@@ -1004,10 +1004,10 @@ void State::finalReduce(CurOp* op, ProgressMeterHolder& pm) {
const NamespaceString nss(_config.incLong);
const WhereCallbackReal whereCallback(_txn, nss.db());
- auto statusWithCQ =
- CanonicalQuery::canonicalize(_config.incLong, BSONObj(), sortKey, BSONObj(), whereCallback);
- verify(statusWithCQ.isOK());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ verify(CanonicalQuery::canonicalize(
+ _config.incLong, BSONObj(), sortKey, BSONObj(), &cqRaw, whereCallback).isOK());
+ std::unique_ptr<CanonicalQuery> cq(cqRaw);
Collection* coll = getCollectionOrUassert(ctx->getDb(), _config.incLong);
invariant(coll);
@@ -1363,13 +1363,14 @@ public:
const WhereCallbackReal whereCallback(txn, nss.db());
- auto statusWithCQ = CanonicalQuery::canonicalize(
- config.ns, config.filter, config.sort, BSONObj(), whereCallback);
- if (!statusWithCQ.isOK()) {
+ CanonicalQuery* cqRaw;
+ if (!CanonicalQuery::canonicalize(
+ config.ns, config.filter, config.sort, BSONObj(), &cqRaw, whereCallback)
+ .isOK()) {
uasserted(17238, "Can't canonicalize query " + config.filter.toString());
return 0;
}
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ std::unique_ptr<CanonicalQuery> cq(cqRaw);
Database* db = scopedAutoDb->getDb();
Collection* coll = state.getCollectionOrUassert(db, config.ns);
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index 2232632c9a5..1fc0b40493c 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -169,9 +169,10 @@ Status PlanCacheCommand::checkAuthForCommand(ClientBasic* client,
}
// static
-StatusWith<unique_ptr<CanonicalQuery>> PlanCacheCommand::canonicalize(OperationContext* txn,
- const string& ns,
- const BSONObj& cmdObj) {
+Status PlanCacheCommand::canonicalize(OperationContext* txn,
+ const string& ns,
+ const BSONObj& cmdObj,
+ CanonicalQuery** canonicalQueryOut) {
// query - required
BSONElement queryElt = cmdObj.getField("query");
if (queryElt.eoo()) {
@@ -206,15 +207,19 @@ StatusWith<unique_ptr<CanonicalQuery>> PlanCacheCommand::canonicalize(OperationC
}
// Create canonical query
+ CanonicalQuery* cqRaw;
+
const NamespaceString nss(ns);
const WhereCallbackReal whereCallback(txn, nss.db());
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ Status result =
+ CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, &cqRaw, whereCallback);
+ if (!result.isOK()) {
+ return result;
}
- return std::move(statusWithCQ.getValue());
+ *canonicalQueryOut = cqRaw;
+ return Status::OK();
}
PlanCacheListQueryShapes::PlanCacheListQueryShapes()
@@ -299,12 +304,13 @@ Status PlanCacheClear::clear(OperationContext* txn,
// - clear plans for single query shape when a query shape is described in the
// command arguments.
if (cmdObj.hasField("query")) {
- auto statusWithCQ = PlanCacheCommand::canonicalize(txn, ns, cmdObj);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cqRaw;
+ Status status = PlanCacheCommand::canonicalize(txn, ns, cmdObj, &cqRaw);
+ if (!status.isOK()) {
+ return status;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ unique_ptr<CanonicalQuery> cq(cqRaw);
if (!planCache->contains(*cq)) {
// Log if asked to clear non-existent query shape.
@@ -368,11 +374,13 @@ Status PlanCacheListPlans::list(OperationContext* txn,
const std::string& ns,
const BSONObj& cmdObj,
BSONObjBuilder* bob) {
- auto statusWithCQ = canonicalize(txn, ns, cmdObj);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cqRaw;
+ Status status = canonicalize(txn, ns, cmdObj, &cqRaw);
+ if (!status.isOK()) {
+ return status;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+
+ unique_ptr<CanonicalQuery> cq(cqRaw);
if (!planCache.contains(*cq)) {
// Return empty plans in results if query shape does not
diff --git a/src/mongo/db/commands/plan_cache_commands.h b/src/mongo/db/commands/plan_cache_commands.h
index d42773f42e7..3858704dbde 100644
--- a/src/mongo/db/commands/plan_cache_commands.h
+++ b/src/mongo/db/commands/plan_cache_commands.h
@@ -94,9 +94,10 @@ public:
/**
* Validatess query shape from command object and returns canonical query.
*/
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(OperationContext* txn,
- const std::string& ns,
- const BSONObj& cmdObj);
+ static Status canonicalize(OperationContext* txn,
+ const std::string& ns,
+ const BSONObj& cmdObj,
+ CanonicalQuery** canonicalQueryOut);
private:
std::string helpText;
diff --git a/src/mongo/db/commands/plan_cache_commands_test.cpp b/src/mongo/db/commands/plan_cache_commands_test.cpp
index c1216ea197d..8a7eee783d8 100644
--- a/src/mongo/db/commands/plan_cache_commands_test.cpp
+++ b/src/mongo/db/commands/plan_cache_commands_test.cpp
@@ -125,9 +125,9 @@ TEST(PlanCacheCommandsTest, planCacheListQueryShapesEmpty) {
TEST(PlanCacheCommandsTest, planCacheListQueryShapesOneKey) {
// Create a canonical query
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Plan cache with one entry
PlanCache planCache;
@@ -150,9 +150,9 @@ TEST(PlanCacheCommandsTest, planCacheListQueryShapesOneKey) {
TEST(PlanCacheCommandsTest, planCacheClearAllShapes) {
// Create a canonical query
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Plan cache with one entry
PlanCache planCache;
@@ -178,57 +178,52 @@ TEST(PlanCacheCommandsTest, planCacheClearAllShapes) {
TEST(PlanCacheCommandsTest, Canonicalize) {
// Invalid parameters
PlanCache planCache;
+ CanonicalQuery* cqRaw;
OperationContextNoop txn;
// Missing query field
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{}")).getStatus());
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{}"), &cqRaw));
// Query needs to be an object
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: 1}")).getStatus());
+ ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: 1}"), &cqRaw));
// Sort needs to be an object
ASSERT_NOT_OK(
- PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: 1}")).getStatus());
+ PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: 1}"), &cqRaw));
// Bad query (invalid sort order)
- ASSERT_NOT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: {a: 0}}"))
- .getStatus());
+ ASSERT_NOT_OK(
+ PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {}, sort: {a: 0}}"), &cqRaw));
// Valid parameters
- auto statusWithCQ = PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {a: 1, b: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> query = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {a: 1, b: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> query(cqRaw);
// Equivalent query should generate same key.
- statusWithCQ = PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {b: 1, a: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> equivQuery = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {b: 1, a: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> equivQuery(cqRaw);
ASSERT_EQUALS(planCache.computeKey(*query), planCache.computeKey(*equivQuery));
// Sort query should generate different key from unsorted query.
- statusWithCQ = PlanCacheCommand::canonicalize(
- &txn, ns, fromjson("{query: {a: 1, b: 1}, sort: {a: 1, b: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> sortQuery1 = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(
+ &txn, ns, fromjson("{query: {a: 1, b: 1}, sort: {a: 1, b: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> sortQuery1(cqRaw);
ASSERT_NOT_EQUALS(planCache.computeKey(*query), planCache.computeKey(*sortQuery1));
// Confirm sort arguments are properly delimited (SERVER-17158)
- statusWithCQ =
- PlanCacheCommand::canonicalize(&txn, ns, fromjson("{query: {a: 1, b: 1}, sort: {aab: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> sortQuery2 = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(
+ &txn, ns, fromjson("{query: {a: 1, b: 1}, sort: {aab: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> sortQuery2(cqRaw);
ASSERT_NOT_EQUALS(planCache.computeKey(*sortQuery1), planCache.computeKey(*sortQuery2));
// Changing order and/or value of predicates should not change key
- statusWithCQ = PlanCacheCommand::canonicalize(
- &txn, ns, fromjson("{query: {b: 3, a: 3}, sort: {a: 1, b: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> sortQuery3 = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(
+ &txn, ns, fromjson("{query: {b: 3, a: 3}, sort: {a: 1, b: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> sortQuery3(cqRaw);
ASSERT_EQUALS(planCache.computeKey(*sortQuery1), planCache.computeKey(*sortQuery3));
// Projected query should generate different key from unprojected query.
- statusWithCQ = PlanCacheCommand::canonicalize(
- &txn, ns, fromjson("{query: {a: 1, b: 1}, projection: {_id: 0, a: 1}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> projectionQuery = std::move(statusWithCQ.getValue());
+ ASSERT_OK(PlanCacheCommand::canonicalize(
+ &txn, ns, fromjson("{query: {a: 1, b: 1}, projection: {_id: 0, a: 1}}"), &cqRaw));
+ unique_ptr<CanonicalQuery> projectionQuery(cqRaw);
ASSERT_NOT_EQUALS(planCache.computeKey(*query), planCache.computeKey(*projectionQuery));
}
@@ -263,12 +258,11 @@ TEST(PlanCacheCommandsTest, planCacheClearUnknownKey) {
TEST(PlanCacheCommandsTest, planCacheClearOneKey) {
// Create 2 canonical queries.
- auto statusWithCQA = CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"));
- ASSERT_OK(statusWithCQA.getStatus());
- unique_ptr<CanonicalQuery> cqA = std::move(statusWithCQA.getValue());
- auto statusWithCQB = CanonicalQuery::canonicalize(ns, fromjson("{b: 1}"));
- ASSERT_OK(statusWithCQB.getStatus());
- unique_ptr<CanonicalQuery> cqB = std::move(statusWithCQB.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cqA(cqRaw);
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{b: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cqB(cqRaw);
// Create plan cache with 2 entries.
PlanCache planCache;
@@ -383,9 +377,9 @@ TEST(PlanCacheCommandsTest, planCacheListPlansUnknownKey) {
TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionTrue) {
// Create a canonical query
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Plan cache with one entry
PlanCache planCache;
@@ -402,9 +396,9 @@ TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionTrue) {
TEST(PlanCacheCommandsTest, planCacheListPlansOnlyOneSolutionFalse) {
// Create a canonical query
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cqRaw;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns, fromjson("{a: 1}"), &cqRaw));
+ unique_ptr<CanonicalQuery> cq(cqRaw);
// Plan cache with one entry
PlanCache planCache;
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index ba7e84b6e31..935b4ec41f6 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -587,12 +587,11 @@ public:
BSONObj sort = BSON("files_id" << 1 << "n" << 1);
MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, query, sort, BSONObj());
- if (!statusWithCQ.isOK()) {
+ CanonicalQuery* cq;
+ if (!CanonicalQuery::canonicalize(ns, query, sort, BSONObj(), &cq).isOK()) {
uasserted(17240, "Can't canonicalize query " + query.toString());
return 0;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
// Check shard version at startup.
// This will throw before we've done any work if shard version is outdated
@@ -603,7 +602,7 @@ public:
PlanExecutor* rawExec;
if (!getExecutor(txn,
coll,
- cq.release(),
+ cq,
PlanExecutor::YIELD_MANUAL,
&rawExec,
QueryPlannerParams::NO_TABLE_SCAN).isOK()) {
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 0517552c7c2..e5e198d7ff0 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -129,19 +129,18 @@ RecordId Helpers::findOne(OperationContext* txn,
if (!collection)
return RecordId();
+ CanonicalQuery* cq;
const WhereCallbackReal whereCallback(txn, collection->ns().db());
- auto statusWithCQ = CanonicalQuery::canonicalize(collection->ns(), query, whereCallback);
- massert(17244, "Could not canonicalize " + query.toString(), statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ massert(17244,
+ "Could not canonicalize " + query.toString(),
+ CanonicalQuery::canonicalize(collection->ns(), query, &cq, whereCallback).isOK());
PlanExecutor* rawExec;
size_t options = requireIndex ? QueryPlannerParams::NO_TABLE_SCAN : QueryPlannerParams::DEFAULT;
- massert(
- 17245,
- "Could not get executor for query " + query.toString(),
- getExecutor(txn, collection, cq.release(), PlanExecutor::YIELD_MANUAL, &rawExec, options)
- .isOK());
+ massert(17245,
+ "Could not get executor for query " + query.toString(),
+ getExecutor(txn, collection, cq, PlanExecutor::YIELD_MANUAL, &rawExec, options).isOK());
unique_ptr<PlanExecutor> exec(rawExec);
PlanExecutor::ExecState state;
diff --git a/src/mongo/db/exec/sort.cpp b/src/mongo/db/exec/sort.cpp
index 7aeef7ee68b..7a98b5113c2 100644
--- a/src/mongo/db/exec/sort.cpp
+++ b/src/mongo/db/exec/sort.cpp
@@ -226,10 +226,10 @@ void SortStageKeyGenerator::getBoundsForSort(const BSONObj& queryObj, const BSON
sortObj, IndexNames::BTREE, true, false, false, "doesnt_matter", NULL, BSONObj());
params.indices.push_back(sortOrder);
- auto statusWithQueryForSort =
- CanonicalQuery::canonicalize("fake_ns", queryObj, WhereCallbackNoop());
- verify(statusWithQueryForSort.isOK());
- unique_ptr<CanonicalQuery> queryForSort = std::move(statusWithQueryForSort.getValue());
+ CanonicalQuery* rawQueryForSort;
+ verify(CanonicalQuery::canonicalize("fake_ns", queryObj, &rawQueryForSort, WhereCallbackNoop())
+ .isOK());
+ unique_ptr<CanonicalQuery> queryForSort(rawQueryForSort);
vector<QuerySolution*> solns;
LOG(5) << "Sort stage: Planning to obtain bounds for sort." << endl;
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index a5b33be1ba9..62daed09f32 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -130,23 +130,27 @@ Status SubplanStage::planSubqueries() {
MatchExpression* orChild = orExpr->getChild(i);
// Turn the i-th child into its own query.
- auto statusWithCQ = CanonicalQuery::canonicalize(*_query, orChild, whereCallback);
- if (!statusWithCQ.isOK()) {
- mongoutils::str::stream ss;
- ss << "Can't canonicalize subchild " << orChild->toString() << " "
- << statusWithCQ.getStatus().reason();
- return Status(ErrorCodes::BadValue, ss);
- }
+ {
+ CanonicalQuery* orChildCQ;
+ Status childCQStatus =
+ CanonicalQuery::canonicalize(*_query, orChild, &orChildCQ, whereCallback);
+ if (!childCQStatus.isOK()) {
+ mongoutils::str::stream ss;
+ ss << "Can't canonicalize subchild " << orChild->toString() << " "
+ << childCQStatus.reason();
+ return Status(ErrorCodes::BadValue, ss);
+ }
- branchResult->canonicalQuery = std::move(statusWithCQ.getValue());
+ branchResult->canonicalQuery.reset(orChildCQ);
+ }
// Plan the i-th child. We might be able to find a plan for the i-th child in the plan
// cache. If there's no cached plan, then we generate and rank plans using the MPS.
CachedSolution* rawCS;
- if (PlanCache::shouldCacheQuery(*branchResult->canonicalQuery) &&
+ if (PlanCache::shouldCacheQuery(*branchResult->canonicalQuery.get()) &&
_collection->infoCache()
->getPlanCache()
- ->get(*branchResult->canonicalQuery, &rawCS)
+ ->get(*branchResult->canonicalQuery.get(), &rawCS)
.isOK()) {
// We have a CachedSolution. Store it for later.
LOG(5) << "Subplanner: cached plan found for child " << i << " of "
@@ -159,7 +163,7 @@ Status SubplanStage::planSubqueries() {
// We don't set NO_TABLE_SCAN because peeking at the cache data will keep us from
// considering any plan that's a collscan.
- Status status = QueryPlanner::plan(*branchResult->canonicalQuery,
+ Status status = QueryPlanner::plan(*branchResult->canonicalQuery.get(),
_plannerParams,
&branchResult->solutions.mutableVector());
diff --git a/src/mongo/db/exec/update.cpp b/src/mongo/db/exec/update.cpp
index e37d716d338..7d2a768664f 100644
--- a/src/mongo/db/exec/update.cpp
+++ b/src/mongo/db/exec/update.cpp
@@ -619,7 +619,7 @@ Status UpdateStage::applyUpdateOpsForInsert(const CanonicalQuery* cq,
BSONObj original;
if (cq) {
- Status status = driver->populateDocumentWithQueryFields(*cq, immutablePaths, *doc);
+ Status status = driver->populateDocumentWithQueryFields(cq, immutablePaths, *doc);
if (!status.isOK()) {
return status;
}
diff --git a/src/mongo/db/ops/parsed_delete.cpp b/src/mongo/db/ops/parsed_delete.cpp
index ddb24fa2faf..46a2a33752d 100644
--- a/src/mongo/db/ops/parsed_delete.cpp
+++ b/src/mongo/db/ops/parsed_delete.cpp
@@ -69,6 +69,7 @@ Status ParsedDelete::parseRequest() {
Status ParsedDelete::parseQueryToCQ() {
dassert(!_canonicalQuery.get());
+ CanonicalQuery* cqRaw;
const WhereCallbackReal whereCallback(_txn, _request->getNamespaceString().db());
// Limit should only used for the findAndModify command when a sort is specified. If a sort
@@ -82,24 +83,25 @@ Status ParsedDelete::parseQueryToCQ() {
// The projection needs to be applied after the delete operation, so we specify an empty
// BSONObj as the projection during canonicalization.
const BSONObj emptyObj;
- auto statusWithCQ = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
- _request->getQuery(),
- _request->getSort(),
- emptyObj, // projection
- 0, // skip
- limit,
- emptyObj, // hint
- emptyObj, // min
- emptyObj, // max
- false, // snapshot
- _request->isExplain(),
- whereCallback);
-
- if (statusWithCQ.isOK()) {
- _canonicalQuery = std::move(statusWithCQ.getValue());
+ Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
+ _request->getQuery(),
+ _request->getSort(),
+ emptyObj, // projection
+ 0, // skip
+ limit,
+ emptyObj, // hint
+ emptyObj, // min
+ emptyObj, // max
+ false, // snapshot
+ _request->isExplain(),
+ &cqRaw,
+ whereCallback);
+
+ if (status.isOK()) {
+ _canonicalQuery.reset(cqRaw);
}
- return statusWithCQ.getStatus();
+ return status;
}
const DeleteRequest* ParsedDelete::getRequest() const {
@@ -121,9 +123,9 @@ bool ParsedDelete::hasParsedQuery() const {
return _canonicalQuery.get() != NULL;
}
-std::unique_ptr<CanonicalQuery> ParsedDelete::releaseParsedQuery() {
+CanonicalQuery* ParsedDelete::releaseParsedQuery() {
invariant(_canonicalQuery.get() != NULL);
- return std::move(_canonicalQuery);
+ return _canonicalQuery.release();
}
} // namespace mongo
diff --git a/src/mongo/db/ops/parsed_delete.h b/src/mongo/db/ops/parsed_delete.h
index cdf22b4cac7..0745cbb85e8 100644
--- a/src/mongo/db/ops/parsed_delete.h
+++ b/src/mongo/db/ops/parsed_delete.h
@@ -102,7 +102,7 @@ public:
/**
* Releases ownership of the canonical query to the caller.
*/
- std::unique_ptr<CanonicalQuery> releaseParsedQuery();
+ CanonicalQuery* releaseParsedQuery();
private:
// Transactional context. Not owned by us.
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index 41b010f1d68..80138e0385d 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -73,6 +73,7 @@ Status ParsedUpdate::parseQuery() {
Status ParsedUpdate::parseQueryToCQ() {
dassert(!_canonicalQuery.get());
+ CanonicalQuery* cqRaw;
const WhereCallbackReal whereCallback(_txn, _request->getNamespaceString().db());
// Limit should only used for the findAndModify command when a sort is specified. If a sort
@@ -86,23 +87,24 @@ Status ParsedUpdate::parseQueryToCQ() {
// The projection needs to be applied after the update operation, so we specify an empty
// BSONObj as the projection during canonicalization.
const BSONObj emptyObj;
- auto statusWithCQ = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
- _request->getQuery(),
- _request->getSort(),
- emptyObj, // projection
- 0, // skip
- limit,
- emptyObj, // hint
- emptyObj, // min
- emptyObj, // max
- false, // snapshot
- _request->isExplain(),
- whereCallback);
- if (statusWithCQ.isOK()) {
- _canonicalQuery = std::move(statusWithCQ.getValue());
+ Status status = CanonicalQuery::canonicalize(_request->getNamespaceString().ns(),
+ _request->getQuery(),
+ _request->getSort(),
+ emptyObj, // projection
+ 0, // skip
+ limit,
+ emptyObj, // hint
+ emptyObj, // min
+ emptyObj, // max
+ false, // snapshot
+ _request->isExplain(),
+ &cqRaw,
+ whereCallback);
+ if (status.isOK()) {
+ _canonicalQuery.reset(cqRaw);
}
- return statusWithCQ.getStatus();
+ return status;
}
Status ParsedUpdate::parseUpdate() {
@@ -136,9 +138,9 @@ bool ParsedUpdate::hasParsedQuery() const {
return _canonicalQuery.get() != NULL;
}
-std::unique_ptr<CanonicalQuery> ParsedUpdate::releaseParsedQuery() {
+CanonicalQuery* ParsedUpdate::releaseParsedQuery() {
invariant(_canonicalQuery.get() != NULL);
- return std::move(_canonicalQuery);
+ return _canonicalQuery.release();
}
const UpdateRequest* ParsedUpdate::getRequest() const {
diff --git a/src/mongo/db/ops/parsed_update.h b/src/mongo/db/ops/parsed_update.h
index 3c0cf015c94..8ce08aaabc3 100644
--- a/src/mongo/db/ops/parsed_update.h
+++ b/src/mongo/db/ops/parsed_update.h
@@ -107,7 +107,7 @@ public:
/**
* Releases ownership of the canonical query to the caller.
*/
- std::unique_ptr<CanonicalQuery> releaseParsedQuery();
+ CanonicalQuery* releaseParsedQuery();
private:
/**
diff --git a/src/mongo/db/ops/update_driver.cpp b/src/mongo/db/ops/update_driver.cpp
index 9045b691e16..ccd966dbb81 100644
--- a/src/mongo/db/ops/update_driver.cpp
+++ b/src/mongo/db/ops/update_driver.cpp
@@ -169,19 +169,18 @@ inline Status UpdateDriver::addAndParse(const modifiertable::ModifierType type,
Status UpdateDriver::populateDocumentWithQueryFields(const BSONObj& query,
const vector<FieldRef*>* immutablePaths,
mutablebson::Document& doc) const {
+ CanonicalQuery* rawCG;
// We canonicalize the query to collapse $and/$or, and the first arg (ns) is not needed
// Also, because this is for the upsert case, where we insert a new document if one was
// not found, the $where clause does not make sense, hence empty WhereCallback.
- auto statusWithCQ = CanonicalQuery::canonicalize("", query, WhereCallbackNoop());
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
- }
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
-
- return populateDocumentWithQueryFields(*cq, immutablePaths, doc);
+ Status s = CanonicalQuery::canonicalize("", query, &rawCG, WhereCallbackNoop());
+ if (!s.isOK())
+ return s;
+ unique_ptr<CanonicalQuery> cq(rawCG);
+ return populateDocumentWithQueryFields(rawCG, immutablePaths, doc);
}
-Status UpdateDriver::populateDocumentWithQueryFields(const CanonicalQuery& query,
+Status UpdateDriver::populateDocumentWithQueryFields(const CanonicalQuery* query,
const vector<FieldRef*>* immutablePathsPtr,
mutablebson::Document& doc) const {
EqualityMatches equalities;
@@ -201,10 +200,10 @@ Status UpdateDriver::populateDocumentWithQueryFields(const CanonicalQuery& query
// Extract only immutable fields from replacement-style
status =
- pathsupport::extractFullEqualityMatches(*query.root(), pathsToExtract, &equalities);
+ pathsupport::extractFullEqualityMatches(*query->root(), pathsToExtract, &equalities);
} else {
// Extract all fields from op-style
- status = pathsupport::extractEqualityMatches(*query.root(), &equalities);
+ status = pathsupport::extractEqualityMatches(*query->root(), &equalities);
}
if (!status.isOK())
diff --git a/src/mongo/db/ops/update_driver.h b/src/mongo/db/ops/update_driver.h
index bb11ee42bb4..00e3e2eb10f 100644
--- a/src/mongo/db/ops/update_driver.h
+++ b/src/mongo/db/ops/update_driver.h
@@ -71,7 +71,7 @@ public:
const std::vector<FieldRef*>* immutablePaths,
mutablebson::Document& doc) const;
- Status populateDocumentWithQueryFields(const CanonicalQuery& query,
+ Status populateDocumentWithQueryFields(const CanonicalQuery* query,
const std::vector<FieldRef*>* immutablePaths,
mutablebson::Document& doc) const;
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index 0a10cfc5f3d..6dbcfe4c812 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -48,7 +48,6 @@ namespace mongo {
using boost::intrusive_ptr;
using std::shared_ptr;
using std::string;
-using std::unique_ptr;
namespace {
class MongodImplementation final : public DocumentSourceNeedsMongod::MongodInterface {
@@ -181,17 +180,14 @@ shared_ptr<PlanExecutor> PipelineD::prepareCursorSource(
const WhereCallbackReal whereCallback(pExpCtx->opCtx, pExpCtx->ns.db());
if (sortStage) {
- auto statusWithCQ = CanonicalQuery::canonicalize(
- pExpCtx->ns, queryObj, sortObj, projectionForQuery, whereCallback);
+ CanonicalQuery* cq;
+ Status status = CanonicalQuery::canonicalize(
+ pExpCtx->ns, queryObj, sortObj, projectionForQuery, &cq, whereCallback);
PlanExecutor* rawExec;
- if (statusWithCQ.isOK() &&
- getExecutor(txn,
- collection,
- statusWithCQ.getValue().release(),
- PlanExecutor::YIELD_AUTO,
- &rawExec,
- runnerOptions).isOK()) {
+ if (status.isOK() &&
+ getExecutor(txn, collection, cq, PlanExecutor::YIELD_AUTO, &rawExec, runnerOptions)
+ .isOK()) {
// success: The PlanExecutor will handle sorting for us using an index.
exec.reset(rawExec);
sortInRunner = true;
@@ -206,14 +202,13 @@ shared_ptr<PlanExecutor> PipelineD::prepareCursorSource(
if (!exec.get()) {
const BSONObj noSort;
- auto statusWithCQ = CanonicalQuery::canonicalize(
- pExpCtx->ns, queryObj, noSort, projectionForQuery, whereCallback);
- uassertStatusOK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ uassertStatusOK(CanonicalQuery::canonicalize(
+ pExpCtx->ns, queryObj, noSort, projectionForQuery, &cq, whereCallback));
PlanExecutor* rawExec;
- uassertStatusOK(getExecutor(
- txn, collection, cq.release(), PlanExecutor::YIELD_AUTO, &rawExec, runnerOptions));
+ uassertStatusOK(
+ getExecutor(txn, collection, cq, PlanExecutor::YIELD_AUTO, &rawExec, runnerOptions));
exec.reset(rawExec);
}
diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp
index 701a5fd2545..ac6ba1627d1 100644
--- a/src/mongo/db/query/canonical_query.cpp
+++ b/src/mongo/db/query/canonical_query.cpp
@@ -100,20 +100,20 @@ bool matchExpressionLessThan(const MatchExpression* lhs, const MatchExpression*
//
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const std::string& ns,
- const BSONObj& query,
- const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
const BSONObj emptyObj;
- return CanonicalQuery::canonicalize(ns, query, emptyObj, emptyObj, 0, 0, whereCallback);
+ return CanonicalQuery::canonicalize(ns, query, emptyObj, emptyObj, 0, 0, out, whereCallback);
}
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const std::string& ns,
- const BSONObj& query,
- bool explain,
- const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ bool explain,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
const BSONObj emptyObj;
return CanonicalQuery::canonicalize(ns,
query,
@@ -126,54 +126,56 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
emptyObj, // max
false, // snapshot
explain,
+ out,
whereCallback);
}
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const std::string& ns,
- const BSONObj& query,
- long long skip,
- long long limit,
- const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ long long skip,
+ long long limit,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
const BSONObj emptyObj;
- return CanonicalQuery::canonicalize(ns, query, emptyObj, emptyObj, skip, limit, whereCallback);
+ return CanonicalQuery::canonicalize(
+ ns, query, emptyObj, emptyObj, skip, limit, out, whereCallback);
}
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const std::string& ns,
- const BSONObj& query,
- const BSONObj& sort,
- const BSONObj& proj,
- const MatchExpressionParser::WhereCallback& whereCallback) {
- return CanonicalQuery::canonicalize(ns, query, sort, proj, 0, 0, whereCallback);
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
+ return CanonicalQuery::canonicalize(ns, query, sort, proj, 0, 0, out, whereCallback);
}
// 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 MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ long long skip,
+ long long limit,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
const BSONObj emptyObj;
return CanonicalQuery::canonicalize(
- ns, query, sort, proj, skip, limit, emptyObj, whereCallback);
+ ns, query, sort, proj, skip, limit, emptyObj, out, whereCallback);
}
// 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 MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ long long skip,
+ long long limit,
+ const BSONObj& hint,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
const BSONObj emptyObj;
return CanonicalQuery::canonicalize(ns,
query,
@@ -186,6 +188,7 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
emptyObj,
false, // snapshot
false, // explain
+ out,
whereCallback);
}
@@ -194,20 +197,22 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
//
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const QueryMessage& qm, const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const QueryMessage& qm,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
// Make LiteParsedQuery.
auto lpqStatus = LiteParsedQuery::fromLegacyQueryMessage(qm);
if (!lpqStatus.isOK()) {
return lpqStatus.getStatus();
}
- return CanonicalQuery::canonicalize(lpqStatus.getValue().release(), whereCallback);
+ return CanonicalQuery::canonicalize(lpqStatus.getValue().release(), out, whereCallback);
}
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- LiteParsedQuery* lpq, const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(LiteParsedQuery* lpq,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
std::unique_ptr<LiteParsedQuery> autoLpq(lpq);
// Make MatchExpression.
@@ -226,14 +231,15 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
if (!initStatus.isOK()) {
return initStatus;
}
- return std::move(cq);
+ *out = cq.release();
+ return Status::OK();
}
// static
-StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
- const CanonicalQuery& baseQuery,
- MatchExpression* root,
- const MatchExpressionParser::WhereCallback& whereCallback) {
+Status CanonicalQuery::canonicalize(const CanonicalQuery& baseQuery,
+ MatchExpression* root,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
// Pass empty sort and projection.
BSONObj emptyObj;
@@ -263,23 +269,24 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
if (!initStatus.isOK()) {
return initStatus;
}
- return std::move(cq);
+ *out = cq.release();
+ return Status::OK();
}
// 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) {
+Status 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,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback) {
// Pass empty sort and projection.
BSONObj emptyObj;
@@ -305,7 +312,8 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize(
if (!initStatus.isOK()) {
return initStatus;
}
- return std::move(cq);
+ *out = cq.release();
+ return Status::OK();
}
Status CanonicalQuery::init(LiteParsedQuery* lpq,
diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h
index 56f06a20c9d..58a2c46f3a8 100644
--- a/src/mongo/db/query/canonical_query.h
+++ b/src/mongo/db/query/canonical_query.h
@@ -41,28 +41,26 @@ namespace mongo {
class CanonicalQuery {
public:
/**
- * If parsing succeeds, returns a std::unique_ptr<CanonicalQuery> representing the parsed
- * query (which will never be NULL). If parsing fails, returns an error Status.
+ * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK().
*
* Used for legacy find through the OP_QUERY message.
*/
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const QueryMessage& qm,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
+ static Status canonicalize(const QueryMessage& qm,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
/**
* Takes ownership of 'lpq'.
*
- * If parsing succeeds, returns a std::unique_ptr<CanonicalQuery> representing the parsed
- * query (which will never be NULL). If parsing fails, returns an error Status.
+ * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK().
*
* Used for finds using the find command path.
*/
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- LiteParsedQuery* lpq,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
+ static Status canonicalize(LiteParsedQuery* lpq,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
/**
* For testing or for internal clients to use.
@@ -75,76 +73,76 @@ public:
*
* Does not take ownership of 'root'.
*/
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const CanonicalQuery& baseQuery,
- MatchExpression* root,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const std::string& ns,
- const BSONObj& query,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const std::string& ns,
- const BSONObj& query,
- bool explain,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const std::string& ns,
- const BSONObj& query,
- long long skip,
- long long limit,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const std::string& ns,
- const BSONObj& query,
- const BSONObj& sort,
- const BSONObj& proj,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize(
- const std::string& ns,
- const BSONObj& query,
- const BSONObj& sort,
- const BSONObj& proj,
- long long skip,
- long long limit,
- const MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<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 MatchExpressionParser::WhereCallback& whereCallback =
- MatchExpressionParser::WhereCallback());
-
- static StatusWith<std::unique_ptr<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 =
- MatchExpressionParser::WhereCallback());
+ static Status canonicalize(const CanonicalQuery& baseQuery,
+ MatchExpression* root,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ bool explain,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ long long skip,
+ long long limit,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ long long skip,
+ long long limit,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status canonicalize(const std::string& ns,
+ const BSONObj& query,
+ const BSONObj& sort,
+ const BSONObj& proj,
+ long long skip,
+ long long limit,
+ const BSONObj& hint,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
+
+ static Status 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,
+ CanonicalQuery** out,
+ const MatchExpressionParser::WhereCallback& whereCallback =
+ MatchExpressionParser::WhereCallback());
/**
* Returns true if "query" describes an exact-match query on _id, possibly with
diff --git a/src/mongo/db/query/canonical_query_test.cpp b/src/mongo/db/query/canonical_query_test.cpp
index 8036dac3adb..d3fb9a55fd4 100644
--- a/src/mongo/db/query/canonical_query_test.cpp
+++ b/src/mongo/db/query/canonical_query_test.cpp
@@ -35,6 +35,7 @@ namespace mongo {
namespace {
using std::string;
+using std::unique_ptr;
using unittest::assertGet;
static const char* ns = "somebogusns";
@@ -51,7 +52,6 @@ MatchExpression* parseMatchExpression(const BSONObj& obj) {
<< ". Reason: " << status.getStatus().toString();
FAIL(ss);
}
-
return status.getValue();
}
@@ -62,7 +62,8 @@ MatchExpression* parseMatchExpression(const BSONObj& obj) {
*/
Status isValid(const std::string& queryStr, const LiteParsedQuery& lpqRaw) {
BSONObj queryObj = fromjson(queryStr);
- unique_ptr<MatchExpression> me(CanonicalQuery::normalizeTree(parseMatchExpression(queryObj)));
+ std::unique_ptr<MatchExpression> me(
+ CanonicalQuery::normalizeTree(parseMatchExpression(queryObj)));
return CanonicalQuery::isValid(me.get(), lpqRaw);
}
@@ -460,22 +461,22 @@ TEST(CanonicalQueryTest, SortTreeNumChildrenComparison) {
/**
* Utility function to create a CanonicalQuery
*/
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr) {
+CanonicalQuery* canonicalize(const char* queryStr) {
BSONObj queryObj = fromjson(queryStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns, queryObj, &cq);
+ ASSERT_OK(result);
+ return cq;
}
-std::unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
- const char* sortStr,
- const char* projStr) {
+CanonicalQuery* canonicalize(const char* queryStr, const char* sortStr, const char* projStr) {
BSONObj queryObj = fromjson(queryStr);
BSONObj sortObj = fromjson(sortStr);
BSONObj projObj = fromjson(projStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, &cq);
+ ASSERT_OK(result);
+ return cq;
}
// Don't do anything with a double OR.
diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp
index 2283bc66e9f..f170dc8ea04 100644
--- a/src/mongo/db/query/find.cpp
+++ b/src/mongo/db/query/find.cpp
@@ -278,9 +278,9 @@ QueryResult::View getMore(OperationContext* txn,
// Note that we declare our locks before our ClientCursorPin, in order to ensure that the
// pin's destructor is called before the lock destructors (so that the unpin occurs under
// the lock).
- unique_ptr<AutoGetCollectionForRead> ctx;
- unique_ptr<Lock::DBLock> unpinDBLock;
- unique_ptr<Lock::CollectionLock> unpinCollLock;
+ std::unique_ptr<AutoGetCollectionForRead> ctx;
+ std::unique_ptr<Lock::DBLock> unpinDBLock;
+ std::unique_ptr<Lock::CollectionLock> unpinCollLock;
CursorManager* cursorManager;
CursorManager* globalCursorManager = CursorManager::getGlobalCursorManager();
@@ -315,7 +315,7 @@ QueryResult::View getMore(OperationContext* txn,
// has a valid RecoveryUnit. As such, we use RAII to accomplish this.
//
// This must be destroyed before the ClientCursor is destroyed.
- unique_ptr<ScopedRecoveryUnitSwapper> ruSwapper;
+ std::unique_ptr<ScopedRecoveryUnitSwapper> ruSwapper;
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
@@ -416,7 +416,7 @@ QueryResult::View getMore(OperationContext* txn,
if (PlanExecutor::DEAD == state || PlanExecutor::FAILURE == state) {
// Propagate this error to caller.
- const unique_ptr<PlanStageStats> stats(exec->getStats());
+ const std::unique_ptr<PlanStageStats> stats(exec->getStats());
error() << "getMore executor error, stats: " << Explain::statsToBSON(*stats);
uasserted(17406, "getMore executor error: " + WorkingSetCommon::toStatusString(obj));
}
@@ -506,14 +506,17 @@ std::string runQuery(OperationContext* txn,
beginQueryOp(txn, nss, q.query, q.ntoreturn, q.ntoskip);
// Parse the qm into a CanonicalQuery.
-
- auto statusWithCQ = CanonicalQuery::canonicalize(q, WhereCallbackReal(txn, nss.db()));
- if (!statusWithCQ.isOK()) {
- uasserted(
- 17287,
- str::stream() << "Can't canonicalize query: " << statusWithCQ.getStatus().toString());
+ std::unique_ptr<CanonicalQuery> cq;
+ {
+ CanonicalQuery* cqRaw;
+ Status canonStatus =
+ CanonicalQuery::canonicalize(q, &cqRaw, WhereCallbackReal(txn, nss.db()));
+ if (!canonStatus.isOK()) {
+ uasserted(17287,
+ str::stream() << "Can't canonicalize query: " << canonStatus.toString());
+ }
+ cq.reset(cqRaw);
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
invariant(cq.get());
LOG(5) << "Running query:\n" << cq->toString();
@@ -527,7 +530,7 @@ std::string runQuery(OperationContext* txn,
ctx.getDb() ? ctx.getDb()->getProfilingLevel() : serverGlobalParams.defaultProfile;
// We have a parsed query. Time to get the execution plan for it.
- unique_ptr<PlanExecutor> exec;
+ std::unique_ptr<PlanExecutor> exec;
{
PlanExecutor* rawExec;
Status execStatus =
@@ -633,7 +636,7 @@ std::string runQuery(OperationContext* txn,
// Caller expects exceptions thrown in certain cases.
if (PlanExecutor::FAILURE == state || PlanExecutor::DEAD == state) {
- const unique_ptr<PlanStageStats> stats(exec->getStats());
+ const std::unique_ptr<PlanStageStats> stats(exec->getStats());
error() << "Plan executor error during find: " << PlanExecutor::statestr(state)
<< ", stats: " << Explain::statsToBSON(*stats);
uasserted(17144, "Executor error: " + WorkingSetCommon::toStatusString(obj));
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index a098175b112..1472d6693ae 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -467,15 +467,14 @@ Status getExecutor(OperationContext* txn,
if (!CanonicalQuery::isSimpleIdQuery(unparsedQuery) ||
!collection->getIndexCatalog()->findIdIndex(txn)) {
const WhereCallbackReal whereCallback(txn, collection->ns().db());
- auto statusWithCQ =
- CanonicalQuery::canonicalize(collection->ns(), unparsedQuery, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
- }
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status status =
+ CanonicalQuery::canonicalize(collection->ns(), unparsedQuery, &cq, whereCallback);
+ if (!status.isOK())
+ return status;
// Takes ownership of 'cq'.
- return getExecutor(txn, collection, cq.release(), yieldPolicy, out, plannerOptions);
+ return getExecutor(txn, collection, cq, yieldPolicy, out, plannerOptions);
}
LOG(2) << "Using idhack: " << unparsedQuery.toString();
@@ -969,13 +968,13 @@ Status getExecutorGroup(OperationContext* txn,
const NamespaceString nss(request.ns);
const WhereCallbackReal whereCallback(txn, nss.db());
-
- auto statusWithCQ =
- CanonicalQuery::canonicalize(request.ns, request.query, request.explain, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* rawCanonicalQuery;
+ Status canonicalizeStatus = CanonicalQuery::canonicalize(
+ request.ns, request.query, request.explain, &rawCanonicalQuery, whereCallback);
+ if (!canonicalizeStatus.isOK()) {
+ return canonicalizeStatus;
}
- unique_ptr<CanonicalQuery> canonicalQuery = std::move(statusWithCQ.getValue());
+ unique_ptr<CanonicalQuery> canonicalQuery(rawCanonicalQuery);
const size_t defaultPlannerOptions = 0;
Status status = prepareExecution(txn,
@@ -1134,8 +1133,7 @@ std::string getProjectedDottedField(const std::string& field, bool* isIDOut) {
std::vector<std::string> prefixStrings(res);
prefixStrings.resize(i);
// Reset projectedField. Instead of overwriting, joinStringDelim() appends joined
- // string
- // to the end of projectedField.
+ // string to the end of projectedField.
std::string projectedField;
mongo::joinStringDelim(prefixStrings, &projectedField, '.');
return projectedField;
@@ -1202,7 +1200,8 @@ Status getExecutorCount(OperationContext* txn,
if (!request.getQuery().isEmpty() || !request.getHint().isEmpty()) {
// If query or hint is not empty, canonicalize the query before working with collection.
typedef MatchExpressionParser::WhereCallback WhereCallback;
- auto statusWithCQ = CanonicalQuery::canonicalize(
+ CanonicalQuery* rawCq = NULL;
+ Status canonStatus = CanonicalQuery::canonicalize(
request.getNs(),
request.getQuery(),
BSONObj(), // sort
@@ -1214,13 +1213,14 @@ Status getExecutorCount(OperationContext* txn,
BSONObj(), // max
false, // snapshot
explain,
+ &rawCq,
collection
? static_cast<const WhereCallback&>(WhereCallbackReal(txn, collection->ns().db()))
: static_cast<const WhereCallback&>(WhereCallbackNoop()));
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ if (!canonStatus.isOK()) {
+ return canonStatus;
}
- cq = std::move(statusWithCQ.getValue());
+ cq.reset(rawCq);
}
if (!collection) {
@@ -1348,15 +1348,15 @@ Status getExecutorDistinct(OperationContext* txn,
// If there are no suitable indices for the distinct hack bail out now into regular planning
// with no projection.
if (plannerParams.indices.empty()) {
- auto statusWithCQ =
- CanonicalQuery::canonicalize(collection->ns().ns(), query, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cq;
+ Status status =
+ CanonicalQuery::canonicalize(collection->ns().ns(), query, &cq, whereCallback);
+ if (!status.isOK()) {
+ return status;
}
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
// Takes ownership of 'cq'.
- return getExecutor(txn, collection, cq.release(), yieldPolicy, out);
+ return getExecutor(txn, collection, cq, yieldPolicy, out);
}
//
@@ -1369,13 +1369,14 @@ Status getExecutorDistinct(OperationContext* txn,
BSONObj projection = getDistinctProjection(field);
// Apply a projection of the key. Empty BSONObj() is for the sort.
- auto statusWithCQ = CanonicalQuery::canonicalize(
- collection->ns().ns(), query, BSONObj(), projection, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ CanonicalQuery* cq;
+ Status status = CanonicalQuery::canonicalize(
+ collection->ns().ns(), query, BSONObj(), projection, &cq, whereCallback);
+ if (!status.isOK()) {
+ return status;
}
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ unique_ptr<CanonicalQuery> autoCq(cq);
// If there's no query, we can just distinct-scan one of the indices.
// Not every index in plannerParams.indices may be suitable. Refer to
@@ -1402,14 +1403,15 @@ Status getExecutorDistinct(OperationContext* txn,
<< ", planSummary: " << Explain::getPlanSummary(root);
// Takes ownership of its arguments (except for 'collection').
- return PlanExecutor::make(txn, ws, root, soln, cq.release(), collection, yieldPolicy, out);
+ return PlanExecutor::make(
+ txn, ws, root, soln, autoCq.release(), collection, yieldPolicy, out);
}
// See if we can answer the query in a fast-distinct compatible fashion.
vector<QuerySolution*> solutions;
- Status status = QueryPlanner::plan(*cq, plannerParams, &solutions);
+ status = QueryPlanner::plan(*cq, plannerParams, &solutions);
if (!status.isOK()) {
- return getExecutor(txn, collection, cq.release(), yieldPolicy, out);
+ return getExecutor(txn, collection, autoCq.release(), yieldPolicy, out);
}
// We look for a solution that has an ixscan we can turn into a distinctixscan
@@ -1430,9 +1432,9 @@ Status getExecutorDistinct(OperationContext* txn,
LOG(2) << "Using fast distinct: " << cq->toStringShort()
<< ", planSummary: " << Explain::getPlanSummary(root);
- // Takes ownership of 'ws', 'root', 'solutions[i]', and 'cq'.
+ // Takes ownership of 'ws', 'root', 'solutions[i]', and 'autoCq'.
return PlanExecutor::make(
- txn, ws, root, solutions[i], cq.release(), collection, yieldPolicy, out);
+ txn, ws, root, solutions[i], autoCq.release(), collection, yieldPolicy, out);
}
}
@@ -1444,15 +1446,15 @@ Status getExecutorDistinct(OperationContext* txn,
}
// We drop the projection from the 'cq'. Unfortunately this is not trivial.
- statusWithCQ = CanonicalQuery::canonicalize(collection->ns().ns(), query, whereCallback);
- if (!statusWithCQ.isOK()) {
- return statusWithCQ.getStatus();
+ status = CanonicalQuery::canonicalize(collection->ns().ns(), query, &cq, whereCallback);
+ if (!status.isOK()) {
+ return status;
}
- cq = std::move(statusWithCQ.getValue());
+ autoCq.reset(cq);
- // Takes ownership of 'cq'.
- return getExecutor(txn, collection, cq.release(), yieldPolicy, out);
+ // Takes ownership of 'autoCq'.
+ return getExecutor(txn, collection, autoCq.release(), yieldPolicy, out);
}
} // namespace mongo
diff --git a/src/mongo/db/query/get_executor_test.cpp b/src/mongo/db/query/get_executor_test.cpp
index 0e8740fa089..fdc04609df8 100644
--- a/src/mongo/db/query/get_executor_test.cpp
+++ b/src/mongo/db/query/get_executor_test.cpp
@@ -48,15 +48,14 @@ static const char* ns = "somebogusns";
/**
* Utility functions to create a CanonicalQuery
*/
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
- const char* sortStr,
- const char* projStr) {
+CanonicalQuery* canonicalize(const char* queryStr, const char* sortStr, const char* projStr) {
BSONObj queryObj = fromjson(queryStr);
BSONObj sortObj = fromjson(sortStr);
BSONObj projObj = fromjson(projStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, &cq);
+ ASSERT_OK(result);
+ return cq;
}
//
diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp
index 2bee0f5f10b..da15528d243 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -59,77 +59,90 @@ static const char* ns = "somebogusns";
/**
* Utility functions to create a CanonicalQuery
*/
-unique_ptr<CanonicalQuery> canonicalize(const BSONObj& queryObj) {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+CanonicalQuery* canonicalize(const BSONObj& queryObj) {
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns, queryObj, &cq);
+ ASSERT_OK(result);
+ return cq;
}
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr) {
+CanonicalQuery* canonicalize(const char* queryStr) {
BSONObj queryObj = fromjson(queryStr);
return canonicalize(queryObj);
}
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
- const char* sortStr,
- const char* projStr) {
+CanonicalQuery* canonicalize(const char* queryStr, const char* sortStr, const char* projStr) {
BSONObj queryObj = fromjson(queryStr);
BSONObj sortObj = fromjson(sortStr);
BSONObj projObj = fromjson(projStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, &cq);
+ ASSERT_OK(result);
+ return cq;
}
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
- const char* sortStr,
- const char* projStr,
- long long skip,
- long long limit,
- const char* hintStr,
- const char* minStr,
- const char* maxStr) {
+CanonicalQuery* canonicalize(const char* queryStr,
+ const char* sortStr,
+ const char* projStr,
+ long long skip,
+ long long limit,
+ const char* hintStr,
+ const char* minStr,
+ const char* maxStr) {
BSONObj queryObj = fromjson(queryStr);
BSONObj sortObj = fromjson(sortStr);
BSONObj projObj = fromjson(projStr);
BSONObj hintObj = fromjson(hintStr);
BSONObj minObj = fromjson(minStr);
BSONObj maxObj = fromjson(maxStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns,
- queryObj,
- sortObj,
- projObj,
- skip,
- limit,
- hintObj,
- minObj,
- maxObj,
- false, // snapshot
- false); // explain
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns,
+ queryObj,
+ sortObj,
+ projObj,
+ skip,
+ limit,
+ hintObj,
+ minObj,
+ maxObj,
+ false, // snapshot
+ false, // explain
+ &cq);
+ ASSERT_OK(result);
+ return cq;
}
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
- const char* sortStr,
- const char* projStr,
- long long skip,
- long long limit,
- const char* hintStr,
- const char* minStr,
- const char* maxStr,
- bool snapshot,
- bool explain) {
+CanonicalQuery* canonicalize(const char* queryStr,
+ const char* sortStr,
+ const char* projStr,
+ long long skip,
+ long long limit,
+ const char* hintStr,
+ const char* minStr,
+ const char* maxStr,
+ bool snapshot,
+ bool explain) {
BSONObj queryObj = fromjson(queryStr);
BSONObj sortObj = fromjson(sortStr);
BSONObj projObj = fromjson(projStr);
BSONObj hintObj = fromjson(hintStr);
BSONObj minObj = fromjson(minStr);
BSONObj maxObj = fromjson(maxStr);
- auto statusWithCQ = CanonicalQuery::canonicalize(
- ns, queryObj, sortObj, projObj, skip, limit, hintObj, minObj, maxObj, snapshot, explain);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize(ns,
+ queryObj,
+ sortObj,
+ projObj,
+ skip,
+ limit,
+ hintObj,
+ minObj,
+ maxObj,
+ snapshot,
+ explain,
+ &cq);
+ ASSERT_OK(result);
+ return cq;
}
/**
@@ -367,7 +380,7 @@ TEST(PlanCacheTest, AddEmptySolutions) {
PlanCache planCache;
unique_ptr<CanonicalQuery> cq(canonicalize("{a: 1}"));
std::vector<QuerySolution*> solns;
- unique_ptr<PlanRankingDecision> decision(createDecision(1U));
+ std::unique_ptr<PlanRankingDecision> decision(createDecision(1U));
ASSERT_NOT_OK(planCache.add(*cq, solns, decision.get()));
}
@@ -454,11 +467,14 @@ TEST(PlanCacheTest, NotifyOfWriteOp) {
class CachePlanSelectionTest : public mongo::unittest::Test {
protected:
void setUp() {
+ cq = NULL;
params.options = QueryPlannerParams::INCLUDE_COLLSCAN;
addIndex(BSON("_id" << 1));
}
void tearDown() {
+ delete cq;
+
for (vector<QuerySolution*>::iterator it = solns.begin(); it != solns.end(); ++it) {
delete *it;
}
@@ -540,6 +556,9 @@ protected:
const BSONObj& maxObj,
bool snapshot) {
// Clean up any previous state from a call to runQueryFull
+ delete cq;
+ cq = NULL;
+
for (vector<QuerySolution*>::iterator it = solns.begin(); it != solns.end(); ++it) {
delete *it;
}
@@ -547,19 +566,23 @@ protected:
solns.clear();
- auto statusWithCQ = CanonicalQuery::canonicalize(ns,
- query,
- sort,
- proj,
- skip,
- limit,
- hint,
- minObj,
- maxObj,
- snapshot,
- false); // explain
- ASSERT_OK(statusWithCQ.getStatus());
- Status s = QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns);
+ Status s = CanonicalQuery::canonicalize(ns,
+ query,
+ sort,
+ proj,
+ skip,
+ limit,
+ hint,
+ minObj,
+ maxObj,
+ snapshot,
+ false, // explain
+ &cq);
+ if (!s.isOK()) {
+ cq = NULL;
+ }
+ ASSERT_OK(s);
+ s = QueryPlanner::plan(*cq, params, &solns);
ASSERT_OK(s);
}
@@ -628,9 +651,11 @@ protected:
const BSONObj& sort,
const BSONObj& proj,
const QuerySolution& soln) const {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, query, sort, proj);
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status s = CanonicalQuery::canonicalize(ns, query, sort, proj, &cq);
+ ASSERT_OK(s);
+ unique_ptr<CanonicalQuery> scopedCq(cq);
+ cq = NULL;
// Create a CachedSolution the long way..
// QuerySolution -> PlanCacheEntry -> CachedSolution
@@ -642,7 +667,7 @@ protected:
CachedSolution cachedSoln(ck, entry);
QuerySolution* out;
- Status s = QueryPlanner::planFromCache(*scopedCq, params, cachedSoln, &out);
+ s = QueryPlanner::planFromCache(*scopedCq.get(), params, cachedSoln, &out);
ASSERT_OK(s);
return out;
@@ -731,6 +756,7 @@ protected:
static const PlanCacheKey ck;
BSONObj queryObj;
+ CanonicalQuery* cq;
QueryPlannerParams params;
vector<QuerySolution*> solns;
};
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 4768eed4312..2c0ca9167a5 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -3761,9 +3761,10 @@ TEST(BadInputTest, CacheDataFromTaggedTree) {
// No relevant index matching the index tag.
relevantIndices.push_back(IndexEntry(BSON("a" << 1)));
- auto statusWithCQ = CanonicalQuery::canonicalize("ns", BSON("a" << 3));
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status cqStatus = CanonicalQuery::canonicalize("ns", BSON("a" << 3), &cq);
+ ASSERT_OK(cqStatus);
+ std::unique_ptr<CanonicalQuery> scopedCq(cq);
scopedCq->root()->setTag(new IndexTag(1));
s = QueryPlanner::cacheDataFromTaggedTree(scopedCq->root(), relevantIndices, &indexTree);
@@ -3772,9 +3773,10 @@ TEST(BadInputTest, CacheDataFromTaggedTree) {
}
TEST(BadInputTest, TagAccordingToCache) {
- auto statusWithCQ = CanonicalQuery::canonicalize("ns", BSON("a" << 3));
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> scopedCq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status cqStatus = CanonicalQuery::canonicalize("ns", BSON("a" << 3), &cq);
+ ASSERT_OK(cqStatus);
+ std::unique_ptr<CanonicalQuery> scopedCq(cq);
std::unique_ptr<PlanCacheIndexTree> indexTree(new PlanCacheIndexTree());
indexTree->setIndexEntry(IndexEntry(BSON("a" << 1)));
@@ -3799,9 +3801,9 @@ TEST(BadInputTest, TagAccordingToCache) {
ASSERT_OK(s);
// Regenerate canonical query in order to clear tags.
- statusWithCQ = CanonicalQuery::canonicalize("ns", BSON("a" << 3));
- ASSERT_OK(statusWithCQ.getStatus());
- scopedCq = std::move(statusWithCQ.getValue());
+ cqStatus = CanonicalQuery::canonicalize("ns", BSON("a" << 3), &cq);
+ ASSERT_OK(cqStatus);
+ scopedCq.reset(cq);
// Mismatched tree topology.
PlanCacheIndexTree* child = new PlanCacheIndexTree();
diff --git a/src/mongo/db/query/query_planner_test_fixture.cpp b/src/mongo/db/query/query_planner_test_fixture.cpp
index 496b6e37128..1b876c5296b 100644
--- a/src/mongo/db/query/query_planner_test_fixture.cpp
+++ b/src/mongo/db/query/query_planner_test_fixture.cpp
@@ -155,20 +155,25 @@ void QueryPlannerTest::runQueryFull(const BSONObj& query,
// Clean up any previous state from a call to runQueryFull
solns.clear();
- auto statusWithCQ = CanonicalQuery::canonicalize(ns,
- query,
- sort,
- proj,
- skip,
- limit,
- hint,
- minObj,
- maxObj,
- snapshot,
- false); // explain
- ASSERT_OK(statusWithCQ.getStatus());
-
- ASSERT_OK(QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns.mutableVector()));
+ {
+ CanonicalQuery* rawCq;
+ Status s = CanonicalQuery::canonicalize(ns,
+ query,
+ sort,
+ proj,
+ skip,
+ limit,
+ hint,
+ minObj,
+ maxObj,
+ snapshot,
+ false, // explain
+ &rawCq);
+ ASSERT_OK(s);
+ cq.reset(rawCq);
+ }
+
+ ASSERT_OK(QueryPlanner::plan(*cq, params, &solns.mutableVector()));
}
void QueryPlannerTest::runInvalidQuery(const BSONObj& query) {
@@ -220,20 +225,25 @@ void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
bool snapshot) {
solns.clear();
- auto statusWithCQ = CanonicalQuery::canonicalize(ns,
- query,
- sort,
- proj,
- skip,
- limit,
- hint,
- minObj,
- maxObj,
- snapshot,
- false); // explain
- ASSERT_OK(statusWithCQ.getStatus());
-
- Status s = QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns.mutableVector());
+ {
+ CanonicalQuery* rawCq;
+ Status s = CanonicalQuery::canonicalize(ns,
+ query,
+ sort,
+ proj,
+ skip,
+ limit,
+ hint,
+ minObj,
+ maxObj,
+ snapshot,
+ false, // explain
+ &rawCq);
+ ASSERT_OK(s);
+ cq.reset(rawCq);
+ }
+
+ Status s = QueryPlanner::plan(*cq, params, &solns.mutableVector());
ASSERT_NOT_OK(s);
}
@@ -247,11 +257,13 @@ void QueryPlannerTest::runQueryAsCommand(const BSONObj& cmdObj) {
std::unique_ptr<LiteParsedQuery> lpq(
assertGet(LiteParsedQuery::makeFromFindCommand(nss, cmdObj, isExplain)));
+ CanonicalQuery* rawCq;
WhereCallbackNoop whereCallback;
- auto statusWithCQ = CanonicalQuery::canonicalize(lpq.release(), whereCallback);
- ASSERT_OK(statusWithCQ.getStatus());
+ Status canonStatus = CanonicalQuery::canonicalize(lpq.release(), &rawCq, whereCallback);
+ ASSERT_OK(canonStatus);
+ cq.reset(rawCq);
- Status s = QueryPlanner::plan(*statusWithCQ.getValue(), params, &solns.mutableVector());
+ Status s = QueryPlanner::plan(*cq, params, &solns.mutableVector());
ASSERT_OK(s);
}
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 53f92a09aeb..834e38ddaed 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -51,7 +51,6 @@ using std::shared_ptr;
using std::map;
using std::set;
using std::string;
-using std::unique_ptr;
using std::vector;
static const char* const ns = "unittests.documentsourcetests";
@@ -179,12 +178,11 @@ protected:
_exec.reset();
OldClientWriteContext ctx(&_opCtx, ns);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, /*query=*/BSONObj());
- uassertStatusOK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ uassertStatusOK(CanonicalQuery::canonicalize(ns, /*query=*/BSONObj(), &cq));
PlanExecutor* execBare;
- uassertStatusOK(getExecutor(
- &_opCtx, ctx.getCollection(), cq.release(), PlanExecutor::YIELD_MANUAL, &execBare));
+ uassertStatusOK(
+ getExecutor(&_opCtx, ctx.getCollection(), cq, PlanExecutor::YIELD_MANUAL, &execBare));
_exec.reset(execBare);
_exec->saveState();
@@ -298,7 +296,7 @@ public:
private:
int _value;
- mutable mongo::mutex _mutex;
+ mutable stdx::mutex _mutex;
mutable stdx::condition_variable _condition;
};
diff --git a/src/mongo/dbtests/executor_registry.cpp b/src/mongo/dbtests/executor_registry.cpp
index 3601ecc80e0..5a3a5649930 100644
--- a/src/mongo/dbtests/executor_registry.cpp
+++ b/src/mongo/dbtests/executor_registry.cpp
@@ -72,16 +72,14 @@ public:
unique_ptr<CollectionScan> scan(new CollectionScan(&_opCtx, params, ws.get(), NULL));
// Create a plan executor to hold it
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), BSONObj());
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
-
+ CanonicalQuery* cq;
+ ASSERT(CanonicalQuery::canonicalize(ns(), BSONObj(), &cq).isOK());
PlanExecutor* exec;
// Takes ownership of 'ws', 'scan', and 'cq'.
Status status = PlanExecutor::make(&_opCtx,
ws.release(),
scan.release(),
- cq.release(),
+ cq,
_ctx->db()->getCollection(ns()),
PlanExecutor::YIELD_MANUAL,
&exec);
diff --git a/src/mongo/dbtests/oplogstarttests.cpp b/src/mongo/dbtests/oplogstarttests.cpp
index 2d685959a24..1c73c533e6b 100644
--- a/src/mongo/dbtests/oplogstarttests.cpp
+++ b/src/mongo/dbtests/oplogstarttests.cpp
@@ -83,9 +83,10 @@ protected:
}
void setupFromQuery(const BSONObj& query) {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), query);
- ASSERT_OK(statusWithCQ.getStatus());
- _cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status s = CanonicalQuery::canonicalize(ns(), query, &cq);
+ ASSERT(s.isOK());
+ _cq.reset(cq);
_oplogws.reset(new WorkingSet());
_stage.reset(new OplogStart(&_txn, collection(), _cq->root(), _oplogws.get()));
}
diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp
index ef9e72bfdeb..77e34fc95f3 100644
--- a/src/mongo/dbtests/plan_ranking.cpp
+++ b/src/mongo/dbtests/plan_ranking.cpp
@@ -97,7 +97,7 @@ public:
* Use the MultiPlanRunner to pick the best plan for the query 'cq'. Goes through
* normal planning to generate solutions and feeds them to the MPR.
*
- * Does NOT take ownership of 'cq'. Caller DOES NOT own the returned QuerySolution*.
+ * Takes ownership of 'cq'. Caller DOES NOT own the returned QuerySolution*.
*/
QuerySolution* pickBestPlan(CanonicalQuery* cq) {
AutoGetCollectionForRead ctx(&_txn, ns);
@@ -117,7 +117,7 @@ public:
// Fill out the MPR.
_mps.reset(new MultiPlanStage(&_txn, collection, cq));
- unique_ptr<WorkingSet> ws(new WorkingSet());
+ std::unique_ptr<WorkingSet> ws(new WorkingSet());
// Put each solution from the planner into the MPR.
for (size_t i = 0; i < solutions.size(); ++i) {
PlanStage* root;
@@ -185,18 +185,15 @@ public:
addIndex(BSON("a" << 1));
addIndex(BSON("b" << 1));
- unique_ptr<CanonicalQuery> cq;
-
// Run the query {a:4, b:1}.
- {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, BSON("a" << 100 << "b" << 1));
- verify(statusWithCQ.isOK());
- cq = std::move(statusWithCQ.getValue());
- ASSERT(cq.get());
- }
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns, BSON("a" << 100 << "b" << 1), &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// {a:100} is super selective so choose that.
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get()));
@@ -205,16 +202,14 @@ public:
internalQueryForceIntersectionPlans = true;
// And run the same query again.
- {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, BSON("a" << 100 << "b" << 1));
- verify(statusWithCQ.isOK());
- cq = std::move(statusWithCQ.getValue());
- }
+ ASSERT(CanonicalQuery::canonicalize(ns, BSON("a" << 100 << "b" << 1), &cq).isOK());
+ std::unique_ptr<CanonicalQuery> killCq2(cq);
// With the "ranking picks ixisect always" option we pick an intersection plan that uses
// both the {a:1} and {b:1} indices even though it performs poorly.
- soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {node: {andSorted: {nodes: ["
"{ixscan: {filter: null, pattern: {a:1}}},"
@@ -239,17 +234,18 @@ public:
addIndex(BSON("b" << 1));
// Run the query {a:1, b:{$gt:1}.
- auto statusWithCQ =
- CanonicalQuery::canonicalize(ns, BSON("a" << 1 << "b" << BSON("$gt" << 1)));
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns, BSON("a" << 1 << "b" << BSON("$gt" << 1)), &cq)
+ .isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// Turn on the "force intersect" option.
// This will be reverted by PlanRankingTestBase's destructor when the test completes.
internalQueryForceIntersectionPlans = true;
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {node: {andHash: {nodes: ["
"{ixscan: {filter: null, pattern: {a:1}}},"
@@ -278,13 +274,15 @@ public:
addIndex(BSON("a" << 1 << "b" << 1));
// Query for a==27 with projection that wants 'a' and 'b'. BSONObj() is for sort.
- auto statusWithCQ = CanonicalQuery::canonicalize(
- ns, BSON("a" << 27), BSONObj(), BSON("_id" << 0 << "a" << 1 << "b" << 1));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ ASSERT(CanonicalQuery::canonicalize(
+ ns, BSON("a" << 27), BSONObj(), BSON("_id" << 0 << "a" << 1 << "b" << 1), &cq)
+ .isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
// Prefer the fully covered plan.
ASSERT(QueryPlannerTestLib::solutionMatches(
@@ -311,13 +309,14 @@ public:
addIndex(BSON("b" << 1));
// There is no data that matches this query but we don't know that until EOF.
+ CanonicalQuery* cq;
BSONObj queryObj = BSON("a" << 1 << "b" << 1 << "c" << 99);
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj);
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ ASSERT(CanonicalQuery::canonicalize(ns, queryObj, &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
// Anti-prefer the intersection plan.
bool bestIsScanOverA = QueryPlannerTestLib::solutionMatches(
@@ -348,13 +347,15 @@ public:
// There is no data that matches this query ({a:2}). Both scans will hit EOF before
// returning any data.
- auto statusWithCQ = CanonicalQuery::canonicalize(
- ns, BSON("a" << 2), BSONObj(), BSON("_id" << 0 << "a" << 1 << "b" << 1));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ ASSERT(CanonicalQuery::canonicalize(
+ ns, BSON("a" << 2), BSONObj(), BSON("_id" << 0 << "a" << 1 << "b" << 1), &cq)
+ .isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
// Prefer the fully covered plan.
ASSERT(QueryPlannerTestLib::solutionMatches(
"{proj: {spec: {_id:0, a:1, b:1}, node: {ixscan: {pattern: {a: 1, b:1}}}}}",
@@ -380,13 +381,14 @@ public:
addIndex(BSON("b" << 1));
// Run the query {a:N+1, b:1}. (No such document.)
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, BSON("a" << N + 1 << "b" << 1));
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns, BSON("a" << N + 1 << "b" << 1), &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// {a: 100} is super selective so choose that.
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get()));
}
@@ -414,14 +416,15 @@ public:
addIndex(BSON("b" << 1));
// Run the query {a:N+1, b:1}. (No such document.)
- auto statusWithCQ =
- CanonicalQuery::canonicalize(ns, BSON("a" << BSON("$gte" << N + 1) << "b" << 1));
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns, BSON("a" << BSON("$gte" << N + 1) << "b" << 1), &cq)
+ .isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// {a: 100} is super selective so choose that.
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get()));
}
@@ -442,14 +445,15 @@ public:
// Run a query with a sort. The blocking sort won't produce any data during the
// evaluation period.
+ CanonicalQuery* cq;
BSONObj queryObj = BSON("_id" << BSON("$gte" << 20 << "$lte" << 200));
BSONObj sortObj = BSON("c" << 1);
BSONObj projObj = BSONObj();
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj);
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ ASSERT(CanonicalQuery::canonicalize(ns, queryObj, sortObj, projObj, &cq).isOK());
+ std::unique_ptr<CanonicalQuery> killCq(cq);
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
// The best must not be a collscan.
ASSERT(QueryPlannerTestLib::solutionMatches(
@@ -472,12 +476,13 @@ public:
}
// Look for A Space Odyssey.
- auto statusWithCQ = CanonicalQuery::canonicalize(ns, BSON("foo" << 2001));
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns, BSON("foo" << 2001), &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
- QuerySolution* soln = pickBestPlan(cq.get());
+ // Takes ownership of cq.
+ QuerySolution* soln = pickBestPlan(cq);
// The best must be a collscan.
ASSERT(QueryPlannerTestLib::solutionMatches("{cscan: {dir: 1, filter: {foo: 2001}}}",
@@ -503,18 +508,19 @@ public:
addIndex(BSON("d" << 1 << "e" << 1));
// Query: find({a: 1}).sort({d: 1})
- auto statusWithCQ = CanonicalQuery::canonicalize(ns,
- BSON("a" << 1),
- BSON("d" << 1), // sort
- BSONObj()); // projection
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ ASSERT(CanonicalQuery::canonicalize(ns,
+ BSON("a" << 1),
+ BSON("d" << 1), // sort
+ BSONObj(), // projection
+ &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// No results will be returned during the trial period,
// so we expect to choose {d: 1, e: 1}, as it allows us
// to avoid the sort stage.
- QuerySolution* soln = pickBestPlan(cq.get());
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches(
"{fetch: {filter: {a:1}, node: "
"{ixscan: {filter: null, pattern: {d:1,e:1}}}}}",
@@ -541,14 +547,14 @@ public:
// Solutions using either 'a' or 'b' will take a long time to start producing
// results. However, an index scan on 'b' will start producing results sooner
// than an index scan on 'a'.
- auto statusWithCQ =
- CanonicalQuery::canonicalize(ns, fromjson("{a: 1, b: 1, c: {$gte: 5000}}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ ASSERT(CanonicalQuery::canonicalize(ns, fromjson("{a: 1, b: 1, c: {$gte: 5000}}"), &cq)
+ .isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// Use index on 'b'.
- QuerySolution* soln = pickBestPlan(cq.get());
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches("{fetch: {node: {ixscan: {pattern: {b: 1}}}}}",
soln->root.get()));
}
@@ -572,14 +578,14 @@ public:
addIndex(BSON("b" << 1 << "c" << 1));
addIndex(BSON("a" << 1));
- auto statusWithCQ =
- CanonicalQuery::canonicalize(ns, fromjson("{a: 9, b: {$ne: 10}, c: 9}"));
- ASSERT_OK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ ASSERT(
+ CanonicalQuery::canonicalize(ns, fromjson("{a: 9, b: {$ne: 10}, c: 9}"), &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// Expect to use index {a: 1, b: 1}.
- QuerySolution* soln = pickBestPlan(cq.get());
+ QuerySolution* soln = pickBestPlan(cq);
ASSERT(QueryPlannerTestLib::solutionMatches("{fetch: {node: {ixscan: {pattern: {a: 1}}}}}",
soln->root.get()));
}
diff --git a/src/mongo/dbtests/query_multi_plan_runner.cpp b/src/mongo/dbtests/query_multi_plan_runner.cpp
index 02e66609dc2..50b957f4731 100644
--- a/src/mongo/dbtests/query_multi_plan_runner.cpp
+++ b/src/mongo/dbtests/query_multi_plan_runner.cpp
@@ -63,7 +63,7 @@ using std::vector;
* Create query solution.
*/
QuerySolution* createQuerySolution() {
- unique_ptr<QuerySolution> soln(new QuerySolution());
+ std::unique_ptr<QuerySolution> soln(new QuerySolution());
soln->cacheData.reset(new SolutionCacheData());
soln->cacheData->solnType = SolutionCacheData::COLLSCAN_SOLN;
soln->cacheData->tree.reset(new PlanCacheIndexTree());
@@ -152,12 +152,11 @@ public:
new CollectionScan(&_txn, csparams, sharedWs.get(), filter.get()));
// Hand the plans off to the runner.
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), BSON("foo" << 7));
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- verify(NULL != cq.get());
+ CanonicalQuery* cq = NULL;
+ verify(CanonicalQuery::canonicalize(ns(), BSON("foo" << 7), &cq).isOK());
+ verify(NULL != cq);
- MultiPlanStage* mps = new MultiPlanStage(&_txn, ctx.getCollection(), cq.get());
+ MultiPlanStage* mps = new MultiPlanStage(&_txn, ctx.getCollection(), cq);
mps->addPlan(createQuerySolution(), firstRoot.release(), sharedWs.get());
mps->addPlan(createQuerySolution(), secondRoot.release(), sharedWs.get());
@@ -169,15 +168,10 @@ public:
// Takes ownership of arguments other than 'collection'.
PlanExecutor* rawExec;
- Status status = PlanExecutor::make(&_txn,
- sharedWs.release(),
- mps,
- cq.release(),
- coll,
- PlanExecutor::YIELD_MANUAL,
- &rawExec);
+ Status status = PlanExecutor::make(
+ &_txn, sharedWs.release(), mps, cq, coll, PlanExecutor::YIELD_MANUAL, &rawExec);
ASSERT_OK(status);
- unique_ptr<PlanExecutor> exec(rawExec);
+ std::unique_ptr<PlanExecutor> exec(rawExec);
// Get all our results out.
int results = 0;
@@ -207,13 +201,14 @@ public:
Collection* collection = ctx.getCollection();
// Query for both 'a' and 'b' and sort on 'b'.
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(),
- BSON("a" << 1 << "b" << 1), // query
- BSON("b" << 1), // sort
- BSONObj()); // proj
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- ASSERT(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns(),
+ BSON("a" << 1 << "b" << 1), // query
+ BSON("b" << 1), // sort
+ BSONObj(), // proj
+ &cq).isOK());
+ ASSERT(NULL != cq);
+ std::unique_ptr<CanonicalQuery> killCq(cq);
// Force index intersection.
bool forceIxisectOldValue = internalQueryForceIntersectionPlans;
@@ -221,7 +216,7 @@ public:
// Get planner params.
QueryPlannerParams plannerParams;
- fillOutPlannerParams(&_txn, collection, cq.get(), &plannerParams);
+ fillOutPlannerParams(&_txn, collection, cq, &plannerParams);
// Turn this off otherwise it pops up in some plans.
plannerParams.options &= ~QueryPlannerParams::KEEP_MUTATIONS;
@@ -235,7 +230,7 @@ public:
ASSERT_EQUALS(solutions.size(), 3U);
// Fill out the MultiPlanStage.
- unique_ptr<MultiPlanStage> mps(new MultiPlanStage(&_txn, collection, cq.get()));
+ unique_ptr<MultiPlanStage> mps(new MultiPlanStage(&_txn, collection, cq));
unique_ptr<WorkingSet> ws(new WorkingSet());
// Put each solution from the planner into the MPR.
for (size_t i = 0; i < solutions.size(); ++i) {
diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp
index 7cbd86ab9cb..9c977bf5336 100644
--- a/src/mongo/dbtests/query_plan_executor.cpp
+++ b/src/mongo/dbtests/query_plan_executor.cpp
@@ -95,23 +95,17 @@ public:
unique_ptr<WorkingSet> ws(new WorkingSet());
// Canonicalize the query
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), filterObj);
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- verify(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns(), filterObj, &cq).isOK());
+ verify(NULL != cq);
// Make the stage.
- unique_ptr<PlanStage> root(new CollectionScan(&_txn, csparams, ws.get(), cq.get()->root()));
+ unique_ptr<PlanStage> root(new CollectionScan(&_txn, csparams, ws.get(), cq->root()));
PlanExecutor* exec;
// Hand the plan off to the executor.
- Status stat = PlanExecutor::make(&_txn,
- ws.release(),
- root.release(),
- cq.release(),
- coll,
- PlanExecutor::YIELD_MANUAL,
- &exec);
+ Status stat = PlanExecutor::make(
+ &_txn, ws.release(), root.release(), cq, coll, PlanExecutor::YIELD_MANUAL, &exec);
ASSERT_OK(stat);
return exec;
}
@@ -145,20 +139,14 @@ public:
IndexScan* ix = new IndexScan(&_txn, ixparams, ws.get(), NULL);
unique_ptr<PlanStage> root(new FetchStage(&_txn, ws.get(), ix, NULL, coll));
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), BSONObj());
- verify(statusWithCQ.isOK());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- verify(NULL != cq.get());
+ CanonicalQuery* cq;
+ verify(CanonicalQuery::canonicalize(ns(), BSONObj(), &cq).isOK());
+ verify(NULL != cq);
PlanExecutor* exec;
// Hand the plan off to the executor.
- Status stat = PlanExecutor::make(&_txn,
- ws.release(),
- root.release(),
- cq.release(),
- coll,
- PlanExecutor::YIELD_MANUAL,
- &exec);
+ Status stat = PlanExecutor::make(
+ &_txn, ws.release(), root.release(), cq, coll, PlanExecutor::YIELD_MANUAL, &exec);
ASSERT_OK(stat);
return exec;
}
diff --git a/src/mongo/dbtests/query_stage_cached_plan.cpp b/src/mongo/dbtests/query_stage_cached_plan.cpp
index a0b7fd14b4a..821a329e91d 100644
--- a/src/mongo/dbtests/query_stage_cached_plan.cpp
+++ b/src/mongo/dbtests/query_stage_cached_plan.cpp
@@ -116,9 +116,9 @@ public:
ASSERT(collection);
// Query can be answered by either index on "a" or index on "b".
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), fromjson("{a: {$gte: 8}, b: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* rawCq;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns(), fromjson("{a: {$gte: 8}, b: 1}"), &rawCq));
+ const std::unique_ptr<CanonicalQuery> cq(rawCq);
// We shouldn't have anything in the plan cache for this shape yet.
PlanCache* cache = collection->infoCache()->getPlanCache();
@@ -180,9 +180,9 @@ public:
ASSERT(collection);
// Query can be answered by either index on "a" or index on "b".
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), fromjson("{a: {$gte: 8}, b: 1}"));
- ASSERT_OK(statusWithCQ.getStatus());
- const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* rawCq;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns(), fromjson("{a: {$gte: 8}, b: 1}"), &rawCq));
+ const std::unique_ptr<CanonicalQuery> cq(rawCq);
// We shouldn't have anything in the plan cache for this shape yet.
PlanCache* cache = collection->infoCache()->getPlanCache();
diff --git a/src/mongo/dbtests/query_stage_delete.cpp b/src/mongo/dbtests/query_stage_delete.cpp
index e3d3ace2054..49a2d8709ae 100644
--- a/src/mongo/dbtests/query_stage_delete.cpp
+++ b/src/mongo/dbtests/query_stage_delete.cpp
@@ -97,10 +97,11 @@ public:
}
}
- unique_ptr<CanonicalQuery> canonicalize(const BSONObj& query) {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), query);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* canonicalize(const BSONObj& query) {
+ CanonicalQuery* cq;
+ Status status = CanonicalQuery::canonicalize(ns(), query, &cq);
+ ASSERT_OK(status);
+ return cq;
}
static size_t numObj() {
@@ -194,8 +195,8 @@ public:
const NamespaceString nss(ns());
const int targetDocIndex = 0;
const BSONObj query = BSON("foo" << BSON("$gte" << targetDocIndex));
- const unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
- const unique_ptr<CanonicalQuery> cq(canonicalize(query));
+ const std::unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
+ const std::unique_ptr<CanonicalQuery> cq(canonicalize(query));
// Get the RecordIds that would be returned by an in-order scan.
vector<RecordId> locs;
@@ -203,7 +204,7 @@ public:
// Configure a QueuedDataStage to pass the first object in the collection back in a
// LOC_AND_UNOWNED_OBJ state.
- unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
+ std::unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
WorkingSetMember member;
member.loc = locs[targetDocIndex];
member.state = WorkingSetMember::LOC_AND_UNOWNED_OBJ;
@@ -216,7 +217,7 @@ public:
deleteParams.returnDeleted = true;
deleteParams.canonicalQuery = cq.get();
- const unique_ptr<DeleteStage> deleteStage(
+ const std::unique_ptr<DeleteStage> deleteStage(
stdx::make_unique<DeleteStage>(&_txn, deleteParams, ws.get(), coll, qds.release()));
const DeleteStats* stats = static_cast<const DeleteStats*>(deleteStage->getSpecificStats());
@@ -259,11 +260,11 @@ public:
OldClientWriteContext ctx(&_txn, ns());
Collection* coll = ctx.getCollection();
const BSONObj query = BSONObj();
- const unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
- const unique_ptr<CanonicalQuery> cq(canonicalize(query));
+ const std::unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
+ const std::unique_ptr<CanonicalQuery> cq(canonicalize(query));
// Configure a QueuedDataStage to pass an OWNED_OBJ to the delete stage.
- unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
+ std::unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
WorkingSetMember member;
member.state = WorkingSetMember::OWNED_OBJ;
member.obj = Snapshotted<BSONObj>(SnapshotId(), fromjson("{x: 1}"));
@@ -275,7 +276,7 @@ public:
deleteParams.returnDeleted = true;
deleteParams.canonicalQuery = cq.get();
- const unique_ptr<DeleteStage> deleteStage(
+ const std::unique_ptr<DeleteStage> deleteStage(
stdx::make_unique<DeleteStage>(&_txn, deleteParams, ws.get(), coll, qds.release()));
const DeleteStats* stats = static_cast<const DeleteStats*>(deleteStage->getSpecificStats());
diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp
index 2231240f2c4..244eee99283 100644
--- a/src/mongo/dbtests/query_stage_subplan.cpp
+++ b/src/mongo/dbtests/query_stage_subplan.cpp
@@ -88,9 +88,9 @@ public:
"{$or: [{a: {$geoWithin: {$centerSphere: [[0,0],10]}}},"
"{a: {$geoWithin: {$centerSphere: [[1,1],10]}}}]}");
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), query);
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* rawCq;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns(), query, &rawCq));
+ std::unique_ptr<CanonicalQuery> cq(rawCq);
Collection* collection = ctx.getCollection();
@@ -131,9 +131,9 @@ public:
Collection* collection = ctx.getCollection();
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), query);
- ASSERT_OK(statusWithCQ.getStatus());
- std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ CanonicalQuery* rawCq;
+ ASSERT_OK(CanonicalQuery::canonicalize(ns(), query, &rawCq));
+ std::unique_ptr<CanonicalQuery> cq(rawCq);
// Get planner params.
QueryPlannerParams plannerParams;
diff --git a/src/mongo/dbtests/query_stage_update.cpp b/src/mongo/dbtests/query_stage_update.cpp
index 2e80ef886aa..c4e33eb6802 100644
--- a/src/mongo/dbtests/query_stage_update.cpp
+++ b/src/mongo/dbtests/query_stage_update.cpp
@@ -82,10 +82,11 @@ public:
return _client.count(ns(), query, 0, 0, 0);
}
- unique_ptr<CanonicalQuery> canonicalize(const BSONObj& query) {
- auto statusWithCQ = CanonicalQuery::canonicalize(ns(), query);
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* canonicalize(const BSONObj& query) {
+ CanonicalQuery* cq;
+ Status status = CanonicalQuery::canonicalize(ns(), query, &cq);
+ ASSERT_OK(status);
+ return cq;
}
/**
@@ -376,8 +377,8 @@ public:
UpdateDriver driver((UpdateDriver::Options()));
const int targetDocIndex = 0; // We'll be working with the first doc in the collection.
const BSONObj query = BSON("foo" << BSON("$gte" << targetDocIndex));
- const unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
- const unique_ptr<CanonicalQuery> cq(canonicalize(query));
+ const std::unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
+ const std::unique_ptr<CanonicalQuery> cq(canonicalize(query));
// Get the RecordIds that would be returned by an in-order scan.
vector<RecordId> locs;
@@ -395,7 +396,7 @@ public:
// Configure a QueuedDataStage to pass the first object in the collection back in a
// LOC_AND_UNOWNED_OBJ state.
- unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
+ std::unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
WorkingSetMember member;
member.loc = locs[targetDocIndex];
member.state = WorkingSetMember::LOC_AND_UNOWNED_OBJ;
@@ -407,7 +408,7 @@ public:
UpdateStageParams updateParams(&request, &driver, opDebug);
updateParams.canonicalQuery = cq.get();
- const unique_ptr<UpdateStage> updateStage(
+ const std::unique_ptr<UpdateStage> updateStage(
stdx::make_unique<UpdateStage>(&_txn, updateParams, ws.get(), coll, qds.release()));
// Should return advanced.
@@ -463,8 +464,8 @@ public:
UpdateDriver driver((UpdateDriver::Options()));
const int targetDocIndex = 10;
const BSONObj query = BSON("foo" << BSON("$gte" << targetDocIndex));
- const unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
- const unique_ptr<CanonicalQuery> cq(canonicalize(query));
+ const std::unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
+ const std::unique_ptr<CanonicalQuery> cq(canonicalize(query));
// Get the RecordIds that would be returned by an in-order scan.
vector<RecordId> locs;
@@ -482,7 +483,7 @@ public:
// Configure a QueuedDataStage to pass the first object in the collection back in a
// LOC_AND_UNOWNED_OBJ state.
- unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
+ std::unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
WorkingSetMember member;
member.loc = locs[targetDocIndex];
member.state = WorkingSetMember::LOC_AND_UNOWNED_OBJ;
@@ -494,7 +495,7 @@ public:
UpdateStageParams updateParams(&request, &driver, opDebug);
updateParams.canonicalQuery = cq.get();
- unique_ptr<UpdateStage> updateStage(
+ std::unique_ptr<UpdateStage> updateStage(
stdx::make_unique<UpdateStage>(&_txn, updateParams, ws.get(), coll, qds.release()));
// Should return advanced.
@@ -543,8 +544,8 @@ public:
UpdateRequest request(nsString());
UpdateDriver driver((UpdateDriver::Options()));
const BSONObj query = BSONObj();
- const unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
- const unique_ptr<CanonicalQuery> cq(canonicalize(query));
+ const std::unique_ptr<WorkingSet> ws(stdx::make_unique<WorkingSet>());
+ const std::unique_ptr<CanonicalQuery> cq(canonicalize(query));
// Populate the request.
request.setQuery(query);
@@ -557,7 +558,7 @@ public:
ASSERT_OK(driver.parse(request.getUpdates(), request.isMulti()));
// Configure a QueuedDataStage to pass an OWNED_OBJ to the update stage.
- unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
+ std::unique_ptr<QueuedDataStage> qds(stdx::make_unique<QueuedDataStage>(ws.get()));
WorkingSetMember member;
member.state = WorkingSetMember::OWNED_OBJ;
member.obj = Snapshotted<BSONObj>(SnapshotId(), fromjson("{x: 1}"));
@@ -567,7 +568,7 @@ public:
UpdateStageParams updateParams(&request, &driver, opDebug);
updateParams.canonicalQuery = cq.get();
- const unique_ptr<UpdateStage> updateStage(
+ const std::unique_ptr<UpdateStage> updateStage(
stdx::make_unique<UpdateStage>(&_txn, updateParams, ws.get(), coll, qds.release()));
const UpdateStats* stats = static_cast<const UpdateStats*>(updateStage->getSpecificStats());
diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp
index e663a5dd640..73c1461c92f 100644
--- a/src/mongo/s/chunk_manager.cpp
+++ b/src/mongo/s/chunk_manager.cpp
@@ -55,14 +55,14 @@
namespace mongo {
+using std::shared_ptr;
+
using std::make_pair;
using std::map;
using std::max;
using std::pair;
using std::set;
-using std::shared_ptr;
using std::string;
-using std::unique_ptr;
using std::vector;
namespace {
@@ -452,13 +452,15 @@ ChunkPtr ChunkManager::findIntersectingChunk(const BSONObj& shardKey) const {
}
void ChunkManager::getShardIdsForQuery(set<ShardId>& shardIds, const BSONObj& query) const {
- auto statusWithCQ = CanonicalQuery::canonicalize(_ns, query, WhereCallbackNoop());
+ CanonicalQuery* canonicalQuery = NULL;
+ Status status = CanonicalQuery::canonicalize(_ns, query, &canonicalQuery, WhereCallbackNoop());
- uassertStatusOK(statusWithCQ.getStatus());
- unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
+ std::unique_ptr<CanonicalQuery> canonicalQueryPtr(canonicalQuery);
+
+ uassert(status.code(), status.reason(), status.isOK());
// Query validation
- if (QueryPlannerCommon::hasNode(cq->root(), MatchExpression::GEO_NEAR)) {
+ if (QueryPlannerCommon::hasNode(canonicalQuery->root(), MatchExpression::GEO_NEAR)) {
uassert(13501, "use geoNear command rather than $near query", false);
}
@@ -468,7 +470,7 @@ void ChunkManager::getShardIdsForQuery(set<ShardId>& shardIds, const BSONObj& qu
// Query { a : { $gte : 1, $lt : 2 },
// b : { $gte : 3, $lt : 4 } }
// => Bounds { a : [1, 2), b : [3, 4) }
- IndexBounds bounds = getIndexBoundsForQuery(_keyPattern.toBSON(), *cq);
+ IndexBounds bounds = getIndexBoundsForQuery(_keyPattern.toBSON(), canonicalQuery);
// Transforms bounds for each shard key field into full shard key ranges
// for example :
@@ -523,12 +525,12 @@ void ChunkManager::getAllShardIds(set<ShardId>* all) const {
}
IndexBounds ChunkManager::getIndexBoundsForQuery(const BSONObj& key,
- const CanonicalQuery& canonicalQuery) {
+ const CanonicalQuery* canonicalQuery) {
// $text is not allowed in planning since we don't have text index on mongos.
//
// TODO: Treat $text query as a no-op in planning. So with shard key {a: 1},
// the query { a: 2, $text: { ... } } will only target to {a: 2}.
- if (QueryPlannerCommon::hasNode(canonicalQuery.root(), MatchExpression::TEXT)) {
+ if (QueryPlannerCommon::hasNode(canonicalQuery->root(), MatchExpression::TEXT)) {
IndexBounds bounds;
IndexBoundsBuilder::allValuesBounds(key, &bounds); // [minKey, maxKey]
return bounds;
@@ -553,7 +555,7 @@ IndexBounds ChunkManager::getIndexBoundsForQuery(const BSONObj& key,
plannerParams.indices.push_back(indexEntry);
OwnedPointerVector<QuerySolution> solutions;
- Status status = QueryPlanner::plan(canonicalQuery, plannerParams, &solutions.mutableVector());
+ Status status = QueryPlanner::plan(*canonicalQuery, plannerParams, &solutions.mutableVector());
uassert(status.code(), status.reason(), status.isOK());
IndexBounds bounds;
diff --git a/src/mongo/s/chunk_manager.h b/src/mongo/s/chunk_manager.h
index cb68b42b858..63e563e7d67 100644
--- a/src/mongo/s/chunk_manager.h
+++ b/src/mongo/s/chunk_manager.h
@@ -208,7 +208,7 @@ public:
// b : { $gte : 3, $lt : 4 } }
// => Bounds { a : [1, 2), b : [3, 4) }
static IndexBounds getIndexBoundsForQuery(const BSONObj& key,
- const CanonicalQuery& canonicalQuery);
+ const CanonicalQuery* canonicalQuery);
// Collapse query solution tree.
//
diff --git a/src/mongo/s/chunk_manager_targeter_test.cpp b/src/mongo/s/chunk_manager_targeter_test.cpp
index ff6d83cf0ea..4f43580d40c 100644
--- a/src/mongo/s/chunk_manager_targeter_test.cpp
+++ b/src/mongo/s/chunk_manager_targeter_test.cpp
@@ -53,11 +53,12 @@ using std::make_pair;
*/
// Utility function to create a CanonicalQuery
-unique_ptr<CanonicalQuery> canonicalize(const char* queryStr) {
+CanonicalQuery* canonicalize(const char* queryStr) {
BSONObj queryObj = fromjson(queryStr);
- auto statusWithCQ = CanonicalQuery::canonicalize("test.foo", queryObj, WhereCallbackNoop());
- ASSERT_OK(statusWithCQ.getStatus());
- return std::move(statusWithCQ.getValue());
+ CanonicalQuery* cq;
+ Status result = CanonicalQuery::canonicalize("test.foo", queryObj, &cq, WhereCallbackNoop());
+ ASSERT_OK(result);
+ return cq;
}
void checkIndexBoundsWithKey(const char* keyStr,
@@ -68,7 +69,7 @@ void checkIndexBoundsWithKey(const char* keyStr,
BSONObj key = fromjson(keyStr);
- IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, *query.get());
+ IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, query.get());
ASSERT_EQUALS(indexBounds.size(), expectedBounds.size());
for (size_t i = 0; i < indexBounds.size(); i++) {
const OrderedIntervalList& oil = indexBounds.fields[i];
@@ -91,7 +92,7 @@ void checkIndexBounds(const char* queryStr, const OrderedIntervalList& expectedO
BSONObj key = fromjson("{a: 1}");
- IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, *query.get());
+ IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, query.get());
ASSERT_EQUALS(indexBounds.size(), 1U);
const OrderedIntervalList& oil = indexBounds.fields.front();
@@ -278,7 +279,7 @@ TEST(CMCollapseTreeTest, BasicAllElemMatch) {
BSONObj key = fromjson("{'foo.a': 1}");
- IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, *query.get());
+ IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, query.get());
ASSERT_EQUALS(indexBounds.size(), 1U);
const OrderedIntervalList& oil = indexBounds.fields.front();
ASSERT_EQUALS(oil.intervals.size(), 1U);
@@ -358,7 +359,7 @@ TEST(CMCollapseTreeTest, HashedSinglePoint) {
BSONObj key = fromjson("{a: 'hashed'}");
- IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, *query.get());
+ IndexBounds indexBounds = ChunkManager::getIndexBoundsForQuery(key, query.get());
ASSERT_EQUALS(indexBounds.size(), 1U);
const OrderedIntervalList& oil = indexBounds.fields.front();
ASSERT_EQUALS(oil.intervals.size(), 1U);
diff --git a/src/mongo/s/shard_key_pattern.cpp b/src/mongo/s/shard_key_pattern.cpp
index 24485148810..f411461b925 100644
--- a/src/mongo/s/shard_key_pattern.cpp
+++ b/src/mongo/s/shard_key_pattern.cpp
@@ -265,11 +265,12 @@ StatusWith<BSONObj> ShardKeyPattern::extractShardKeyFromQuery(const BSONObj& bas
return StatusWith<BSONObj>(BSONObj());
// Extract equalities from query
- auto statusWithCQ = CanonicalQuery::canonicalize("", basicQuery, WhereCallbackNoop());
- if (!statusWithCQ.isOK()) {
- return StatusWith<BSONObj>(statusWithCQ.getStatus());
- }
- unique_ptr<CanonicalQuery> query = std::move(statusWithCQ.getValue());
+ CanonicalQuery* rawQuery;
+ Status queryStatus =
+ CanonicalQuery::canonicalize("", basicQuery, &rawQuery, WhereCallbackNoop());
+ if (!queryStatus.isOK())
+ return StatusWith<BSONObj>(queryStatus);
+ unique_ptr<CanonicalQuery> query(rawQuery);
EqualityMatches equalities;
// TODO: Build the path set initially?