diff options
author | Mickey. J Winters <mickey.winters@mongodb.com> | 2021-03-10 15:02:44 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-03-10 15:57:27 +0000 |
commit | 10fcf336a0759ef5cee54576dafb1f19e4e125b5 (patch) | |
tree | 2324a3c6776348c4be3ea6b43370cc937c11982d /src | |
parent | 3d3a8cb06e9103e7269938331daf513e9cdb4c33 (diff) | |
download | mongo-10fcf336a0759ef5cee54576dafb1f19e4e125b5.tar.gz |
SERVER-54552 [SBE] Reverse index scan may produce wrong results
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_index_scan.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/storage/index_entry_comparison.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/storage/index_entry_comparison.h | 13 |
3 files changed, 40 insertions, 14 deletions
diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp index 863a2824ed8..1eee1a968f7 100644 --- a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp +++ b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp @@ -233,15 +233,20 @@ makeIntervalsFromIndexBounds(const IndexBounds& bounds, "Generated interval [lowKey, highKey]", "lowKey"_attr = lowKey, "highKey"_attr = highKey); - // For high keys use the opposite rule as a normal seek because a forward scan should end - // after the key if inclusive, and before if exclusive. - const auto inclusive = forward != highKeyInclusive; - result.push_back({std::make_unique<KeyString::Value>( - IndexEntryComparison::makeKeyStringFromBSONKeyForSeek( - lowKey, version, ordering, forward, lowKeyInclusive)), - std::make_unique<KeyString::Value>( - IndexEntryComparison::makeKeyStringFromBSONKeyForSeek( - highKey, version, ordering, forward, inclusive))}); + // Note that 'makeKeyFromBSONKeyForSeek()' is intended to compute the "start" key for an + // index scan. The logic for computing a "discriminator" for an "end" key is reversed, which + // is why we use 'makeKeyStringFromBSONKey()' to manually specify the discriminator for the + // end key. + result.push_back( + {std::make_unique<KeyString::Value>( + IndexEntryComparison::makeKeyStringFromBSONKeyForSeek( + lowKey, version, ordering, forward, lowKeyInclusive)), + std::make_unique<KeyString::Value>(IndexEntryComparison::makeKeyStringFromBSONKey( + highKey, + version, + ordering, + forward != highKeyInclusive ? KeyString::Discriminator::kExclusiveBefore + : KeyString::Discriminator::kExclusiveAfter))}); } return result; } diff --git a/src/mongo/db/storage/index_entry_comparison.cpp b/src/mongo/db/storage/index_entry_comparison.cpp index a1b42051f15..965a4e8d796 100644 --- a/src/mongo/db/storage/index_entry_comparison.cpp +++ b/src/mongo/db/storage/index_entry_comparison.cpp @@ -167,12 +167,20 @@ KeyString::Value IndexEntryComparison::makeKeyStringFromBSONKeyForSeek(const BSO Ordering ord, bool isForward, bool inclusive) { + return makeKeyStringFromBSONKey(bsonKey, + version, + ord, + isForward == inclusive + ? KeyString::Discriminator::kExclusiveBefore + : KeyString::Discriminator::kExclusiveAfter); +} + +KeyString::Value IndexEntryComparison::makeKeyStringFromBSONKey(const BSONObj& bsonKey, + KeyString::Version version, + Ordering ord, + KeyString::Discriminator discrim) { BSONObj finalKey = BSONObj::stripFieldNames(bsonKey); - KeyString::Builder builder(version, - finalKey, - ord, - isForward == inclusive ? KeyString::Discriminator::kExclusiveBefore - : KeyString::Discriminator::kExclusiveAfter); + KeyString::Builder builder(version, finalKey, ord, discrim); return builder.getValueCopy(); } diff --git a/src/mongo/db/storage/index_entry_comparison.h b/src/mongo/db/storage/index_entry_comparison.h index 6a1574c7360..767385283cf 100644 --- a/src/mongo/db/storage/index_entry_comparison.h +++ b/src/mongo/db/storage/index_entry_comparison.h @@ -257,6 +257,19 @@ public: bool isForward, bool inclusive); + /** + * Encodes the BSON Key into a KeyString object to pass in to SortedDataInterface::seek() + * or SortedDataInterface::setEndPosition(). + * + * This funcition is similar to IndexEntryComparison::makeKeyStringFromBSONKeyForSeek() + * but allows you to pick your own KeyString::Discriminator based on wether or not the + * resulting KeyString is for the start key or end key of a seek. + */ + static KeyString::Value makeKeyStringFromBSONKey(const BSONObj& bsonKey, + KeyString::Version version, + Ordering ord, + KeyString::Discriminator discrim); + private: // Ordering is used in comparison() to compare BSONElements const Ordering _order; |