Example #1
0
    Status FindCmd::explain(OperationContext* txn,
                             const std::string& dbname,
                             const BSONObj& cmdObj,
                             ExplainCommon::Verbosity verbosity,
                             BSONObjBuilder* out) const {
        const string fullns = parseNs(dbname, cmdObj);

        // Parse the command BSON to a LiteParsedQuery.
        LiteParsedQuery* rawLpq;
        bool isExplain = true;
        Status lpqStatus = LiteParsedQuery::make(fullns, cmdObj, isExplain, &rawLpq);
        if (!lpqStatus.isOK()) {
            return lpqStatus;
        }
        auto_ptr<LiteParsedQuery> lpq(rawLpq);

        const NamespaceString nss(fullns);

        // Finish the parsing step by using the LiteParsedQuery to create a CanonicalQuery.
        // This requires a lock on the collection in case we're parsing $where: where-specific
        // parsing code assumes we have a lock and creates execution machinery that requires it.
        CanonicalQuery* rawCq;
        WhereCallbackReal whereCallback(txn, nss.db());
        Status canonStatus = CanonicalQuery::canonicalize(lpq.release(), &rawCq, whereCallback);
        if (!canonStatus.isOK()) {
            return canonStatus;
        }
        auto_ptr<CanonicalQuery> cq(rawCq);

        AutoGetCollectionForRead ctx(txn, nss);
        // The collection may be NULL. If so, getExecutor() should handle it by returning
        // an execution tree with an EOFStage.
        Collection* collection = ctx.getCollection();

        // We have a parsed query. Time to get the execution plan for it.
        PlanExecutor* rawExec;
        Status execStatus = Status::OK();
        if (cq->getParsed().getOptions().oplogReplay) {
            execStatus = getOplogStartHack(txn, collection, cq.release(), &rawExec);
        }
        else {
            size_t options = QueryPlannerParams::DEFAULT;
            if (shardingState.needCollectionMetadata(cq->getParsed().ns())) {
                options |= QueryPlannerParams::INCLUDE_SHARD_FILTER;
            }

            execStatus = getExecutor(txn, collection, cq.release(), &rawExec, options);
        }

        if (!execStatus.isOK()) {
            return execStatus;
        }

        scoped_ptr<PlanExecutor> exec(rawExec);
        exec->setYieldPolicy(PlanExecutor::YIELD_AUTO);

        // Got the execution tree. Explain it.
        return Explain::explainStages(exec.get(), verbosity, out);
    }
Example #2
0
    // static
    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) {
        LiteParsedQuery* lpqRaw;
        // Pass empty sort and projection.
        BSONObj emptyObj;
        Status parseStatus = LiteParsedQuery::make(ns, skip, limit, 0, query, proj, sort,
                                                   hint, minObj, maxObj, snapshot, explain,
                                                   &lpqRaw);
        if (!parseStatus.isOK()) {
            return parseStatus;
        }
        std::auto_ptr<LiteParsedQuery> lpq(lpqRaw);

        // Build a parse tree from the BSONObj in the parsed query.
        StatusWithMatchExpression swme = 
                            MatchExpressionParser::parse(lpq->getFilter(), whereCallback);
        if (!swme.isOK()) {
            return swme.getStatus();
        }

        // Make the CQ we'll hopefully return.
        std::auto_ptr<CanonicalQuery> cq(new CanonicalQuery());
        // Takes ownership of lpq and the MatchExpression* in swme.
        Status initStatus = cq->init(lpq.release(), whereCallback, swme.getValue());

        if (!initStatus.isOK()) { return initStatus; }
        *out = cq.release();
        return Status::OK();
    }
Example #3
0
    Status ClusterFindCmd::explain(OperationContext* txn,
                                   const std::string& dbname,
                                   const BSONObj& cmdObj,
                                   ExplainCommon::Verbosity verbosity,
                                   BSONObjBuilder* out) const {
        const string fullns = parseNs(dbname, cmdObj);

        // Parse the command BSON to a LiteParsedQuery.
        LiteParsedQuery* rawLpq;
        bool isExplain = true;
        Status lpqStatus = LiteParsedQuery::make(fullns, cmdObj, isExplain, &rawLpq);
        if (!lpqStatus.isOK()) {
            return lpqStatus;
        }
        auto_ptr<LiteParsedQuery> lpq(rawLpq);

        BSONObjBuilder explainCmdBob;
        ClusterExplain::wrapAsExplain(cmdObj, verbosity, &explainCmdBob);

        // We will time how long it takes to run the commands on the shards.
        Timer timer;

        vector<Strategy::CommandResult> shardResults;
        STRATEGY->commandOp(dbname,
                            explainCmdBob.obj(),
                            lpq->getOptions().toInt(),
                            fullns,
                            lpq->getFilter(),
                            &shardResults);

        long long millisElapsed = timer.millis();

        const char* mongosStageName = ClusterExplain::getStageNameForReadOp(shardResults, cmdObj);

        return ClusterExplain::buildExplainResult(shardResults,
                                                  mongosStageName,
                                                  millisElapsed,
                                                  out);
    }