SERVER-112352 Change to use ExtensionCallbackNoop in UpdateCmdShape (#45168)

GitOrigin-RevId: bf6f25f5874258dc19fdd229a7537ee337289a96
This commit is contained in:
Chi-I Huang 2025-12-15 13:28:37 -08:00 committed by MongoDB Bot
parent 9ec406e405
commit 06390f0c4d
3 changed files with 61 additions and 13 deletions

View File

@ -12,8 +12,6 @@
// requires_profiling, // requires_profiling,
// # Uses $where operation. // # Uses $where operation.
// requires_scripting, // requires_scripting,
// # TODO SERVER-112352 Re-parse error when using $where in an update
// known_query_shape_computation_problem,
// ] // ]
// We turn off gossiping the mongo shell's clusterTime because it causes the slow command log // We turn off gossiping the mongo shell's clusterTime because it causes the slow command log

View File

@ -32,6 +32,7 @@
#include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonelement.h"
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonobjbuilder.h" #include "mongo/bson/bsonobjbuilder.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/expression_context_builder.h" #include "mongo/db/pipeline/expression_context_builder.h"
#include "mongo/db/query/query_shape/let_shape_component.h" #include "mongo/db/query/query_shape/let_shape_component.h"
#include "mongo/db/query/query_shape/serialization_options.h" #include "mongo/db/query/query_shape/serialization_options.h"
@ -228,9 +229,7 @@ void UpdateCmdShape::appendCmdSpecificShapeComponents(BSONObjBuilder& bob,
} }
auto parsedUpdate = uassertStatusOK(parsed_update_command::parse( auto parsedUpdate = uassertStatusOK(parsed_update_command::parse(
expCtx, expCtx, &updateRequest, makeExtensionsCallback<ExtensionsCallbackNoop>()));
&updateRequest,
makeExtensionsCallback<ExtensionsCallbackReal>(opCtx, &updateRequest.getNsString())));
UpdateCmdShapeComponents{parsedUpdate, _components.let, opts}.appendTo(bob, opts, expCtx); UpdateCmdShapeComponents{parsedUpdate, _components.let, opts}.appendTo(bob, opts, expCtx);
} }

View File

