From 2f08571855761cfa81b442d63a15736fc5c4707c Mon Sep 17 00:00:00 2001 From: Will Buerger Date: Tue, 14 Feb 2023 19:30:59 +0000 Subject: SERVER-73673: Query shape (literal redaction) for leftover non-leaf MatchExpressions, pt. 1 --- src/mongo/db/matcher/expression_always_boolean.h | 7 +++++-- src/mongo/db/matcher/expression_array.cpp | 7 ++++--- src/mongo/db/matcher/expression_tree.cpp | 1 - src/mongo/db/query/query_shape_test.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/mongo/db/matcher/expression_always_boolean.h b/src/mongo/db/matcher/expression_always_boolean.h index 901203f9eff..054b9b417ca 100644 --- a/src/mongo/db/matcher/expression_always_boolean.h +++ b/src/mongo/db/matcher/expression_always_boolean.h @@ -63,8 +63,11 @@ public: } void serialize(BSONObjBuilder* out, SerializationOptions opts) const final { - // TODO support 'opts.redactFieldNames.' - out->append(name(), 1); + if (opts.replacementForLiteralArgs) { + out->append(name(), *opts.replacementForLiteralArgs); + } else { + out->append(name(), 1); + } } bool equivalent(const MatchExpression* other) const final { diff --git a/src/mongo/db/matcher/expression_array.cpp b/src/mongo/db/matcher/expression_array.cpp index 6ed79d1de5e..5f69a1211de 100644 --- a/src/mongo/db/matcher/expression_array.cpp +++ b/src/mongo/db/matcher/expression_array.cpp @@ -105,8 +105,9 @@ void ElemMatchObjectMatchExpression::debugString(StringBuilder& debug, int inden BSONObj ElemMatchObjectMatchExpression::getSerializedRightHandSide( boost::optional replacementForLiteralArgs) const { - // TODO SERVER-73673 respect and test 'replacementForLiteralArgs'. - return BSON("$elemMatch" << _sub->serialize()); + SerializationOptions opts; + opts.replacementForLiteralArgs = replacementForLiteralArgs; + return BSON("$elemMatch" << _sub->serialize(opts)); } MatchExpression::ExpressionOptimizerFunc ElemMatchObjectMatchExpression::getOptimizer() const { @@ -178,10 +179,10 @@ BSONObj ElemMatchValueMatchExpression::getSerializedRightHandSide( boost::optional replacementForLiteralArgs) const { BSONObjBuilder emBob; - // TODO SERVER-73673 respect and test 'replacementForLiteralArgs'. for (auto&& child : _subs) { SerializationOptions opts; opts.includePath = false; + opts.replacementForLiteralArgs = replacementForLiteralArgs; child->serialize(&emBob, opts); } diff --git a/src/mongo/db/matcher/expression_tree.cpp b/src/mongo/db/matcher/expression_tree.cpp index c2778acb271..2f3f376931b 100644 --- a/src/mongo/db/matcher/expression_tree.cpp +++ b/src/mongo/db/matcher/expression_tree.cpp @@ -350,7 +350,6 @@ void AndMatchExpression::serialize(BSONObjBuilder* out, SerializationOptions opt return; } - // TODO SERVER-73673 this looks correct - just need to test. BSONArrayBuilder arrBob(out->subarrayStart("$and")); _listToBSON(&arrBob, opts); arrBob.doneFast(); diff --git a/src/mongo/db/query/query_shape_test.cpp b/src/mongo/db/query/query_shape_test.cpp index 5ee00a416dd..47c5e2bdea6 100644 --- a/src/mongo/db/query/query_shape_test.cpp +++ b/src/mongo/db/query/query_shape_test.cpp @@ -98,6 +98,30 @@ TEST(QueryPredicateShape, BitTestOperators) { assertShapeIs("{a: {$bitsAnyClear: 50}}", "{a: {$bitsAnyClear: '?'}}"); } +TEST(QueryPredicateShape, AlwaysBoolean) { + assertShapeIs("{$alwaysTrue: 1}", "{$alwaysTrue: '?'}"); + assertShapeIs("{$alwaysFalse: 1}", "{$alwaysFalse: '?'}"); +} + +TEST(QueryPredicateShape, And) { + assertShapeIs("{$and: [{a: {$lt: 5}}, {b: {$gte: 3}}, {c: {$lte: 10}}]}", + "{$and: [{a: {$lt: '?'}}, {b: {$gte: '?'}}, {c: {$lte: '?'}}]}"); +} + +TEST(QueryPredicateShape, Or) { + assertShapeIs("{$or: [{a: 5}, {b: {$in: [1,2,3]}}, {c: {$gt: 10}}]}", + "{$or: [{a: {$eq: '?'}}, {b: {$in: ['?']}}, {c: {$gt: '?'}}]}"); +} + +TEST(QueryPredicateShape, ElemMatch) { + // ElemMatchObjectMatchExpression + assertShapeIs("{a: {$elemMatch: {b: 5, c: {$exists: true}}}}", + "{a: {$elemMatch: {$and: [{b: {$eq: '?'}}, {c: {$exists: '?'}}]}}}"); + + // ElemMatchValueMatchExpression + assertShapeIs("{a: {$elemMatch: {$gt: 5, $lt: 10}}}", "{a: {$elemMatch: {$gt: '?', $lt:'?'}}}"); +} + BSONObj queryShapeForOptimizedExprExpression(std::string exprPredicateJson) { ParsedMatchExpressionForTest expr(exprPredicateJson); // We need to optimize an $expr expression in order to generate an $_internalExprEq. It's not -- cgit v1.2.1