std::unique_ptr<LiteParsedDocumentSourceForeignCollections> DocumentSourceOut::liteParse( const AggregationRequest& request, const BSONElement& spec) { uassert(ErrorCodes::TypeMismatch, str::stream() << "$out stage requires a string argument, but found " << typeName(spec.type()), spec.type() == BSONType::String); NamespaceString targetNss(request.getNamespaceString().db(), spec.valueStringData()); uassert(ErrorCodes::InvalidNamespace, str::stream() << "Invalid $out target namespace, " << targetNss.ns(), targetNss.isValid()); ActionSet actions{ActionType::remove, ActionType::insert}; if (request.shouldBypassDocumentValidation()) { actions.addAction(ActionType::bypassDocumentValidation); } PrivilegeVector privileges{Privilege(ResourcePattern::forExactNamespace(targetNss), actions)}; return stdx::make_unique<LiteParsedDocumentSourceForeignCollections>(std::move(targetNss), std::move(privileges)); }
Status renameCollectionForApplyOps(OperationContext* opCtx, const std::string& dbName, const BSONElement& ui, const BSONObj& cmd) { const auto sourceNsElt = cmd.firstElement(); const auto targetNsElt = cmd["to"]; const auto dropSourceElt = cmd["dropSource"]; uassert(ErrorCodes::TypeMismatch, "'renameCollection' must be of type String", sourceNsElt.type() == BSONType::String); uassert(ErrorCodes::TypeMismatch, "'to' must be of type String", targetNsElt.type() == BSONType::String); NamespaceString sourceNss(sourceNsElt.valueStringData()); NamespaceString targetNss(targetNsElt.valueStringData()); NamespaceString uiNss(getNamespaceFromUUID(opCtx, ui)); NamespaceString dropSourceNss(getNamespaceFromUUID(opCtx, dropSourceElt)); // If the UUID we're targeting already exists, rename from there no matter what. // When dropSource is specified, the rename is accross databases. In that case, ui indicates // the UUID of the new target collection and the dropSourceNss specifies the sourceNss. if (!uiNss.isEmpty()) { sourceNss = uiNss; // The cross-database rename was already done and just needs a local rename, but we may // still need to actually remove the source collection. auto dropSourceNss = getNamespaceFromUUID(opCtx, dropSourceElt); if (!dropSourceNss.isEmpty()) { BSONObjBuilder unusedBuilder; dropCollection(opCtx, dropSourceNss, unusedBuilder, repl::OpTime(), DropCollectionSystemCollectionMode::kAllowSystemCollectionDrops) .ignore(); } } else if (!dropSourceNss.isEmpty()) { sourceNss = dropSourceNss; } else { // When replaying cross-database renames, both source and target collections may no longer // exist. Attempting a rename anyway could result in removing a newer collection of the // same name. uassert(ErrorCodes::NamespaceNotFound, str::stream() << "source collection (UUID " << uassertStatusOK(UUID::parse(dropSourceElt)) << ") for rename to " << targetNss.ns() << " no longer exists", !dropSourceElt); } OptionalCollectionUUID targetUUID; if (!ui.eoo()) targetUUID = uassertStatusOK(UUID::parse(ui)); return renameCollectionCommon(opCtx, sourceNss, targetNss, targetUUID, cmd["dropTarget"].trueValue(), cmd["stayTemp"].trueValue()); }