summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/sbe_stage_builder_filter.cpp
diff options
context:
space:
mode:
authorMindaugas Malinauskas <mindaugas.malinauskas@mongodb.com>2021-06-29 17:55:00 +0100
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-07-20 10:37:07 +0000
commit23e56121a014719f0dd29d27a60a72a0e11dac10 (patch)
treef8ba7f2741ad051f9745544409e83554bb51af3d /src/mongo/db/query/sbe_stage_builder_filter.cpp
parenta3b9fc2924e1b5be041716038ba81759a667a5a3 (diff)
downloadmongo-23e56121a014719f0dd29d27a60a72a0e11dac10.tar.gz
SERVER-57321 Make $mod match expression handle NaN, Infinity and large values
Diffstat (limited to 'src/mongo/db/query/sbe_stage_builder_filter.cpp')
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp49
1 files changed, 31 insertions, 18 deletions
diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp
index f58ee002164..1beac3ae456 100644
--- a/src/mongo/db/query/sbe_stage_builder_filter.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp
@@ -1644,25 +1644,38 @@ public:
// The mod function returns the result of the mod operation between the operand and
// given divisor, so construct an expression to then compare the result of the operation
// to the given remainder.
- auto makePredicate = [expr](sbe::value::SlotId inputSlot,
- EvalStage inputStage) -> EvalExprStagePair {
+ auto makePredicate = [expr, context = _context](sbe::value::SlotId inputSlot,
+ EvalStage inputStage) -> EvalExprStagePair {
+ auto frameId = context->state.frameId();
+ sbe::EVariable dividend{inputSlot};
+ sbe::EVariable dividendConvertedToNumberInt64{frameId, 0};
auto truncatedArgument = sbe::makeE<sbe::ENumericConvert>(
- sbe::makeE<sbe::EFunction>("trunc",
- sbe::makeEs(sbe::makeE<sbe::EVariable>(inputSlot))),
- sbe::value::TypeTags::NumberInt64);
-
- return {makeFillEmptyFalse(makeBinaryOp(
- sbe::EPrimBinary::eq,
- sbe::makeE<sbe::EFunction>(
- "mod",
- sbe::makeEs(std::move(truncatedArgument),
- sbe::makeE<sbe::EConstant>(
- sbe::value::TypeTags::NumberInt64,
- sbe::value::bitcastFrom<int64_t>(expr->getDivisor())))),
- sbe::makeE<sbe::EConstant>(
- sbe::value::TypeTags::NumberInt64,
- sbe::value::bitcastFrom<int64_t>(expr->getRemainder())))),
- std::move(inputStage)};
+ makeFunction("trunc"_sd, dividend.clone()), sbe::value::TypeTags::NumberInt64);
+ auto modExpression = buildMultiBranchConditional(
+ CaseValuePair{
+ generateNullOrMissing(dividendConvertedToNumberInt64),
+ sbe::makeE<sbe::EFail>(ErrorCodes::Error{5732102},
+ "cannot represent dividend as a 64-bit integer"_sd)},
+ makeFillEmptyFalse(makeBinaryOp(
+ sbe::EPrimBinary::eq,
+ makeFunction(
+ "mod"_sd,
+ dividendConvertedToNumberInt64.clone(),
+ makeConstant(sbe::value::TypeTags::NumberInt64,
+ sbe::value::bitcastFrom<int64_t>(expr->getDivisor()))),
+ makeConstant(sbe::value::TypeTags::NumberInt64,
+ sbe::value::bitcastFrom<int64_t>(expr->getRemainder())))));
+ return {
+ makeBinaryOp(sbe::EPrimBinary::logicAnd,
+ makeNot(makeBinaryOp(sbe::EPrimBinary::logicOr,
+ generateNonNumericCheck(dividend),
+ makeBinaryOp(sbe::EPrimBinary::logicOr,
+ generateNaNCheck(dividend),
+ generateInfinityCheck(dividend)))),
+ sbe::makeE<sbe::ELocalBind>(frameId,
+ sbe::makeEs(std::move(truncatedArgument)),
+ std::move(modExpression))),
+ std::move(inputStage)};
};
generatePredicate(_context,