summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/group.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/group.cpp')
-rw-r--r--src/mongo/db/commands/group.cpp280
1 files changed, 134 insertions, 146 deletions
diff --git a/src/mongo/db/commands/group.cpp b/src/mongo/db/commands/group.cpp
index 31a03fa2543..cdfb9ca0d5a 100644
--- a/src/mongo/db/commands/group.cpp
+++ b/src/mongo/db/commands/group.cpp
@@ -44,176 +44,164 @@
namespace mongo {
- using std::unique_ptr;
- using std::string;
+using std::unique_ptr;
+using std::string;
- static GroupCommand cmdGroup;
+static GroupCommand cmdGroup;
- GroupCommand::GroupCommand() : Command("group") {}
+GroupCommand::GroupCommand() : Command("group") {}
- Status GroupCommand::checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
- std::string ns = parseNs(dbname, cmdObj);
- if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnNamespace(
- NamespaceString(ns), ActionType::find)) {
- return Status(ErrorCodes::Unauthorized, "unauthorized");
- }
- return Status::OK();
+Status GroupCommand::checkAuthForCommand(ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
+ std::string ns = parseNs(dbname, cmdObj);
+ if (!AuthorizationSession::get(client)
+ ->isAuthorizedForActionsOnNamespace(NamespaceString(ns), ActionType::find)) {
+ return Status(ErrorCodes::Unauthorized, "unauthorized");
}
-
- std::string GroupCommand::parseNs(const std::string& dbname, const BSONObj& cmdObj) const {
- const BSONObj& p = cmdObj.firstElement().embeddedObjectUserCheck();
- uassert(17211, "ns has to be set", p["ns"].type() == String);
- return dbname + "." + p["ns"].String();
+ return Status::OK();
+}
+
+std::string GroupCommand::parseNs(const std::string& dbname, const BSONObj& cmdObj) const {
+ const BSONObj& p = cmdObj.firstElement().embeddedObjectUserCheck();
+ uassert(17211, "ns has to be set", p["ns"].type() == String);
+ return dbname + "." + p["ns"].String();
+}
+
+Status GroupCommand::parseRequest(const string& dbname,
+ const BSONObj& cmdObj,
+ GroupRequest* request) const {
+ request->ns = parseNs(dbname, cmdObj);
+
+ // By default, group requests are regular group not explain of group.
+ request->explain = false;
+
+ const BSONObj& p = cmdObj.firstElement().embeddedObjectUserCheck();
+
+ if (p["cond"].type() == Object) {
+ request->query = p["cond"].embeddedObject().getOwned();
+ } else if (p["condition"].type() == Object) {
+ request->query = p["condition"].embeddedObject().getOwned();
+ } else if (p["query"].type() == Object) {
+ request->query = p["query"].embeddedObject().getOwned();
+ } else if (p["q"].type() == Object) {
+ request->query = p["q"].embeddedObject().getOwned();
}
- Status GroupCommand::parseRequest(const string& dbname,
- const BSONObj& cmdObj,
- GroupRequest* request) const {
- request->ns = parseNs(dbname, cmdObj);
-
- // By default, group requests are regular group not explain of group.
- request->explain = false;
-
- const BSONObj& p = cmdObj.firstElement().embeddedObjectUserCheck();
-
- if (p["cond"].type() == Object) {
- request->query = p["cond"].embeddedObject().getOwned();
- }
- else if (p["condition"].type() == Object) {
- request->query = p["condition"].embeddedObject().getOwned();
- }
- else if (p["query"].type() == Object) {
- request->query = p["query"].embeddedObject().getOwned();
- }
- else if (p["q"].type() == Object) {
- request->query = p["q"].embeddedObject().getOwned();
- }
-
- if (p["key"].type() == Object) {
- request->keyPattern = p["key"].embeddedObjectUserCheck().getOwned();
- if (!p["$keyf"].eoo()) {
- return Status(ErrorCodes::BadValue, "can't have key and $keyf");
- }
- }
- else if (!p["$keyf"].eoo()) {
- request->keyFunctionCode = p["$keyf"]._asCode();
- }
- else {
- // No key specified. Use the entire object as the key.
- }
-
- BSONElement reduce = p["$reduce"];
- if (reduce.eoo()) {
- return Status(ErrorCodes::BadValue, "$reduce has to be set");
- }
- request->reduceCode = reduce._asCode();
-
- if (reduce.type() == CodeWScope) {
- request->reduceScope = reduce.codeWScopeObject().getOwned();
+ if (p["key"].type() == Object) {
+ request->keyPattern = p["key"].embeddedObjectUserCheck().getOwned();
+ if (!p["$keyf"].eoo()) {
+ return Status(ErrorCodes::BadValue, "can't have key and $keyf");
}
+ } else if (!p["$keyf"].eoo()) {
+ request->keyFunctionCode = p["$keyf"]._asCode();
+ } else {
+ // No key specified. Use the entire object as the key.
+ }
- if (p["initial"].type() != Object) {
- return Status(ErrorCodes::BadValue, "initial has to be an object");
- }
- request->initial = p["initial"].embeddedObject().getOwned();
+ BSONElement reduce = p["$reduce"];
+ if (reduce.eoo()) {
+ return Status(ErrorCodes::BadValue, "$reduce has to be set");
+ }
+ request->reduceCode = reduce._asCode();
- if (!p["finalize"].eoo()) {
- request->finalize = p["finalize"]._asCode();
- }
+ if (reduce.type() == CodeWScope) {
+ request->reduceScope = reduce.codeWScopeObject().getOwned();
+ }
- return Status::OK();
+ if (p["initial"].type() != Object) {
+ return Status(ErrorCodes::BadValue, "initial has to be an object");
}
+ request->initial = p["initial"].embeddedObject().getOwned();
- bool GroupCommand::run(OperationContext* txn,
- const std::string& dbname,
- BSONObj& cmdObj,
- int,
- std::string& errmsg,
- BSONObjBuilder& out) {
- GroupRequest groupRequest;
- Status parseRequestStatus = parseRequest(dbname, cmdObj, &groupRequest);
- if (!parseRequestStatus.isOK()) {
- return appendCommandStatus(out, parseRequestStatus);
- }
+ if (!p["finalize"].eoo()) {
+ request->finalize = p["finalize"]._asCode();
+ }
- AutoGetCollectionForRead ctx(txn, groupRequest.ns);
- Collection* coll = ctx.getCollection();
-
- PlanExecutor *rawPlanExecutor;
- Status getExecStatus = getExecutorGroup(txn,
- coll,
- groupRequest,
- PlanExecutor::YIELD_AUTO,
- &rawPlanExecutor);
- if (!getExecStatus.isOK()) {
- return appendCommandStatus(out, getExecStatus);
- }
+ return Status::OK();
+}
+
+bool GroupCommand::run(OperationContext* txn,
+ const std::string& dbname,
+ BSONObj& cmdObj,
+ int,
+ std::string& errmsg,
+ BSONObjBuilder& out) {
+ GroupRequest groupRequest;
+ Status parseRequestStatus = parseRequest(dbname, cmdObj, &groupRequest);
+ if (!parseRequestStatus.isOK()) {
+ return appendCommandStatus(out, parseRequestStatus);
+ }
- unique_ptr<PlanExecutor> planExecutor(rawPlanExecutor);
-
- // Group executors return ADVANCED exactly once, with the entire group result.
- BSONObj retval;
- PlanExecutor::ExecState state = planExecutor->getNext(&retval, NULL);
- if (PlanExecutor::ADVANCED != state) {
- invariant(PlanExecutor::FAILURE == state || PlanExecutor::DEAD == state);
-
- if (WorkingSetCommon::isValidStatusMemberObject(retval)) {
- return appendCommandStatus(out, WorkingSetCommon::getMemberObjectStatus(retval));
- }
- return appendCommandStatus(out,
- Status(ErrorCodes::BadValue,
- str::stream() << "error encountered during group "
- << "operation, executor returned "
- << PlanExecutor::statestr(state)));
- }
+ AutoGetCollectionForRead ctx(txn, groupRequest.ns);
+ Collection* coll = ctx.getCollection();
- invariant(planExecutor->isEOF());
+ PlanExecutor* rawPlanExecutor;
+ Status getExecStatus =
+ getExecutorGroup(txn, coll, groupRequest, PlanExecutor::YIELD_AUTO, &rawPlanExecutor);
+ if (!getExecStatus.isOK()) {
+ return appendCommandStatus(out, getExecStatus);
+ }
- invariant(STAGE_GROUP == planExecutor->getRootStage()->stageType());
- GroupStage* groupStage = static_cast<GroupStage*>(planExecutor->getRootStage());
- const GroupStats* groupStats =
- static_cast<const GroupStats*>(groupStage->getSpecificStats());
- const CommonStats* groupChildStats = groupStage->getChildren()[0]->getCommonStats();
+ unique_ptr<PlanExecutor> planExecutor(rawPlanExecutor);
- out.appendArray("retval", retval);
- out.append("count", static_cast<long long>(groupChildStats->advanced));
- out.append("keys", static_cast<long long>(groupStats->nGroups));
+ // Group executors return ADVANCED exactly once, with the entire group result.
+ BSONObj retval;
+ PlanExecutor::ExecState state = planExecutor->getNext(&retval, NULL);
+ if (PlanExecutor::ADVANCED != state) {
+ invariant(PlanExecutor::FAILURE == state || PlanExecutor::DEAD == state);
- return true;
+ if (WorkingSetCommon::isValidStatusMemberObject(retval)) {
+ return appendCommandStatus(out, WorkingSetCommon::getMemberObjectStatus(retval));
+ }
+ return appendCommandStatus(out,
+ Status(ErrorCodes::BadValue,
+ str::stream() << "error encountered during group "
+ << "operation, executor returned "
+ << PlanExecutor::statestr(state)));
}
- Status GroupCommand::explain(OperationContext* txn,
- const std::string& dbname,
- const BSONObj& cmdObj,
- ExplainCommon::Verbosity verbosity,
- BSONObjBuilder* out) const {
- GroupRequest groupRequest;
- Status parseRequestStatus = parseRequest(dbname, cmdObj, &groupRequest);
- if (!parseRequestStatus.isOK()) {
- return parseRequestStatus;
- }
+ invariant(planExecutor->isEOF());
+
+ invariant(STAGE_GROUP == planExecutor->getRootStage()->stageType());
+ GroupStage* groupStage = static_cast<GroupStage*>(planExecutor->getRootStage());
+ const GroupStats* groupStats = static_cast<const GroupStats*>(groupStage->getSpecificStats());
+ const CommonStats* groupChildStats = groupStage->getChildren()[0]->getCommonStats();
+
+ out.appendArray("retval", retval);
+ out.append("count", static_cast<long long>(groupChildStats->advanced));
+ out.append("keys", static_cast<long long>(groupStats->nGroups));
+
+ return true;
+}
+
+Status GroupCommand::explain(OperationContext* txn,
+ const std::string& dbname,
+ const BSONObj& cmdObj,
+ ExplainCommon::Verbosity verbosity,
+ BSONObjBuilder* out) const {
+ GroupRequest groupRequest;
+ Status parseRequestStatus = parseRequest(dbname, cmdObj, &groupRequest);
+ if (!parseRequestStatus.isOK()) {
+ return parseRequestStatus;
+ }
- groupRequest.explain = true;
+ groupRequest.explain = true;
- AutoGetCollectionForRead ctx(txn, groupRequest.ns);
- Collection* coll = ctx.getCollection();
+ AutoGetCollectionForRead ctx(txn, groupRequest.ns);
+ Collection* coll = ctx.getCollection();
- PlanExecutor *rawPlanExecutor;
- Status getExecStatus = getExecutorGroup(txn,
- coll,
- groupRequest,
- PlanExecutor::YIELD_AUTO,
- &rawPlanExecutor);
- if (!getExecStatus.isOK()) {
- return getExecStatus;
- }
+ PlanExecutor* rawPlanExecutor;
+ Status getExecStatus =
+ getExecutorGroup(txn, coll, groupRequest, PlanExecutor::YIELD_AUTO, &rawPlanExecutor);
+ if (!getExecStatus.isOK()) {
+ return getExecStatus;
+ }
- unique_ptr<PlanExecutor> planExecutor(rawPlanExecutor);
+ unique_ptr<PlanExecutor> planExecutor(rawPlanExecutor);
- Explain::explainStages(planExecutor.get(), verbosity, out);
- return Status::OK();
- }
+ Explain::explainStages(planExecutor.get(), verbosity, out);
+ return Status::OK();
+}
} // namespace mongo