summaryrefslogtreecommitdiff
path: root/src/mongo/db/query
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/query
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/query')
-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
9 files changed, 377 insertions, 326 deletions
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);
}