From fc9b2eab13efc7b63e69595d54a5663e17913b8a Mon Sep 17 00:00:00 2001 From: Hana Pearlman Date: Thu, 27 Jan 2022 01:33:54 +0000 Subject: SERVER-63000: createPredicatesOnBucketLevelField with $in should be treated like $or --- src/mongo/db/exec/bucket_unpacker.cpp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/mongo/db/exec') diff --git a/src/mongo/db/exec/bucket_unpacker.cpp b/src/mongo/db/exec/bucket_unpacker.cpp index 2627b680e3c..50e2063257b 100644 --- a/src/mongo/db/exec/bucket_unpacker.cpp +++ b/src/mongo/db/exec/bucket_unpacker.cpp @@ -559,19 +559,36 @@ std::unique_ptr BucketSpec::createPredicatesOnBucketLevelField( policy, matchExpr, "can't handle {$eq: null} predicate (inside $in predicate)"); auto result = std::make_unique(); + + bool alwaysTrue = false; for (auto&& elem : inExpr->getEqualities()) { // If inExpr is {$in: [X, Y]} then the elems are '0: X' and '1: Y'. auto eq = std::make_unique( inExpr->path(), elem, nullptr /*annotation*/, inExpr->getCollator()); - result->add(createComparisonPredicate(eq.get(), - bucketSpec, - bucketMaxSpanSeconds, - collationMatchesDefault, - pExpCtx, - haveComputedMetaField, - assumeNoMixedSchemaData, - policy)); + auto child = createComparisonPredicate(eq.get(), + bucketSpec, + bucketMaxSpanSeconds, + collationMatchesDefault, + pExpCtx, + haveComputedMetaField, + assumeNoMixedSchemaData, + policy); + + // As with OR, only add the child if it has been succesfully translated, otherwise the + // $in cannot be correctly mapped to bucket level fields and we should return nullptr. + if (child) { + result->add(std::move(child)); + } else { + alwaysTrue = true; + if (policy == IneligiblePredicatePolicy::kIgnore) + break; + } } + if (alwaysTrue) + return nullptr; + + // As above, no special case for an empty IN: returning nullptr would be incorrect because + // it means 'always-true', here. return result; } return handleIneligible(policy, matchExpr, "can't handle this predicate"); -- cgit v1.2.1