diff options
| author | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-14 14:26:38 -0300 |
|---|---|---|
| committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-14 14:26:38 -0300 |
| commit | 294bc6ecabf14c09c9bc8644704921dcf97cb44e (patch) | |
| tree | 279b1e0bab53901a1647ac63c1c724f0f789a663 /src/mongo/db/commands/find_cmd.cpp | |
| parent | 70be7c27a251621187a1de533462ae2bb1e3bd39 (diff) | |
| parent | 1e917fd798aa25b7066d4b414b51184f13d5a092 (diff) | |
Update upstream source from tag 'upstream/6.0.10'debian/6.0.10-1
Update to upstream version '6.0.10'
with Debian dir 2d176fa254eee97b139f712fec5709641335a8c3
Diffstat (limited to 'src/mongo/db/commands/find_cmd.cpp')
| -rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index f7ac781404f..1fdb621add3 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -133,11 +133,17 @@ std::unique_ptr<FindCommandRequest> parseCmdObjectToFindCommandRequest(Operation boost::intrusive_ptr<ExpressionContext> makeExpressionContext( OperationContext* opCtx, const FindCommandRequest& findCommand, + const CollectionPtr& collPtr, boost::optional<ExplainOptions::Verbosity> verbosity) { std::unique_ptr<CollatorInterface> collator; if (!findCommand.getCollation().isEmpty()) { collator = uassertStatusOK(CollatorFactoryInterface::get(opCtx->getServiceContext()) ->makeFromBSON(findCommand.getCollation())); + } else if (collPtr && collPtr->getDefaultCollator()) { + // The 'collPtr' will be null for views, but we don't need to worry about views here. The + // views will get rewritten into aggregate command and will regenerate the + // ExpressionContext. + collator = collPtr->getDefaultCollator()->clone(); } // Although both 'find' and 'aggregate' commands have an ExpressionContext, some of the data @@ -320,7 +326,16 @@ public: // Finish the parsing step by using the FindCommandRequest to create a CanonicalQuery. const ExtensionsCallbackReal extensionsCallback(opCtx, &nss); - auto expCtx = makeExpressionContext(opCtx, *findCommand, verbosity); + + // The collection may be NULL. If so, getExecutor() should handle it by returning an + // execution tree with an EOFStage. + const auto& collection = ctx->getCollection(); + if (!ctx->getView()) { + const bool isClusteredCollection = collection && collection->isClustered(); + uassertStatusOK(query_request_helper::validateResumeAfter( + findCommand->getResumeAfter(), isClusteredCollection)); + } + auto expCtx = makeExpressionContext(opCtx, *findCommand, collection, verbosity); const bool isExplain = true; auto cq = uassertStatusOK( CanonicalQuery::canonicalize(opCtx, @@ -370,10 +385,6 @@ public: return; } - // The collection may be NULL. If so, getExecutor() should handle it by returning an - // execution tree with an EOFStage. - const auto& collection = ctx->getCollection(); - // Get the execution plan for the query. bool permitYield = true; auto exec = @@ -505,14 +516,16 @@ public: } // Tailing a replicated capped clustered collection requires majority read concern. - const auto coll = ctx->getCollection().get(); - if (coll) { + const auto& collection = ctx->getCollection(); + + bool isClusteredCollection = false; + if (collection) { const bool isTailable = findCommand->getTailable(); const bool isMajorityReadConcern = repl::ReadConcernArgs::get(opCtx).getLevel() == repl::ReadConcernLevel::kMajorityReadConcern; - const bool isClusteredCollection = coll->isClustered(); - const bool isCapped = coll->isCapped(); - const bool isReplicated = coll->ns().isReplicated(); + isClusteredCollection = collection->isClustered(); + const bool isCapped = collection->isCapped(); + const bool isReplicated = collection->ns().isReplicated(); if (isClusteredCollection && isCapped && isReplicated && isTailable) { uassert(ErrorCodes::Error(6049203), "A tailable cursor on a capped clustered collection requires majority " @@ -521,12 +534,22 @@ public: } } + // Views use the aggregation system and the $_resumeAfter parameter is not allowed. A + // more descriptive error will be raised later, but we want to validate this parameter + // before beginning the operation. + if (!ctx->getView()) { + uassertStatusOK(query_request_helper::validateResumeAfter( + findCommand->getResumeAfter(), isClusteredCollection)); + } + // Fill out curop information. beginQueryOp(opCtx, nss, _request.body); // Finish the parsing step by using the FindCommandRequest to create a CanonicalQuery. const ExtensionsCallbackReal extensionsCallback(opCtx, &nss); - auto expCtx = makeExpressionContext(opCtx, *findCommand, boost::none /* verbosity */); + + auto expCtx = + makeExpressionContext(opCtx, *findCommand, collection, boost::none /* verbosity */); auto cq = uassertStatusOK( CanonicalQuery::canonicalize(opCtx, std::move(findCommand), @@ -570,8 +593,6 @@ public: uassertStatusOK(replCoord->checkCanServeReadsFor( opCtx, nss, ReadPreferenceSetting::get(opCtx).canRunOnSecondary())); - const auto& collection = ctx->getCollection(); - if (cq->getFindCommandRequest().getReadOnce()) { // The readOnce option causes any storage-layer cursors created during plan // execution to assume read data will not be needed again and need not be cached. @@ -656,8 +677,6 @@ public: auto&& [stats, _] = explainer.getWinningPlanStats(ExplainOptions::Verbosity::kExecStats); LOGV2_WARNING(23798, - "Plan executor error during find command: {error}, " - "stats: {stats}, cmd: {cmd}", "Plan executor error during find command", "error"_attr = exception.toStatus(), "stats"_attr = redact(stats), @@ -715,14 +734,14 @@ public: if (stashResourcesForGetMore) { // Collect storage stats now before we stash the recovery unit. These stats are // normally collected in the service entry point layer just before a command - // ends, but they must be collected before stashing the - // RecoveryUnit. Otherwise, the service entry point layer will collect the - // stats from the new RecoveryUnit, which wasn't actually used for the query. + // ends, but they must be collected before stashing the RecoveryUnit. Otherwise, + // the service entry point layer will collect the stats from the new + // RecoveryUnit, which wasn't actually used for the query. // // The stats collected here will not get overwritten, as the service entry // point layer will only set these stats when they're not empty. CurOp::get(opCtx)->debug().storageStats = - opCtx->recoveryUnit()->getOperationStatistics(); + opCtx->recoveryUnit()->computeOperationStatisticsSinceLastCall(); } } else { endQueryOp(opCtx, collection, *exec, numResults, cursorId); |
