diff options
Diffstat (limited to 'src/mongo/db/commands/group.cpp')
-rw-r--r-- | src/mongo/db/commands/group.cpp | 280 |
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 |