summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorQingyang Chen <qingyang.chen@10gen.com>2015-06-22 13:22:45 -0400
committerQingyang Chen <qingyang.chen@10gen.com>2015-06-22 13:22:45 -0400
commit22cf042f9541cf778f71e1bd1a84fcd87012c0b1 (patch)
tree0d293b08d819409580f7087654b5d6f81d5d40a4 /src/mongo/db
parent3f6f66daac840fe2b2dc26eeeacbf015479567df (diff)
downloadmongo-22cf042f9541cf778f71e1bd1a84fcd87012c0b1.tar.gz
Revert "SERVER-16889 query subsystem CanonicalQuery::canonicalize use StatusWith<unique_ptr> for ownership transfer"
This reverts commit 3f6f66daac840fe2b2dc26eeeacbf015479567df.
Diffstat (limited to 'src/mongo/db')
-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
29 files changed, 596 insertions, 532 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);
}