// static StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize( OperationContext* opCtx, const CanonicalQuery& baseQuery, MatchExpression* root, const ExtensionsCallback& extensionsCallback) { // TODO: we should be passing the filter corresponding to 'root' to the QR rather than the base // query's filter, baseQuery.getQueryRequest().getFilter(). auto qr = stdx::make_unique<QueryRequest>(baseQuery.nss()); qr->setFilter(baseQuery.getQueryRequest().getFilter()); qr->setProj(baseQuery.getQueryRequest().getProj()); qr->setSort(baseQuery.getQueryRequest().getSort()); qr->setCollation(baseQuery.getQueryRequest().getCollation()); qr->setExplain(baseQuery.getQueryRequest().isExplain()); auto qrStatus = qr->validate(); if (!qrStatus.isOK()) { return qrStatus; } std::unique_ptr<CollatorInterface> collator; if (baseQuery.getCollator()) { collator = baseQuery.getCollator()->clone(); } // Make the CQ we'll hopefully return. std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery()); Status initStatus = cq->init( std::move(qr), extensionsCallback, root->shallowClone().release(), std::move(collator)); if (!initStatus.isOK()) { return initStatus; } return std::move(cq); }
// static StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize( OperationContext* opCtx, const CanonicalQuery& baseQuery, MatchExpression* root) { auto qr = stdx::make_unique<QueryRequest>(baseQuery.nss()); BSONObjBuilder builder; root->serialize(&builder); qr->setFilter(builder.obj()); qr->setProj(baseQuery.getQueryRequest().getProj()); qr->setSort(baseQuery.getQueryRequest().getSort()); qr->setCollation(baseQuery.getQueryRequest().getCollation()); qr->setExplain(baseQuery.getQueryRequest().isExplain()); auto qrStatus = qr->validate(); if (!qrStatus.isOK()) { return qrStatus; } std::unique_ptr<CollatorInterface> collator; if (baseQuery.getCollator()) { collator = baseQuery.getCollator()->clone(); } // Make the CQ we'll hopefully return. std::unique_ptr<CanonicalQuery> cq(new CanonicalQuery()); Status initStatus = cq->init(opCtx, std::move(qr), baseQuery.canHaveNoopMatchNodes(), root->shallowClone(), std::move(collator)); if (!initStatus.isOK()) { return initStatus; } return std::move(cq); }
Status PlanCache::add(const CanonicalQuery& query, const std::vector<QuerySolution*>& solns, PlanRankingDecision* why, Date_t now) { invariant(why); if (solns.empty()) { return Status(ErrorCodes::BadValue, "no solutions provided"); } if (why->stats.size() != solns.size()) { return Status(ErrorCodes::BadValue, "number of stats in decision must match solutions"); } if (why->scores.size() != solns.size()) { return Status(ErrorCodes::BadValue, "number of scores in decision must match solutions"); } if (why->candidateOrder.size() != solns.size()) { return Status(ErrorCodes::BadValue, "candidate ordering entries in decision must match solutions"); } PlanCacheEntry* entry = new PlanCacheEntry(solns, why); const QueryRequest& qr = query.getQueryRequest(); entry->query = qr.getFilter().getOwned(); entry->sort = qr.getSort().getOwned(); if (query.getCollator()) { entry->collation = query.getCollator()->getSpec().toBSON(); } entry->timeOfCreation = now; // Strip projections on $-prefixed fields, as these are added by internal callers of the query // system and are not considered part of the user projection. BSONObjBuilder projBuilder; for (auto elem : qr.getProj()) { if (elem.fieldName()[0] == '$') { continue; } projBuilder.append(elem); } entry->projection = projBuilder.obj(); stdx::lock_guard<stdx::mutex> cacheLock(_cacheMutex); std::unique_ptr<PlanCacheEntry> evictedEntry = _cache.add(computeKey(query), entry); if (NULL != evictedEntry.get()) { LOG(1) << _ns << ": plan cache maximum size exceeded - " << "removed least recently used entry " << redact(evictedEntry->toString()); } return Status::OK(); }
// static bool IDHackStage::supportsQuery(Collection* collection, const CanonicalQuery& query) { return !query.getQueryRequest().showRecordId() && query.getQueryRequest().getHint().isEmpty() && !query.getQueryRequest().getSkip() && CanonicalQuery::isSimpleIdQuery(query.getQueryRequest().getFilter()) && !query.getQueryRequest().isTailable() && CollatorInterface::collatorsMatch(query.getCollator(), collection->getDefaultCollator()); }
void QuerySettings::setAllowedIndices(const CanonicalQuery& canonicalQuery, const PlanCacheKey& key, const BSONObjSet& indexKeyPatterns, const stdx::unordered_set<std::string>& indexNames) { const QueryRequest& qr = canonicalQuery.getQueryRequest(); const BSONObj& query = qr.getFilter(); const BSONObj& sort = qr.getSort(); const BSONObj& projection = qr.getProj(); const BSONObj collation = canonicalQuery.getCollator() ? canonicalQuery.getCollator()->getSpec().toBSON() : BSONObj(); stdx::lock_guard<stdx::mutex> cacheLock(_mutex); _allowedIndexEntryMap.erase(key); _allowedIndexEntryMap.emplace( std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(query, sort, projection, collation, indexKeyPatterns, indexNames)); }