diff options
-rw-r--r-- | src/mongo/db/commands/current_op.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/commands/dbcommands.cpp | 15 | ||||
-rw-r--r-- | src/mongo/db/commands/find_cmd.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/commands/getmore_cmd.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/commands/list_collections.cpp | 27 | ||||
-rw-r--r-- | src/mongo/db/commands/list_databases.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/commands/list_indexes.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/commands/pipeline_command.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_coll_stats.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/query/query_request_helper.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/query/query_request_helper.h | 4 | ||||
-rw-r--r-- | src/mongo/db/query/query_request_test.cpp | 16 | ||||
-rw-r--r-- | src/mongo/util/serialization_context.h | 7 |
15 files changed, 110 insertions, 34 deletions
diff --git a/src/mongo/db/commands/current_op.cpp b/src/mongo/db/commands/current_op.cpp index 8ba08e6c37b..dd888b36db8 100644 --- a/src/mongo/db/commands/current_op.cpp +++ b/src/mongo/db/commands/current_op.cpp @@ -96,8 +96,12 @@ public: CommandHelpers::appendSimpleCommandStatus(bodyBuilder, true); bodyBuilder.doneFast(); + // We need to copy the serialization context from the request to the reply object return CursorResponse::parseFromBSON( - replyBuilder.releaseBody(), nullptr, request.getNamespace().tenantId()); + replyBuilder.releaseBody(), + nullptr, + request.getNamespace().tenantId(), + SerializationContext::stateCommandReply(request.getSerializationContext())); } virtual void appendToResponse(BSONObjBuilder* result) const final { diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp index 147df508a9c..ba74cea6106 100644 --- a/src/mongo/db/commands/dbcommands.cpp +++ b/src/mongo/db/commands/dbcommands.cpp @@ -220,7 +220,9 @@ public: !storageEngine->supportsRecoveryTimestamp()); } - Reply reply; + // We need to copy the serialization context from the request to the reply object + Reply reply( + SerializationContext::stateCommandReply(request().getSerializationContext())); uassertStatusOK( dropCollection(opCtx, request().getNamespace(), @@ -457,7 +459,13 @@ public: uassert(ErrorCodes::OperationFailed, "No collection name specified", !nss.coll().empty()); - result.append("ns", NamespaceStringUtil::serialize(nss)); + // We need to use the serialization context from the request when calling + // NamespaceStringUtil to build the reply + result.append( + "ns", + NamespaceStringUtil::serialize( + nss, SerializationContext::stateCommandReply(cmd.getSerializationContext()))); + auto spec = StorageStatsSpec::parse(IDLParserContext("collStats"), cmdObj); Status status = appendCollectionStorageStats(opCtx, nss, spec, &result); if (!status.isOK() && (status.code() != ErrorCodes::NamespaceNotFound)) { @@ -640,7 +648,8 @@ public: AutoGetDb autoDb(opCtx, dbname, MODE_IS); Database* db = autoDb.getDb(); - Reply reply; + // We need to copy the serialization context from the request to the reply object + Reply reply(SerializationContext::stateCommandReply(cmd.getSerializationContext())); reply.setDB(dbname.db()); if (!db) { diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp index 2b6d5cb9dc8..2c261b751b2 100644 --- a/src/mongo/db/commands/find_cmd.cpp +++ b/src/mongo/db/commands/find_cmd.cpp @@ -571,6 +571,10 @@ public: } } + // We need to copy the serialization context from the request to the reply object before + // the request object goes out of scope + const auto serializationContext = cq->getFindCommandRequest().getSerializationContext(); + // Get the execution plan for the query. bool permitYield = true; auto exec = @@ -726,8 +730,8 @@ public: // documents. auto& metricsCollector = ResourceConsumption::MetricsCollector::get(opCtx); metricsCollector.incrementDocUnitsReturned(nss.ns(), docUnitsReturned); - query_request_helper::validateCursorResponse(result->getBodyBuilder().asTempObj(), - nss.tenantId()); + query_request_helper::validateCursorResponse( + result->getBodyBuilder().asTempObj(), nss.tenantId(), serializationContext); } void appendMirrorableRequest(BSONObjBuilder* bob) const override { diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp index 28a3d8fb43b..8f91862d002 100644 --- a/src/mongo/db/commands/getmore_cmd.cpp +++ b/src/mongo/db/commands/getmore_cmd.cpp @@ -797,9 +797,14 @@ public: void validateResult(rpc::ReplyBuilderInterface* reply, boost::optional<TenantId> tenantId) { auto ret = reply->getBodyBuilder().asTempObj(); - CursorGetMoreReply::parse( - IDLParserContext{"CursorGetMoreReply", false /* apiStrict */, tenantId}, - ret.removeField("ok")); + + // We need to copy the serialization context from the request to the reply object + CursorGetMoreReply::parse(IDLParserContext("CursorGetMoreReply", + false /* apiStrict */, + tenantId, + SerializationContext::stateCommandReply( + _cmd.getSerializationContext())), + ret.removeField("ok")); } const GetMoreCommandRequest _cmd; diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp index 571c3156786..f332d975201 100644 --- a/src/mongo/db/commands/list_collections.cpp +++ b/src/mongo/db/commands/list_collections.cpp @@ -255,9 +255,14 @@ BSONObj buildCollectionBson(OperationContext* opCtx, ListCollectionsReply createListCollectionsCursorReply( CursorId cursorId, const NamespaceString& cursorNss, + const SerializationContext& serializationContext, std::vector<mongo::ListCollectionsReplyItem>&& firstBatch) { return ListCollectionsReply( - ListCollectionsReplyCursor(cursorId, cursorNss, std::move(firstBatch))); + ListCollectionsReplyCursor(cursorId, + cursorNss, + std::move(firstBatch), + SerializationContext::stateCommandReply(serializationContext)), + SerializationContext::stateCommandReply(serializationContext)); } class CmdListCollections : public ListCollectionsCmdVersion1Gen<CmdListCollections> { @@ -316,6 +321,9 @@ public: const bool nameOnly = listCollRequest.getNameOnly(); const bool authorizedCollections = listCollRequest.getAuthorizedCollections(); + // We need to copy the serialization context from the request to the reply object + const auto serializationContext = listCollRequest.getSerializationContext(); + // The collator is null because collection objects are compared using binary comparison. auto expCtx = make_intrusive<ExpressionContext>( opCtx, std::unique_ptr<CollatorInterface>(nullptr), ns()); @@ -520,10 +528,11 @@ public: try { firstBatch.push_back(ListCollectionsReplyItem::parse( - IDLParserContext("ListCollectionsReplyItem", - false /* apiStrict*/, - cursorNss.tenantId(), - SerializationContext::stateCommandReply()), + IDLParserContext( + "ListCollectionsReplyItem", + false /* apiStrict*/, + cursorNss.tenantId(), + SerializationContext::stateCommandReply(serializationContext)), nextDoc)); } catch (const DBException& exc) { LOGV2_ERROR( @@ -537,7 +546,7 @@ public: } if (exec->isEOF()) { return createListCollectionsCursorReply( - 0 /* cursorId */, cursorNss, std::move(firstBatch)); + 0 /* cursorId */, cursorNss, serializationContext, std::move(firstBatch)); } exec->saveState(); exec->detachFromOperationContext(); @@ -560,8 +569,10 @@ public: pinnedCursor->incNBatches(); pinnedCursor->incNReturnedSoFar(firstBatch.size()); - return createListCollectionsCursorReply( - pinnedCursor.getCursor()->cursorid(), cursorNss, std::move(firstBatch)); + return createListCollectionsCursorReply(pinnedCursor.getCursor()->cursorid(), + cursorNss, + serializationContext, + std::move(firstBatch)); } }; } cmdListCollections; diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp index 3ad19b1d236..2f07229b1cd 100644 --- a/src/mongo/db/commands/list_databases.cpp +++ b/src/mongo/db/commands/list_databases.cpp @@ -135,7 +135,9 @@ public: false /* setTenantId */, authorizedDatabases); - ListDatabasesReply reply(items); + // We need to copy the serialization context from the request to the reply object + ListDatabasesReply reply( + items, SerializationContext::stateCommandReply(cmd.getSerializationContext())); if (!nameOnly) { reply.setTotalSize(totalSize); reply.setTotalSizeMb(totalSize / (1024 * 1024)); diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp index 951d1f6e4a4..848fbb896c8 100644 --- a/src/mongo/db/commands/list_indexes.cpp +++ b/src/mongo/db/commands/list_indexes.cpp @@ -285,6 +285,9 @@ public: const NamespaceString& nss) { auto& cmd = request(); + // We need to copy the serialization context from the request to the reply object + const auto serializationContext = cmd.getSerializationContext(); + long long batchSize = std::numeric_limits<long long>::max(); if (cmd.getCursor() && cmd.getCursor()->getBatchSize()) { batchSize = *cmd.getCursor()->getBatchSize(); @@ -335,7 +338,12 @@ public: try { firstBatch.push_back(ListIndexesReplyItem::parse( - IDLParserContext("ListIndexesReplyItem"), nextDoc)); + IDLParserContext( + "ListIndexesReplyItem", + false /* apiStrict */, + nss.tenantId(), + SerializationContext::stateCommandReply(serializationContext)), + nextDoc)); } catch (const DBException& exc) { LOGV2_ERROR(5254500, "Could not parse catalog entry while replying to listIndexes", @@ -351,7 +359,11 @@ public: } if (exec->isEOF()) { - return ListIndexesReplyCursor(0 /* cursorId */, nss, std::move(firstBatch)); + return ListIndexesReplyCursor( + 0 /* cursorId */, + nss, + std::move(firstBatch), + SerializationContext::stateCommandReply(serializationContext)); } exec->saveState(); @@ -374,7 +386,10 @@ public: pinnedCursor->incNReturnedSoFar(firstBatch.size()); return ListIndexesReplyCursor( - pinnedCursor.getCursor()->cursorid(), nss, std::move(firstBatch)); + pinnedCursor.getCursor()->cursorid(), + nss, + std::move(firstBatch), + SerializationContext::stateCommandReply(serializationContext)); } }; } cmdListIndexes; diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp index 337c3e5b067..20eab15b603 100644 --- a/src/mongo/db/commands/pipeline_command.cpp +++ b/src/mongo/db/commands/pipeline_command.cpp @@ -230,7 +230,8 @@ public: if (!_aggregationRequest.getExplain() && !_aggregationRequest.getExchange()) { query_request_helper::validateCursorResponse( reply->getBodyBuilder().asTempObj(), - _aggregationRequest.getNamespace().tenantId()); + _aggregationRequest.getNamespace().tenantId(), + _aggregationRequest.getSerializationContext()); } } diff --git a/src/mongo/db/pipeline/document_source_coll_stats.cpp b/src/mongo/db/pipeline/document_source_coll_stats.cpp index 0facc2283ef..1df5e681484 100644 --- a/src/mongo/db/pipeline/document_source_coll_stats.cpp +++ b/src/mongo/db/pipeline/document_source_coll_stats.cpp @@ -78,7 +78,12 @@ BSONObj DocumentSourceCollStats::makeStatsForNs( const boost::optional<BSONObj>& filterObj) { BSONObjBuilder builder; - builder.append("ns", NamespaceStringUtil::serialize(nss)); + // We need to use the serialization context from the request when calling + // NamespaceStringUtil to build the reply + builder.append( + "ns", + NamespaceStringUtil::serialize( + nss, SerializationContext::stateCommandReply(spec.getSerializationContext()))); auto shardName = expCtx->mongoProcessInterface->getShardName(expCtx->opCtx); diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp index e45933d4f73..bd7e20902ba 100644 --- a/src/mongo/db/pipeline/document_source_out.cpp +++ b/src/mongo/db/pipeline/document_source_out.cpp @@ -96,8 +96,10 @@ DocumentSourceOutSpec DocumentSourceOut::parseOutSpecAndResolveTargetNamespace( DocumentSourceOutSpec outSpec; if (spec.type() == BSONType::String) { outSpec.setColl(spec.valueStringData()); + // TODO SERVER-77000: access a SerializationContext object to serialize properly outSpec.setDb(defaultDB.db()); } else if (spec.type() == BSONType::Object) { + // TODO SERVER-77000: access a SerializationContext object to pass into the IDLParserContext outSpec = mongo::DocumentSourceOutSpec::parse(IDLParserContext(kStageName), spec.embeddedObject()); } else { @@ -325,6 +327,7 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( Value DocumentSourceOut::serialize(SerializationOptions opts) const { BSONObjBuilder bob; DocumentSourceOutSpec spec; + // TODO SERVER-74284: use SerializatonContext from expCtx and DatabaseNameUtil to serialize spec.setDb(_outputNs.dbName().db()); spec.setColl(_outputNs.coll()); spec.setTimeseries(_timeseries); diff --git a/src/mongo/db/pipeline/document_source_out_test.cpp b/src/mongo/db/pipeline/document_source_out_test.cpp index bae50841f0a..324d681c221 100644 --- a/src/mongo/db/pipeline/document_source_out_test.cpp +++ b/src/mongo/db/pipeline/document_source_out_test.cpp @@ -216,6 +216,8 @@ TEST_F(DocumentSourceOutServerlessTest, CreateFromBSONContainsExpectedNamespaces ASSERT_EQ(outSource->getOutputNs(), NamespaceString::createNamespaceString_forTest(defaultDb, targetColl)); + // TODO SERVER-74284: update this test once the serialize function has been updated to use + // DatabaseNameUtil::serialize() instead // Assert the tenantId is not included in the serialized namespace. auto serialized = outSource->serialize().getDocument(); auto expectedDoc = Document{{"coll", targetColl}, {"db", expCtx->ns.dbName().db()}}; diff --git a/src/mongo/db/query/query_request_helper.cpp b/src/mongo/db/query/query_request_helper.cpp index 16d95be8c87..477ab4d4834 100644 --- a/src/mongo/db/query/query_request_helper.cpp +++ b/src/mongo/db/query/query_request_helper.cpp @@ -231,10 +231,16 @@ TailableModeEnum getTailableMode(const FindCommandRequest& findCommand) { tailableModeFromBools(findCommand.getTailable(), findCommand.getAwaitData())); } -void validateCursorResponse(const BSONObj& outputAsBson, boost::optional<TenantId> tenantId) { +void validateCursorResponse(const BSONObj& outputAsBson, + boost::optional<TenantId> tenantId, + const SerializationContext& serializationContext) { if (getTestCommandsEnabled()) { CursorInitialReply::parse( - IDLParserContext("CursorInitialReply", false /* apiStrict */, tenantId), outputAsBson); + IDLParserContext("CursorInitialReply", + false /* apiStrict */, + tenantId, + SerializationContext::stateCommandReply(serializationContext)), + outputAsBson); } } diff --git a/src/mongo/db/query/query_request_helper.h b/src/mongo/db/query/query_request_helper.h index 3f73d188578..4f60e34ebb6 100644 --- a/src/mongo/db/query/query_request_helper.h +++ b/src/mongo/db/query/query_request_helper.h @@ -139,7 +139,9 @@ TailableModeEnum getTailableMode(const FindCommandRequest& findCommand); /** * Asserts whether the cursor response adhere to the format defined in IDL. */ -void validateCursorResponse(const BSONObj& outputAsBson, boost::optional<TenantId> tenantId); +void validateCursorResponse(const BSONObj& outputAsBson, + boost::optional<TenantId> tenantId, + const SerializationContext& serializationContext); /** * Updates the projection object with a $meta projection for the showRecordId option. diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp index 15827a9be2f..7ae44a202fb 100644 --- a/src/mongo/db/query/query_request_test.cpp +++ b/src/mongo/db/query/query_request_test.cpp @@ -1524,19 +1524,19 @@ TEST(QueryRequestTest, ConvertToFindWithAllowDiskUseFalseSucceeds) { TEST(QueryRequestHelperTest, ValidateResponseMissingFields) { BSONObjBuilder builder; - ASSERT_THROWS_CODE( - query_request_helper::validateCursorResponse(builder.asTempObj(), boost::none), - DBException, - 6253507); + ASSERT_THROWS_CODE(query_request_helper::validateCursorResponse( + builder.asTempObj(), boost::none, SerializationContext()), + DBException, + 6253507); } TEST(QueryRequestHelperTest, ValidateResponseWrongDataType) { BSONObjBuilder builder; builder.append("cursor", 1); - ASSERT_THROWS_CODE( - query_request_helper::validateCursorResponse(builder.asTempObj(), boost::none), - DBException, - ErrorCodes::TypeMismatch); + ASSERT_THROWS_CODE(query_request_helper::validateCursorResponse( + builder.asTempObj(), boost::none, SerializationContext()), + DBException, + ErrorCodes::TypeMismatch); } TEST(QueryRequestHelperTest, ParsedCursorRemainsValidAfterBSONDestroyed) { diff --git a/src/mongo/util/serialization_context.h b/src/mongo/util/serialization_context.h index 356cc3e9c8c..62fc4f59f39 100644 --- a/src/mongo/util/serialization_context.h +++ b/src/mongo/util/serialization_context.h @@ -97,6 +97,13 @@ struct SerializationContext { return *stateCommandReply; } + static SerializationContext stateCommandReply(const SerializationContext& requestCtxt) { + return SerializationContext(Source::Command, + CallerType::Reply, + requestCtxt._prefixState, + requestCtxt._nonPrefixedTenantId); + } + static const SerializationContext& stateCommandRequest() { static StaticImmortal<SerializationContext> stateCommandRequest{Source::Command, CallerType::Request}; |