@ -30,6 +30,7 @@
#include "mongo/db/query/query_shape/update_cmd_shape.h" #include "mongo/db/query/query_shape/update_cmd_shape.h"
#include "mongo/bson/json.h" #include "mongo/bson/json.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/pipeline/expression_context_for_test.h" #include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/query_shape/let_shape_component.h" #include "mongo/db/query/query_shape/let_shape_component.h"
#include "mongo/db/query/query_shape/update_cmd_builder.h" #include "mongo/db/query/query_shape/update_cmd_builder.h"
@ -53,11 +54,15 @@ public:
_expCtx = make_intrusive<ExpressionContextForTest>(); _expCtx = make_intrusive<ExpressionContextForTest>();
} }
std::vector<UpdateCmdShape> makeShapesFromUpdate(StringData updateCmd) { std::vector<UpdateCmdShape> makeShapesFromUpdate(BSONObj updateCmd) {
auto updateRequest = UpdateCommandRequest::parseOwned(fromjson(updateCmd)); auto updateRequest = UpdateCommandRequest::parseOwned(std::move(updateCmd));
return makeShapesFromUpdateRequest(updateRequest); return makeShapesFromUpdateRequest(updateRequest);
} }
std::vector<UpdateCmdShape> makeShapesFromUpdate(StringData updateCmd) {
return makeShapesFromUpdate(fromjson(updateCmd));
}
std::vector<UpdateCmdShape> makeShapesFromUpdateRequest( std::vector<UpdateCmdShape> makeShapesFromUpdateRequest(
const write_ops::UpdateCommandRequest& updateRequest) { const write_ops::UpdateCommandRequest& updateRequest) {
std::vector<UpdateCmdShape> shapes; std::vector<UpdateCmdShape> shapes;
@ -71,17 +76,16 @@ public:
_expCtx = makeBlankExpressionContext( _expCtx = makeBlankExpressionContext(
_operationContext.get(), updateRequest.getNamespace(), updateRequest.getLet()); _operationContext.get(), updateRequest.getNamespace(), updateRequest.getLet());
auto parsedUpdate = uassertStatusOK( auto parsedUpdate = uassertStatusOK(parsed_update_command::parse(
parsed_update_command::parse(_expCtx, _expCtx, &request, makeExtensionsCallback<ExtensionsCallbackNoop>()));
&request,
makeExtensionsCallback<ExtensionsCallbackReal>(
_operationContext.get(), &request.getNsString())));
shapes.emplace_back(updateRequest, parsedUpdate, _expCtx); shapes.emplace_back(updateRequest, parsedUpdate, _expCtx);
} }
return shapes; return shapes;
} }
UpdateCmdShape makeOneShapeFromUpdate(StringData updateCmd) { template <typename T>
requires std::is_same_v<T, StringData> || std::is_same_v<T, BSONObj>
UpdateCmdShape makeOneShapeFromUpdate(T updateCmd) {
auto shapes = makeShapesFromUpdate(updateCmd); auto shapes = makeShapesFromUpdate(updateCmd);
ASSERT_EQ(shapes.size(), 1); ASSERT_EQ(shapes.size(), 1);
return shapes.front(); return shapes.front();
@ -1536,6 +1540,53 @@ TEST_F(UpdateCmdShapeTest, PipelineUpdateWithStageAliasesShape) {
SerializationContext::stateDefault())); SerializationContext::stateDefault()));
} }
TEST_F(UpdateCmdShapeTest, WhereUpdateShape) {
auto cmd = BSON(
"update" << "testColl" << "updates"
<< BSON_ARRAY(BSON(
"q" << BSON("$where" << BSONCode("function(){ sleep(1000); return true;}"))
<< "u" << BSON("$set" << BSON("item" << "ABC123"))))
<< "$db" << "testDB");
auto shape = makeOneShapeFromUpdate(cmd);
ASSERT_BSONOBJ_EQ( // NOLINT
BSON("cmdNs" << BSON("db" << "testDB" << "coll" << "testColl") << "command" << "update"
<< "q" << BSON("$where" << BSONCode("return ?;")) << "u"
<< BSON("$set" << BSON("item" << "?")) << "multi" << false << "upsert"
<< false),
shape.toBson(_operationContext.get(),
SerializationOptions::kRepresentativeQueryShapeSerializeOptions,
SerializationContext::stateDefault()));
ASSERT_BSONOBJ_EQ_AUTO( // NOLINT
R"({
cmdNs: {
db: "testDB",
coll: "testColl"
},
command: "update",
q: { $where: "?javascript" },
u: { $set: { item: "?string" } },
multi: false,
upsert: false })",
shape.toBson(_operationContext.get(),
SerializationOptions::kDebugQueryShapeSerializeOptions,
SerializationContext::stateDefault()));
ASSERT_BSONOBJ_EQ_AUTO( // NOLINT
R"({
cmdNs: {
db: "HASH<testDB>",
coll: "HASH<testColl>"
},
command: "update",
q: { $where: "?javascript" },
u: { $set: { "HASH<item>": "?string" } },
multi: false,
upsert: false })",
shape.toBson(_operationContext.get(),
SerializationOptions::kDebugShapeAndMarkIdentifiers_FOR_TEST,
SerializationContext::stateDefault()));
}
TEST_F(UpdateCmdShapeTest, BatchReplacementUpdateShape) { TEST_F(UpdateCmdShapeTest, BatchReplacementUpdateShape) {
auto shapes = makeShapesFromUpdate(R"({ auto shapes = makeShapesFromUpdate(R"({
update: "testColl", update: "testColl",